diff options
Diffstat (limited to 'drivers/staging/vt6656')
77 files changed, 33816 insertions, 0 deletions
diff --git a/drivers/staging/vt6656/80211hdr.h b/drivers/staging/vt6656/80211hdr.h new file mode 100644 index 00000000..000304ff --- /dev/null +++ b/drivers/staging/vt6656/80211hdr.h @@ -0,0 +1,324 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: 80211hdr.h + * + * Purpose: 802.11 MAC headers related pre-defines and macros. + * + * Author: Lyndon Chen + * + * Date: Apr 8, 2002 + */ + +#ifndef __80211HDR_H__ +#define __80211HDR_H__ + +/* bit type */ +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +/* 802.11 frame related, defined as 802.11 spec */ +#define WLAN_ADDR_LEN 6 +#define WLAN_CRC_LEN 4 +#define WLAN_CRC32_LEN 4 +#define WLAN_FCS_LEN 4 +#define WLAN_BSSID_LEN 6 +#define WLAN_BSS_TS_LEN 8 +#define WLAN_HDR_ADDR2_LEN 16 +#define WLAN_HDR_ADDR3_LEN 24 +#define WLAN_HDR_ADDR4_LEN 30 +#define WLAN_IEHDR_LEN 2 +#define WLAN_SSID_MAXLEN 32 +#define WLAN_RATES_MAXLEN 16 +#define WLAN_RATES_MAXLEN_11B 4 +#define WLAN_RSN_MAXLEN 32 +#define WLAN_DATA_MAXLEN 2312 +#define WLAN_A3FR_MAXLEN (WLAN_HDR_ADDR3_LEN \ + + WLAN_DATA_MAXLEN \ + + WLAN_CRC_LEN) + +#define WLAN_BEACON_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_ADDR3_LEN + 0) +#define WLAN_NULLDATA_FR_MAXLEN (WLAN_HDR_ADDR3_LEN + 0) +#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_ADDR3_LEN + 2) +#define WLAN_ASSOCREQ_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_ASSOCRESP_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_REASSOCREQ_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_REASSOCRESP_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_PROBEREQ_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_PROBERESP_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_AUTHEN_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_ADDR3_LEN + 2) + +#define WLAN_WEP_NKEYS 4 +#define WLAN_WEP40_KEYLEN 5 +#define WLAN_WEP104_KEYLEN 13 +#define WLAN_WEP232_KEYLEN 29 +#define WLAN_WEPMAX_KEYLEN 32 +#define WLAN_CHALLENGE_IE_MAXLEN 255 +#define WLAN_CHALLENGE_IE_LEN 130 +#define WLAN_CHALLENGE_LEN 128 +#define WLAN_WEP_IV_LEN 4 +#define WLAN_WEP_ICV_LEN 4 +#define WLAN_FRAGS_MAX 16 + +/* Frame Type */ +#define WLAN_TYPE_MGR 0x00 +#define WLAN_TYPE_CTL 0x01 +#define WLAN_TYPE_DATA 0x02 + +#define WLAN_FTYPE_MGMT 0x00 +#define WLAN_FTYPE_CTL 0x01 +#define WLAN_FTYPE_DATA 0x02 + +/* Frame Subtypes */ +#define WLAN_FSTYPE_ASSOCREQ 0x00 +#define WLAN_FSTYPE_ASSOCRESP 0x01 +#define WLAN_FSTYPE_REASSOCREQ 0x02 +#define WLAN_FSTYPE_REASSOCRESP 0x03 +#define WLAN_FSTYPE_PROBEREQ 0x04 +#define WLAN_FSTYPE_PROBERESP 0x05 +#define WLAN_FSTYPE_BEACON 0x08 +#define WLAN_FSTYPE_ATIM 0x09 +#define WLAN_FSTYPE_DISASSOC 0x0a +#define WLAN_FSTYPE_AUTHEN 0x0b +#define WLAN_FSTYPE_DEAUTHEN 0x0c +#define WLAN_FSTYPE_ACTION 0x0d + +/* Control */ +#define WLAN_FSTYPE_PSPOLL 0x0a +#define WLAN_FSTYPE_RTS 0x0b +#define WLAN_FSTYPE_CTS 0x0c +#define WLAN_FSTYPE_ACK 0x0d +#define WLAN_FSTYPE_CFEND 0x0e +#define WLAN_FSTYPE_CFENDCFACK 0x0f + +/* Data */ +#define WLAN_FSTYPE_DATAONLY 0x00 +#define WLAN_FSTYPE_DATA_CFACK 0x01 +#define WLAN_FSTYPE_DATA_CFPOLL 0x02 +#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03 +#define WLAN_FSTYPE_NULL 0x04 +#define WLAN_FSTYPE_CFACK 0x05 +#define WLAN_FSTYPE_CFPOLL 0x06 +#define WLAN_FSTYPE_CFACK_CFPOLL 0x07 + +#ifdef __BIG_ENDIAN + +/* GET & SET Frame Control bit */ +#define WLAN_GET_FC_PRVER(n) ((((u16)(n) >> 8) & (BIT0 | BIT1)) +#define WLAN_GET_FC_FTYPE(n) ((((u16)(n) >> 8) & (BIT2 | BIT3)) >> 2) +#define WLAN_GET_FC_FSTYPE(n) ((((u16)(n) >> 8) \ + & (BIT4|BIT5|BIT6|BIT7)) >> 4) +#define WLAN_GET_FC_TODS(n) ((((u16)(n) << 8) & (BIT8)) >> 8) +#define WLAN_GET_FC_FROMDS(n) ((((u16)(n) << 8) & (BIT9)) >> 9) +#define WLAN_GET_FC_MOREFRAG(n) ((((u16)(n) << 8) & (BIT10)) >> 10) +#define WLAN_GET_FC_RETRY(n) ((((u16)(n) << 8) & (BIT11)) >> 11) +#define WLAN_GET_FC_PWRMGT(n) ((((u16)(n) << 8) & (BIT12)) >> 12) +#define WLAN_GET_FC_MOREDATA(n) ((((u16)(n) << 8) & (BIT13)) >> 13) +#define WLAN_GET_FC_ISWEP(n) ((((u16)(n) << 8) & (BIT14)) >> 14) +#define WLAN_GET_FC_ORDER(n) ((((u16)(n) << 8) & (BIT15)) >> 15) + +/* Sequence Field bit */ +#define WLAN_GET_SEQ_FRGNUM(n) (((u16)(n) >> 8) & (BIT0|BIT1|BIT2|BIT3)) +#define WLAN_GET_SEQ_SEQNUM(n) ((((u16)(n) >> 8) \ + & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) + +/* Capability Field bit */ +#define WLAN_GET_CAP_INFO_ESS(n) (((n) >> 8) & BIT0) +#define WLAN_GET_CAP_INFO_IBSS(n) ((((n) >> 8) & BIT1) >> 1) +#define WLAN_GET_CAP_INFO_CFPOLLABLE(n) ((((n) >> 8) & BIT2) >> 2) +#define WLAN_GET_CAP_INFO_CFPOLLREQ(n) ((((n) >> 8) & BIT3) >> 3) +#define WLAN_GET_CAP_INFO_PRIVACY(n) ((((n) >> 8) & BIT4) >> 4) +#define WLAN_GET_CAP_INFO_SHORTPREAMBLE(n) ((((n) >> 8) & BIT5) >> 5) +#define WLAN_GET_CAP_INFO_PBCC(n) ((((n) >> 8) & BIT6) >> 6) +#define WLAN_GET_CAP_INFO_AGILITY(n) ((((n) >> 8) & BIT7) >> 7) +#define WLAN_GET_CAP_INFO_SPECTRUMMNG(n) ((((n)) & BIT8) >> 10) +#define WLAN_GET_CAP_INFO_SHORTSLOTTIME(n) ((((n)) & BIT10) >> 10) +#define WLAN_GET_CAP_INFO_DSSSOFDM(n) ((((n)) & BIT13) >> 13) +#define WLAN_GET_CAP_INFO_GRPACK(n) ((((n)) & BIT14) >> 14) + +#else + +/* GET & SET Frame Control bit */ +#define WLAN_GET_FC_PRVER(n) (((u16)(n)) & (BIT0 | BIT1)) +#define WLAN_GET_FC_FTYPE(n) ((((u16)(n)) & (BIT2 | BIT3)) >> 2) +#define WLAN_GET_FC_FSTYPE(n) ((((u16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4) +#define WLAN_GET_FC_TODS(n) ((((u16)(n)) & (BIT8)) >> 8) +#define WLAN_GET_FC_FROMDS(n) ((((u16)(n)) & (BIT9)) >> 9) +#define WLAN_GET_FC_MOREFRAG(n) ((((u16)(n)) & (BIT10)) >> 10) +#define WLAN_GET_FC_RETRY(n) ((((u16)(n)) & (BIT11)) >> 11) +#define WLAN_GET_FC_PWRMGT(n) ((((u16)(n)) & (BIT12)) >> 12) +#define WLAN_GET_FC_MOREDATA(n) ((((u16)(n)) & (BIT13)) >> 13) +#define WLAN_GET_FC_ISWEP(n) ((((u16)(n)) & (BIT14)) >> 14) +#define WLAN_GET_FC_ORDER(n) ((((u16)(n)) & (BIT15)) >> 15) + +/* Sequence Field bit */ +#define WLAN_GET_SEQ_FRGNUM(n) (((u16)(n)) & (BIT0|BIT1|BIT2|BIT3)) +#define WLAN_GET_SEQ_SEQNUM(n) ((((u16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) + +/* Capability Field bit */ +#define WLAN_GET_CAP_INFO_ESS(n) ((n) & BIT0) +#define WLAN_GET_CAP_INFO_IBSS(n) (((n) & BIT1) >> 1) +#define WLAN_GET_CAP_INFO_CFPOLLABLE(n) (((n) & BIT2) >> 2) +#define WLAN_GET_CAP_INFO_CFPOLLREQ(n) (((n) & BIT3) >> 3) +#define WLAN_GET_CAP_INFO_PRIVACY(n) (((n) & BIT4) >> 4) +#define WLAN_GET_CAP_INFO_SHORTPREAMBLE(n) (((n) & BIT5) >> 5) +#define WLAN_GET_CAP_INFO_PBCC(n) (((n) & BIT6) >> 6) +#define WLAN_GET_CAP_INFO_AGILITY(n) (((n) & BIT7) >> 7) +#define WLAN_GET_CAP_INFO_SPECTRUMMNG(n) (((n) & BIT8) >> 10) +#define WLAN_GET_CAP_INFO_SHORTSLOTTIME(n) (((n) & BIT10) >> 10) +#define WLAN_GET_CAP_INFO_DSSSOFDM(n) (((n) & BIT13) >> 13) +#define WLAN_GET_CAP_INFO_GRPACK(n) (((n) & BIT14) >> 14) + +#endif /* #ifdef __BIG_ENDIAN */ + +#define WLAN_SET_CAP_INFO_ESS(n) (n) +#define WLAN_SET_CAP_INFO_IBSS(n) ((n) << 1) +#define WLAN_SET_CAP_INFO_CFPOLLABLE(n) ((n) << 2) +#define WLAN_SET_CAP_INFO_CFPOLLREQ(n) ((n) << 3) +#define WLAN_SET_CAP_INFO_PRIVACY(n) ((n) << 4) +#define WLAN_SET_CAP_INFO_SHORTPREAMBLE(n) ((n) << 5) +#define WLAN_SET_CAP_INFO_SPECTRUMMNG(n) ((n) << 8) +#define WLAN_SET_CAP_INFO_PBCC(n) ((n) << 6) +#define WLAN_SET_CAP_INFO_AGILITY(n) ((n) << 7) +#define WLAN_SET_CAP_INFO_SHORTSLOTTIME(n) ((n) << 10) +#define WLAN_SET_CAP_INFO_DSSSOFDM(n) ((n) << 13) +#define WLAN_SET_CAP_INFO_GRPACK(n) ((n) << 14) + +#define WLAN_SET_FC_PRVER(n) ((u16)(n)) +#define WLAN_SET_FC_FTYPE(n) (((u16)(n)) << 2) +#define WLAN_SET_FC_FSTYPE(n) (((u16)(n)) << 4) +#define WLAN_SET_FC_TODS(n) (((u16)(n)) << 8) +#define WLAN_SET_FC_FROMDS(n) (((u16)(n)) << 9) +#define WLAN_SET_FC_MOREFRAG(n) (((u16)(n)) << 10) +#define WLAN_SET_FC_RETRY(n) (((u16)(n)) << 11) +#define WLAN_SET_FC_PWRMGT(n) (((u16)(n)) << 12) +#define WLAN_SET_FC_MOREDATA(n) (((u16)(n)) << 13) +#define WLAN_SET_FC_ISWEP(n) (((u16)(n)) << 14) +#define WLAN_SET_FC_ORDER(n) (((u16)(n)) << 15) + +#define WLAN_SET_SEQ_FRGNUM(n) ((u16)(n)) +#define WLAN_SET_SEQ_SEQNUM(n) (((u16)(n)) << 4) + +/* ERP Field bit */ + +#define WLAN_GET_ERP_NONERP_PRESENT(n) ((n) & BIT0) +#define WLAN_GET_ERP_USE_PROTECTION(n) (((n) & BIT1) >> 1) +#define WLAN_GET_ERP_BARKER_MODE(n) (((n) & BIT2) >> 2) + +#define WLAN_SET_ERP_NONERP_PRESENT(n) (n) +#define WLAN_SET_ERP_USE_PROTECTION(n) ((n) << 1) +#define WLAN_SET_ERP_BARKER_MODE(n) ((n) << 2) + +/* Support & Basic Rates field */ +#define WLAN_MGMT_IS_BASICRATE(b) ((b) & BIT7) +#define WLAN_MGMT_GET_RATE(b) ((b) & ~BIT7) + +/* TIM field */ +#define WLAN_MGMT_IS_MULTICAST_TIM(b) ((b) & BIT0) +#define WLAN_MGMT_GET_TIM_OFFSET(b) (((b) & ~BIT0) >> 1) + +/* 3-Addr & 4-Addr */ +#define WLAN_HDR_A3_DATA_PTR(p) (((u8 *)(p)) + WLAN_HDR_ADDR3_LEN) +#define WLAN_HDR_A4_DATA_PTR(p) (((u8 *)(p)) + WLAN_HDR_ADDR4_LEN) + +/* IEEE ADDR */ +#define IEEE_ADDR_UNIVERSAL 0x02 +#define IEEE_ADDR_GROUP 0x01 + +typedef struct { + u8 abyAddr[6]; +} IEEE_ADDR, *PIEEE_ADDR; + +/* 802.11 Header Format */ + +typedef struct tagWLAN_80211HDR_A2 { + + u16 wFrameCtl; + u16 wDurationID; + u8 abyAddr1[WLAN_ADDR_LEN]; + u8 abyAddr2[WLAN_ADDR_LEN]; + +} __attribute__ ((__packed__)) +WLAN_80211HDR_A2, *PWLAN_80211HDR_A2; + +typedef struct tagWLAN_80211HDR_A3 { + + u16 wFrameCtl; + u16 wDurationID; + u8 abyAddr1[WLAN_ADDR_LEN]; + u8 abyAddr2[WLAN_ADDR_LEN]; + u8 abyAddr3[WLAN_ADDR_LEN]; + u16 wSeqCtl; + +} __attribute__ ((__packed__)) +WLAN_80211HDR_A3, *PWLAN_80211HDR_A3; + +typedef struct tagWLAN_80211HDR_A4 { + + u16 wFrameCtl; + u16 wDurationID; + u8 abyAddr1[WLAN_ADDR_LEN]; + u8 abyAddr2[WLAN_ADDR_LEN]; + u8 abyAddr3[WLAN_ADDR_LEN]; + u16 wSeqCtl; + u8 abyAddr4[WLAN_ADDR_LEN]; + +} __attribute__ ((__packed__)) +WLAN_80211HDR_A4, *PWLAN_80211HDR_A4; + +typedef union tagUWLAN_80211HDR { + + WLAN_80211HDR_A2 sA2; + WLAN_80211HDR_A3 sA3; + WLAN_80211HDR_A4 sA4; + +} UWLAN_80211HDR, *PUWLAN_80211HDR; + +#endif /* __80211HDR_H__ */ diff --git a/drivers/staging/vt6656/80211mgr.c b/drivers/staging/vt6656/80211mgr.c new file mode 100644 index 00000000..61edb51f --- /dev/null +++ b/drivers/staging/vt6656/80211mgr.c @@ -0,0 +1,861 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: 80211mgr.c + * + * Purpose: Handles the 802.11 management support functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + * Functions: + * vMgrEncodeBeacon - Encode the Beacon frame + * vMgrDecodeBeacon - Decode the Beacon frame + * vMgrEncodeDisassociation - Encode the Disassociation frame + * vMgrDecodeDisassociation - Decode the Disassociation frame + * vMgrEncodeAssocRequest - Encode the Association request frame + * vMgrDecodeAssocRequest - Decode the Association request frame + * vMgrEncodeAssocResponse - Encode the Association response frame + * vMgrDecodeAssocResponse - Decode the Association response frame + * vMgrEncodeReAssocRequest - Encode the ReAssociation request frame + * vMgrDecodeReAssocRequest - Decode the ReAssociation request frame + * vMgrEncodeProbeRequest - Encode the Probe request frame + * vMgrDecodeProbeRequest - Decode the Probe request frame + * vMgrEncodeProbeResponse - Encode the Probe response frame + * vMgrDecodeProbeResponse - Decode the Probe response frame + * vMgrEncodeAuthen - Encode the Authentication frame + * vMgrDecodeAuthen - Decode the Authentication frame + * vMgrEncodeDeauthen - Encode the DeAuthentication frame + * vMgrDecodeDeauthen - Decode the DeAuthentication frame + * vMgrEncodeReassocResponse - Encode the Reassociation response frame + * + * Revision History: + * + */ + +#include "device.h" +#include "tmacro.h" +#include "tether.h" +#include "80211mgr.h" +#include "80211hdr.h" +#include "wpa.h" + +static int msglevel = MSG_LEVEL_INFO; +/*static int msglevel =MSG_LEVEL_DEBUG;*/ + +/*+ + * + * Routine Description: + * Encode Beacon frame body offset + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeBeacon( + PWLAN_FR_BEACON pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pqwTimestamp = + (u64 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_TS); + pFrame->pwBeaconInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_BCN_INT); + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_CAPINFO); + + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_BEACON_OFF_SSID; + + return; +} + +/*+ + * + * Routine Description: + * Decode Beacon frame body offset + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeBeacon( + PWLAN_FR_BEACON pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pqwTimestamp = + (u64 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_TS); + pFrame->pwBeaconInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_BCN_INT); + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_CAPINFO); + + /* Information elements */ + pItem = (PWLAN_IE)((u8 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))) + + WLAN_BEACON_OFF_SSID); + while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) { + + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + case WLAN_EID_FH_PARMS: + /* pFrame->pFHParms = (PWLAN_IE_FH_PARMS)pItem; */ + break; + case WLAN_EID_DS_PARMS: + if (pFrame->pDSParms == NULL) + pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem; + break; + case WLAN_EID_CF_PARMS: + if (pFrame->pCFParms == NULL) + pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem; + break; + case WLAN_EID_IBSS_PARMS: + if (pFrame->pIBSSParms == NULL) + pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem; + break; + case WLAN_EID_TIM: + if (pFrame->pTIM == NULL) + pFrame->pTIM = (PWLAN_IE_TIM)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + + case WLAN_EID_ERP: + if (pFrame->pERP == NULL) + pFrame->pERP = (PWLAN_IE_ERP)pItem; + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_COUNTRY: /* 7 */ + if (pFrame->pIE_Country == NULL) + pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem; + break; + + case WLAN_EID_PWR_CONSTRAINT: /* 32 */ + if (pFrame->pIE_PowerConstraint == NULL) + pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem; + break; + + case WLAN_EID_CH_SWITCH: /* 37 */ + if (pFrame->pIE_CHSW == NULL) + pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem; + break; + + case WLAN_EID_QUIET: /* 40 */ + if (pFrame->pIE_Quiet == NULL) + pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem; + break; + + case WLAN_EID_IBSS_DFS: + if (pFrame->pIE_IBSSDFS == NULL) + pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem; + break; + + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in beacon decode.\n", pItem->byElementID); + break; + + } + pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len); + } +} + +/*+ + * + * Routine Description: + * Encode Disassociation + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeDisassociation( + PWLAN_FR_DISASSOC pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwReason = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_DISASSOC_OFF_REASON); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DISASSOC_OFF_REASON + sizeof(*(pFrame->pwReason)); +} + +/*+ + * + * Routine Description: + * Decode Disassociation + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeDisassociation( + PWLAN_FR_DISASSOC pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwReason = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_DISASSOC_OFF_REASON); +} + +/*+ + * + * Routine Description: + * Encode Association Request + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeAssocRequest( + PWLAN_FR_ASSOCREQ pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + /* Fixed Fields */ + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_CAP_INFO); + pFrame->pwListenInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_LISTEN_INT); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCREQ_OFF_LISTEN_INT + sizeof(*(pFrame->pwListenInterval)); +} + +/*+ + * + * Routine Description: (AP) + * Decode Association Request + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeAssocRequest( + PWLAN_FR_ASSOCREQ pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + /* Fixed Fields */ + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_CAP_INFO); + pFrame->pwListenInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_LISTEN_INT); + + /* Information elements */ + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_SSID); + + while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) { + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in assocreq decode.\n", + pItem->byElementID); + break; + } + pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len); + } +} + +/*+ + * + * Routine Description: (AP) + * Encode Association Response + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeAssocResponse( + PWLAN_FR_ASSOCRESP pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_CAP_INFO); + pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_STATUS); + pFrame->pwAid = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_AID); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCRESP_OFF_AID + + sizeof(*(pFrame->pwAid)); +} + +/*+ + * + * Routine Description: + * Decode Association Response + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeAssocResponse( + PWLAN_FR_ASSOCRESP pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_CAP_INFO); + pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_STATUS); + pFrame->pwAid = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_AID); + + /* Information elements */ + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_SUPP_RATES); + + pItem = (PWLAN_IE)(pFrame->pSuppRates); + pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len); + + if ((((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pFrame->pExtSuppRates=[%p].\n", pItem); + } else + pFrame->pExtSuppRates = NULL; +} + +/*+ + * + * Routine Description: + * Encode Reassociation Request + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeReassocRequest( + PWLAN_FR_REASSOCREQ pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_CAP_INFO); + pFrame->pwListenInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_LISTEN_INT); + pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_CURR_AP); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCREQ_OFF_CURR_AP + sizeof(*(pFrame->pAddrCurrAP)); +} + +/*+ + * + * Routine Description: (AP) + * Decode Reassociation Request + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeReassocRequest( + PWLAN_FR_REASSOCREQ pFrame + ) +{ + PWLAN_IE pItem; + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_CAP_INFO); + pFrame->pwListenInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_LISTEN_INT); + pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_CURR_AP); + + /* Information elements */ + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_SSID); + + while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) { + + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + break; + + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in reassocreq decode.\n", + pItem->byElementID); + break; + } + pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len); + } +} + +/*+ + * + * Routine Description: + * Encode Probe Request + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeProbeRequest( + PWLAN_FR_PROBEREQ pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + pFrame->len = WLAN_HDR_ADDR3_LEN; +} + +/*+ + * + * Routine Description: + * Decode Probe Request + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeProbeRequest( + PWLAN_FR_PROBEREQ pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Information elements */ + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))); + + while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) { + + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in probereq\n", pItem->byElementID); + break; + } + + pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len); + } +} + +/*+ + * + * Routine Description: + * Encode Probe Response + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeProbeResponse( + PWLAN_FR_PROBERESP pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pqwTimestamp = + (u64 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_TS); + pFrame->pwBeaconInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_BCN_INT); + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_CAP_INFO); + + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_PROBERESP_OFF_CAP_INFO + + sizeof(*(pFrame->pwCapInfo)); +} + +/*+ + * + * Routine Description: + * Decode Probe Response + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeProbeResponse( + PWLAN_FR_PROBERESP pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pqwTimestamp = + (u64 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_TS); + pFrame->pwBeaconInterval = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_BCN_INT); + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_CAP_INFO); + + /* Information elements */ + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_SSID); + + while (((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) { + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + case WLAN_EID_FH_PARMS: + break; + case WLAN_EID_DS_PARMS: + if (pFrame->pDSParms == NULL) + pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem; + break; + case WLAN_EID_CF_PARMS: + if (pFrame->pCFParms == NULL) + pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem; + break; + case WLAN_EID_IBSS_PARMS: + if (pFrame->pIBSSParms == NULL) + pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == true) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + case WLAN_EID_ERP: + if (pFrame->pERP == NULL) + pFrame->pERP = (PWLAN_IE_ERP)pItem; + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_COUNTRY: /* 7 */ + if (pFrame->pIE_Country == NULL) + pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem; + break; + + case WLAN_EID_PWR_CONSTRAINT: /* 32 */ + if (pFrame->pIE_PowerConstraint == NULL) + pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem; + break; + + case WLAN_EID_CH_SWITCH: /* 37 */ + if (pFrame->pIE_CHSW == NULL) + pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem; + break; + + case WLAN_EID_QUIET: /* 40 */ + if (pFrame->pIE_Quiet == NULL) + pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem; + break; + + case WLAN_EID_IBSS_DFS: + if (pFrame->pIE_IBSSDFS == NULL) + pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem; + break; + + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in proberesp\n", pItem->byElementID); + break; + } + + pItem = (PWLAN_IE)(((u8 *)pItem) + 2 + pItem->len); + } +} + +/*+ + * + * Routine Description: + * Encode Authentication frame + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeAuthen( + PWLAN_FR_AUTHEN pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwAuthAlgorithm = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_AUTH_ALG); + pFrame->pwAuthSequence = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_AUTH_SEQ); + pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_STATUS); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_AUTHEN_OFF_STATUS + sizeof(*(pFrame->pwStatus)); +} + +/*+ + * + * Routine Description: + * Decode Authentication + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeAuthen( + PWLAN_FR_AUTHEN pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwAuthAlgorithm = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_AUTH_ALG); + pFrame->pwAuthSequence = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_AUTH_SEQ); + pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_STATUS); + + /* Information elements */ + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_CHALLENGE); + + if ((((u8 *)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) + pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem; +} + +/*+ + * + * Routine Description: + * Encode Authentication + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeDeauthen( + PWLAN_FR_DEAUTHEN pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwReason = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_DEAUTHEN_OFF_REASON); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DEAUTHEN_OFF_REASON + sizeof(*(pFrame->pwReason)); +} + +/*+ + * + * Routine Description: + * Decode Deauthentication + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrDecodeDeauthen( + PWLAN_FR_DEAUTHEN pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwReason = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_DEAUTHEN_OFF_REASON); +} + +/*+ + * + * Routine Description: (AP) + * Encode Reassociation Response + * + * + * Return Value: + * None. + * +-*/ + +void +vMgrEncodeReassocResponse( + PWLAN_FR_REASSOCRESP pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + /* Fixed Fields */ + pFrame->pwCapInfo = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_CAP_INFO); + pFrame->pwStatus = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_STATUS); + pFrame->pwAid = (u16 *)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_AID); + + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid)); +} diff --git a/drivers/staging/vt6656/80211mgr.h b/drivers/staging/vt6656/80211mgr.h new file mode 100644 index 00000000..39cde1a0 --- /dev/null +++ b/drivers/staging/vt6656/80211mgr.h @@ -0,0 +1,808 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: 80211mgr.h + * + * Purpose: 802.11 management frames pre-defines. + * + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + */ + +#ifndef __80211MGR_H__ +#define __80211MGR_H__ + +#include "80211hdr.h" + +#define WLAN_MIN_ARRAY 1 + +/* Information Element ID value */ +#define WLAN_EID_SSID 0 +#define WLAN_EID_SUPP_RATES 1 +#define WLAN_EID_FH_PARMS 2 +#define WLAN_EID_DS_PARMS 3 +#define WLAN_EID_CF_PARMS 4 +#define WLAN_EID_TIM 5 +#define WLAN_EID_IBSS_PARMS 6 +#define WLAN_EID_COUNTRY 7 +#define WLAN_EID_CHALLENGE 16 +#define WLAN_EID_PWR_CONSTRAINT 32 +#define WLAN_EID_PWR_CAPABILITY 33 +#define WLAN_EID_TPC_REQ 34 +#define WLAN_EID_TPC_REP 35 +#define WLAN_EID_SUPP_CH 36 +#define WLAN_EID_CH_SWITCH 37 +#define WLAN_EID_MEASURE_REQ 38 +#define WLAN_EID_MEASURE_REP 39 +#define WLAN_EID_QUIET 40 +#define WLAN_EID_IBSS_DFS 41 +#define WLAN_EID_ERP 42 +/* reference 802.11i 7.3.2 table 20 */ +#define WLAN_EID_RSN 48 +#define WLAN_EID_EXTSUPP_RATES 50 +/* reference WiFi WPA spec */ +#define WLAN_EID_RSN_WPA 221 + +#ifdef Cisco_ccx +#define WLAN_EID_CCX 133 +#define WLAN_EID_CCX_IP 149 +#define WLAN_EID_CCX_Ver 221 +#endif + +#define WLAN_EID_ERP_NONERP_PRESENT 0x01 +#define WLAN_EID_ERP_USE_PROTECTION 0x02 +#define WLAN_EID_ERP_BARKER_MODE 0x04 + +/* reason codes */ +#define WLAN_MGMT_REASON_RSVD 0 +#define WLAN_MGMT_REASON_UNSPEC 1 +#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID 2 +#define WLAN_MGMT_REASON_DEAUTH_LEAVING 3 +#define WLAN_MGMT_REASON_DISASSOC_INACTIVE 4 +#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY 5 +#define WLAN_MGMT_REASON_CLASS2_NONAUTH 6 +#define WLAN_MGMT_REASON_CLASS3_NONASSOC 7 +#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8 +#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH 9 +#define WLAN_MGMT_REASON_DISASSOC_PWR_CAP_UNACCEPT 10 +#define WLAN_MGMT_REASON_DISASSOC_SUPP_CH_UNACCEPT 11 +#define WLAN_MGMT_REASON_INVALID_IE 13 +#define WLAN_MGMT_REASON_MIC_FAILURE 14 +#define WLAN_MGMT_REASON_4WAY_HANDSHAKE_TIMEOUT 15 +#define WLAN_MGMT_REASON_GRPKEY_UPDATE_TIMEOUT 16 +#define WLAN_MGMT_REASON_4WAY_INFO_DIFFERENT 17 +#define WLAN_MGMT_REASON_MULTCAST_CIPHER_INVALID 18 +#define WLAN_MGMT_REASON_UNCAST_CIPHER_INVALID 19 +#define WLAN_MGMT_REASON_AKMP_INVALID 20 +#define WLAN_MGMT_REASON_RSNE_UNSUPPORTED 21 +#define WLAN_MGMT_REASON_RSNE_CAP_INVALID 22 +#define WLAN_MGMT_REASON_80211X_AUTH_FAILED 23 + +/* status codes */ +#define WLAN_MGMT_STATUS_SUCCESS 0 +#define WLAN_MGMT_STATUS_UNSPEC_FAILURE 1 +#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED 10 +#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC 11 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC 12 +#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG 13 +#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ 14 +#define WLAN_MGMT_STATUS_CHALLENGE_FAIL 15 +#define WLAN_MGMT_STATUS_AUTH_TIMEOUT 16 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY 17 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES 18 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_SHORTPREAMBLE 19 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_PBCC 20 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_AGILITY 21 + +/* reference 802.11h 7.3.1.9 */ +#define WLAN_MGMT_STATUS_ASSOC_REJECT_BCS_SPECTRUM_MNG 22 +#define WLAN_MGMT_STATUS_ASSOC_REJECT_BCS_PWR_CAP 23 +#define WLAN_MGMT_STATUS_ASSOC_REJECT_BCS_SUPP_CH 24 + +/* reference 802.11g 7.3.1.9 */ +#define WLAN_MGMT_STATUS_SHORTSLOTTIME_UNSUPPORTED 25 +#define WLAN_MGMT_STATUS_DSSSOFDM_UNSUPPORTED 26 + +/* reference 802.11i 7.3.1.9 table 19 */ +#define WLAN_MGMT_STATUS_INVALID_IE 40 +#define WLAN_MGMT_STATUS_GROUP_CIPHER_INVALID 41 +#define WLAN_MGMT_STATUS_PAIRWISE_CIPHER_INVALID 42 +#define WLAN_MGMT_STATUS_AKMP_INVALID 43 +#define WLAN_MGMT_STATUS_UNSUPPORT_RSN_IE_VER 44 +#define WLAN_MGMT_STATUS_INVALID_RSN_IE_CAP 45 +#define WLAN_MGMT_STATUS_CIPHER_REJECT 46 + +/* auth algorithm */ +#define WLAN_AUTH_ALG_OPENSYSTEM 0 +#define WLAN_AUTH_ALG_SHAREDKEY 1 + +/* management frame field offsets */ + +/* + * Note: Not all fields are listed because of variable lengths + * Note: These offsets are from the start of the frame data + */ + +#define WLAN_BEACON_OFF_TS 0 +#define WLAN_BEACON_OFF_BCN_INT 8 +#define WLAN_BEACON_OFF_CAPINFO 10 +#define WLAN_BEACON_OFF_SSID 12 + +#define WLAN_DISASSOC_OFF_REASON 0 + +#define WLAN_ASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_ASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_ASSOCREQ_OFF_SSID 4 + +#define WLAN_ASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_ASSOCRESP_OFF_STATUS 2 +#define WLAN_ASSOCRESP_OFF_AID 4 +#define WLAN_ASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_REASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_REASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_REASSOCREQ_OFF_CURR_AP 4 +#define WLAN_REASSOCREQ_OFF_SSID 10 + +#define WLAN_REASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_REASSOCRESP_OFF_STATUS 2 +#define WLAN_REASSOCRESP_OFF_AID 4 +#define WLAN_REASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_PROBEREQ_OFF_SSID 0 + +#define WLAN_PROBERESP_OFF_TS 0 +#define WLAN_PROBERESP_OFF_BCN_INT 8 +#define WLAN_PROBERESP_OFF_CAP_INFO 10 +#define WLAN_PROBERESP_OFF_SSID 12 + +#define WLAN_AUTHEN_OFF_AUTH_ALG 0 +#define WLAN_AUTHEN_OFF_AUTH_SEQ 2 +#define WLAN_AUTHEN_OFF_STATUS 4 +#define WLAN_AUTHEN_OFF_CHALLENGE 6 + +#define WLAN_DEAUTHEN_OFF_REASON 0 + +/* cipher suite selectors defined in 802.11i */ +#define WLAN_11i_CSS_USE_GROUP 0 +#define WLAN_11i_CSS_WEP40 1 +#define WLAN_11i_CSS_TKIP 2 +#define WLAN_11i_CSS_CCMP 4 +#define WLAN_11i_CSS_WEP104 5 +#define WLAN_11i_CSS_UNKNOWN 255 + +/* authentication and key management suite selectors defined in 802.11i */ +#define WLAN_11i_AKMSS_802_1X 1 +#define WLAN_11i_AKMSS_PSK 2 +#define WLAN_11i_AKMSS_UNKNOWN 255 + +/* measurement type definitions reference IEEE 802.11h table 20b */ +#define MEASURE_TYPE_BASIC 0 +#define MEASURE_TYPE_CCA 1 +#define MEASURE_TYPE_RPI 2 + +/* measurement request mode definitions reference IEEE 802.11h figure 46h */ +#define MEASURE_MODE_ENABLE 0x02 +#define MEASURE_MODE_REQ 0x04 +#define MEASURE_MODE_REP 0x08 + +/* measurement report mode definitions reference IEEE 802.11h figure 46m */ +#define MEASURE_MODE_LATE 0x01 +#define MEASURE_MODE_INCAPABLE 0x02 +#define MEASURE_MODE_REFUSED 0x04 + +/* Information Element types */ + +#pragma pack(1) +typedef struct tagWLAN_IE { + u8 byElementID; + u8 len; +} __attribute__ ((__packed__)) +WLAN_IE, *PWLAN_IE; + +/* Service Set IDentity (SSID) */ +#pragma pack(1) +typedef struct tagWLAN_IE_SSID { + u8 byElementID; + u8 len; + u8 abySSID[1]; +} __attribute__ ((__packed__)) +WLAN_IE_SSID, *PWLAN_IE_SSID; + +/* Supported Rates */ +#pragma pack(1) +typedef struct tagWLAN_IE_SUPP_RATES { + u8 byElementID; + u8 len; + u8 abyRates[1]; +} __attribute__ ((__packed__)) +WLAN_IE_SUPP_RATES, *PWLAN_IE_SUPP_RATES; + +/* FH Parameter Set */ +#pragma pack(1) +typedef struct _WLAN_IE_FH_PARMS { + u8 byElementID; + u8 len; + u16 wDwellTime; + u8 byHopSet; + u8 byHopPattern; + u8 byHopIndex; +} WLAN_IE_FH_PARMS, *PWLAN_IE_FH_PARMS; + +/* DS Parameter Set */ +#pragma pack(1) +typedef struct tagWLAN_IE_DS_PARMS { + u8 byElementID; + u8 len; + u8 byCurrChannel; +} __attribute__ ((__packed__)) +WLAN_IE_DS_PARMS, *PWLAN_IE_DS_PARMS; + +/* CF Parameter Set */ +#pragma pack(1) +typedef struct tagWLAN_IE_CF_PARMS { + u8 byElementID; + u8 len; + u8 byCFPCount; + u8 byCFPPeriod; + u16 wCFPMaxDuration; + u16 wCFPDurRemaining; +} __attribute__ ((__packed__)) +WLAN_IE_CF_PARMS, *PWLAN_IE_CF_PARMS; + +/* TIM */ +#pragma pack(1) +typedef struct tagWLAN_IE_TIM { + u8 byElementID; + u8 len; + u8 byDTIMCount; + u8 byDTIMPeriod; + u8 byBitMapCtl; + u8 byVirtBitMap[1]; +} __attribute__ ((__packed__)) +WLAN_IE_TIM, *PWLAN_IE_TIM; + +/* IBSS Parameter Set */ +#pragma pack(1) +typedef struct tagWLAN_IE_IBSS_PARMS { + u8 byElementID; + u8 len; + u16 wATIMWindow; +} __attribute__ ((__packed__)) +WLAN_IE_IBSS_PARMS, *PWLAN_IE_IBSS_PARMS; + +/* Challenge Text */ +#pragma pack(1) +typedef struct tagWLAN_IE_CHALLENGE { + u8 byElementID; + u8 len; + u8 abyChallenge[1]; +} __attribute__ ((__packed__)) +WLAN_IE_CHALLENGE, *PWLAN_IE_CHALLENGE; + +#pragma pack(1) +typedef struct tagWLAN_IE_RSN_EXT { + u8 byElementID; + u8 len; + u8 abyOUI[4]; + u16 wVersion; + u8 abyMulticast[4]; + u16 wPKCount; + struct { + u8 abyOUI[4]; + } PKSList[1]; + /* the rest is variable so need to overlay ieauth structure */ +} WLAN_IE_RSN_EXT, *PWLAN_IE_RSN_EXT; + +#pragma pack(1) +typedef struct tagWLAN_IE_RSN_AUTH { + u16 wAuthCount; + struct { + u8 abyOUI[4]; + } AuthKSList[1]; +} WLAN_IE_RSN_AUTH, *PWLAN_IE_RSN_AUTH; + +/* RSN Identity */ +#pragma pack(1) +typedef struct tagWLAN_IE_RSN { + u8 byElementID; + u8 len; + u16 wVersion; + u8 abyRSN[WLAN_MIN_ARRAY]; +} WLAN_IE_RSN, *PWLAN_IE_RSN; + +/* CCX Identity DavidWang */ +#pragma pack(1) +typedef struct tagWLAN_IE_CCX { +u8 byElementID; +u8 len; +u8 abyCCX[30]; +} WLAN_IE_CCX, *PWLAN_IE_CCX; +#pragma pack(1) +typedef struct tagWLAN_IE_CCX_IP { +u8 byElementID; +u8 len; +u8 abyCCXOUI[4]; +u8 abyCCXIP[4]; +u8 abyCCXREV[2]; +} WLAN_IE_CCX_IP, *PWLAN_IE_CCX_IP; +#pragma pack(1) +typedef struct tagWLAN_IE_CCX_Ver { +u8 byElementID; +u8 len; +u8 abyCCXVer[5]; +} WLAN_IE_CCX_Ver, *PWLAN_IE_CCX_Ver; + +/* ERP */ +#pragma pack(1) +typedef struct tagWLAN_IE_ERP { + u8 byElementID; + u8 len; + u8 byContext; +} __attribute__ ((__packed__)) +WLAN_IE_ERP, *PWLAN_IE_ERP; + +#pragma pack(1) +typedef struct _MEASEURE_REQ { + u8 byChannel; + u8 abyStartTime[8]; + u8 abyDuration[2]; +} MEASEURE_REQ, *PMEASEURE_REQ, + MEASEURE_REQ_BASIC, *PMEASEURE_REQ_BASIC, + MEASEURE_REQ_CCA, *PMEASEURE_REQ_CCA, + MEASEURE_REQ_RPI, *PMEASEURE_REQ_RPI; + +typedef struct _MEASEURE_REP_BASIC { + u8 byChannel; + u8 abyStartTime[8]; + u8 abyDuration[2]; + u8 byMap; +} MEASEURE_REP_BASIC, *PMEASEURE_REP_BASIC; + +typedef struct _MEASEURE_REP_CCA { + u8 byChannel; + u8 abyStartTime[8]; + u8 abyDuration[2]; + u8 byCCABusyFraction; +} MEASEURE_REP_CCA, *PMEASEURE_REP_CCA; + +typedef struct _MEASEURE_REP_RPI { + u8 byChannel; + u8 abyStartTime[8]; + u8 abyDuration[2]; + u8 abyRPIdensity[8]; +} MEASEURE_REP_RPI, *PMEASEURE_REP_RPI; + +typedef union _MEASEURE_REP { + + MEASEURE_REP_BASIC sBasic; + MEASEURE_REP_CCA sCCA; + MEASEURE_REP_RPI sRPI; + +} MEASEURE_REP, *PMEASEURE_REP; + +typedef struct _WLAN_IE_MEASURE_REQ { + u8 byElementID; + u8 len; + u8 byToken; + u8 byMode; + u8 byType; + MEASEURE_REQ sReq; +} WLAN_IE_MEASURE_REQ, *PWLAN_IE_MEASURE_REQ; + +typedef struct _WLAN_IE_MEASURE_REP { + u8 byElementID; + u8 len; + u8 byToken; + u8 byMode; + u8 byType; + MEASEURE_REP sRep; +} WLAN_IE_MEASURE_REP, *PWLAN_IE_MEASURE_REP; + +typedef struct _WLAN_IE_CH_SW { + u8 byElementID; + u8 len; + u8 byMode; + u8 byChannel; + u8 byCount; +} WLAN_IE_CH_SW, *PWLAN_IE_CH_SW; + +typedef struct _WLAN_IE_QUIET { + u8 byElementID; + u8 len; + u8 byQuietCount; + u8 byQuietPeriod; + u8 abyQuietDuration[2]; + u8 abyQuietOffset[2]; +} WLAN_IE_QUIET, *PWLAN_IE_QUIET; + +typedef struct _WLAN_IE_COUNTRY { + u8 byElementID; + u8 len; + u8 abyCountryString[3]; + u8 abyCountryInfo[3]; +} WLAN_IE_COUNTRY, *PWLAN_IE_COUNTRY; + +typedef struct _WLAN_IE_PW_CONST { + u8 byElementID; + u8 len; + u8 byPower; +} WLAN_IE_PW_CONST, *PWLAN_IE_PW_CONST; + +typedef struct _WLAN_IE_PW_CAP { + u8 byElementID; + u8 len; + u8 byMinPower; + u8 byMaxPower; +} WLAN_IE_PW_CAP, *PWLAN_IE_PW_CAP; + +typedef struct _WLAN_IE_SUPP_CH { + u8 byElementID; + u8 len; + u8 abyChannelTuple[2]; +} WLAN_IE_SUPP_CH, *PWLAN_IE_SUPP_CH; + +typedef struct _WLAN_IE_TPC_REQ { + u8 byElementID; + u8 len; +} WLAN_IE_TPC_REQ, *PWLAN_IE_TPC_REQ; + +typedef struct _WLAN_IE_TPC_REP { + u8 byElementID; + u8 len; + u8 byTxPower; + u8 byLinkMargin; +} WLAN_IE_TPC_REP, *PWLAN_IE_TPC_REP; + +typedef struct _WLAN_IE_IBSS_DFS { + u8 byElementID; + u8 len; + u8 abyDFSOwner[6]; + u8 byDFSRecovery; + u8 abyChannelMap[2]; +} WLAN_IE_IBSS_DFS, *PWLAN_IE_IBSS_DFS; + +#pragma pack() + +/* frame types */ + +/* prototype structure, all mgmt frame types will start with these members */ +typedef struct tagWLAN_FR_MGMT { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + +} WLAN_FR_MGMT, *PWLAN_FR_MGMT; + +/* beacon frame */ +typedef struct tagWLAN_FR_BEACON { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + u64 *pqwTimestamp; + u16 * pwBeaconInterval; + u16 * pwCapInfo; + /* info elements */ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; +/* PWLAN_IE_FH_PARMS pFHParms; */ + PWLAN_IE_DS_PARMS pDSParms; + PWLAN_IE_CF_PARMS pCFParms; + PWLAN_IE_TIM pTIM; + PWLAN_IE_IBSS_PARMS pIBSSParms; + PWLAN_IE_RSN pRSN; + PWLAN_IE_RSN_EXT pRSNWPA; + PWLAN_IE_ERP pERP; + PWLAN_IE_SUPP_RATES pExtSuppRates; + PWLAN_IE_COUNTRY pIE_Country; + PWLAN_IE_PW_CONST pIE_PowerConstraint; + PWLAN_IE_CH_SW pIE_CHSW; + PWLAN_IE_IBSS_DFS pIE_IBSSDFS; + PWLAN_IE_QUIET pIE_Quiet; + +} WLAN_FR_BEACON, *PWLAN_FR_BEACON; + +/* IBSS ATIM frame */ +typedef struct tagWLAN_FR_IBSSATIM { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + + /* fixed fields */ + /* info elements */ + /* this frame type has a null body */ + +} WLAN_FR_IBSSATIM, *PWLAN_FR_IBSSATIM; + +/* disassociation */ +typedef struct tagWLAN_FR_DISASSOC { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + u16 * pwReason; + /* info elements */ + +} WLAN_FR_DISASSOC, *PWLAN_FR_DISASSOC; + +/* association request */ +typedef struct tagWLAN_FR_ASSOCREQ { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + u16 * pwCapInfo; + u16 * pwListenInterval; + /* info elements */ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_RSN pRSN; + PWLAN_IE_CCX pCCX; + PWLAN_IE_CCX_IP pCCXIP; + PWLAN_IE_CCX_Ver pCCXVER; + PWLAN_IE_RSN_EXT pRSNWPA; + PWLAN_IE_SUPP_RATES pExtSuppRates; + PWLAN_IE_PW_CAP pCurrPowerCap; + PWLAN_IE_SUPP_CH pCurrSuppCh; + +} WLAN_FR_ASSOCREQ, *PWLAN_FR_ASSOCREQ; + +/* association response */ +typedef struct tagWLAN_FR_ASSOCRESP { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + u16 * pwCapInfo; + u16 * pwStatus; + u16 * pwAid; + /* info elements */ + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_SUPP_RATES pExtSuppRates; + +} WLAN_FR_ASSOCRESP, *PWLAN_FR_ASSOCRESP; + +/* reassociation request */ +typedef struct tagWLAN_FR_REASSOCREQ { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + + /* fixed fields */ + u16 * pwCapInfo; + u16 * pwListenInterval; + PIEEE_ADDR pAddrCurrAP; + + /* info elements */ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_RSN pRSN; + PWLAN_IE_CCX pCCX; + PWLAN_IE_CCX_IP pCCXIP; + PWLAN_IE_CCX_Ver pCCXVER; + PWLAN_IE_RSN_EXT pRSNWPA; + PWLAN_IE_SUPP_RATES pExtSuppRates; + +} WLAN_FR_REASSOCREQ, *PWLAN_FR_REASSOCREQ; + +/* reassociation response */ +typedef struct tagWLAN_FR_REASSOCRESP { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + u16 * pwCapInfo; + u16 * pwStatus; + u16 * pwAid; + /* info elements */ + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_SUPP_RATES pExtSuppRates; + +} WLAN_FR_REASSOCRESP, *PWLAN_FR_REASSOCRESP; + +/* probe request */ +typedef struct tagWLAN_FR_PROBEREQ { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + /* info elements */ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_SUPP_RATES pExtSuppRates; + +} WLAN_FR_PROBEREQ, *PWLAN_FR_PROBEREQ; + +/* probe response */ +typedef struct tagWLAN_FR_PROBERESP { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + u64 *pqwTimestamp; + u16 * pwBeaconInterval; + u16 * pwCapInfo; + /* info elements */ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_DS_PARMS pDSParms; + PWLAN_IE_CF_PARMS pCFParms; + PWLAN_IE_IBSS_PARMS pIBSSParms; + PWLAN_IE_RSN pRSN; + PWLAN_IE_RSN_EXT pRSNWPA; + PWLAN_IE_ERP pERP; + PWLAN_IE_SUPP_RATES pExtSuppRates; + PWLAN_IE_COUNTRY pIE_Country; + PWLAN_IE_PW_CONST pIE_PowerConstraint; + PWLAN_IE_CH_SW pIE_CHSW; + PWLAN_IE_IBSS_DFS pIE_IBSSDFS; + PWLAN_IE_QUIET pIE_Quiet; + +} WLAN_FR_PROBERESP, *PWLAN_FR_PROBERESP; + +/* authentication */ +typedef struct tagWLAN_FR_AUTHEN { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + u16 * pwAuthAlgorithm; + u16 * pwAuthSequence; + u16 * pwStatus; + /* info elements */ + PWLAN_IE_CHALLENGE pChallenge; + +} WLAN_FR_AUTHEN, *PWLAN_FR_AUTHEN; + +/* deauthentication */ +typedef struct tagWLAN_FR_DEAUTHEN { + + unsigned int uType; + unsigned int len; + u8 * pBuf; + PUWLAN_80211HDR pHdr; + /* fixed fields */ + u16 * pwReason; + + /* info elements */ + +} WLAN_FR_DEAUTHEN, *PWLAN_FR_DEAUTHEN; + +void +vMgrEncodeBeacon( + PWLAN_FR_BEACON pFrame + ); + +void +vMgrDecodeBeacon( + PWLAN_FR_BEACON pFrame + ); + +void +vMgrEncodeDisassociation( + PWLAN_FR_DISASSOC pFrame + ); + +void +vMgrDecodeDisassociation( + PWLAN_FR_DISASSOC pFrame + ); + +void +vMgrEncodeAssocRequest( + PWLAN_FR_ASSOCREQ pFrame + ); + +void +vMgrDecodeAssocRequest( + PWLAN_FR_ASSOCREQ pFrame + ); + +void +vMgrEncodeAssocResponse( + PWLAN_FR_ASSOCRESP pFrame + ); + +void +vMgrDecodeAssocResponse( + PWLAN_FR_ASSOCRESP pFrame + ); + +void +vMgrEncodeReassocRequest( + PWLAN_FR_REASSOCREQ pFrame + ); + +void +vMgrDecodeReassocRequest( + PWLAN_FR_REASSOCREQ pFrame + ); + +void +vMgrEncodeProbeRequest( + PWLAN_FR_PROBEREQ pFrame + ); + +void +vMgrDecodeProbeRequest( + PWLAN_FR_PROBEREQ pFrame + ); + +void +vMgrEncodeProbeResponse( + PWLAN_FR_PROBERESP pFrame + ); + +void +vMgrDecodeProbeResponse( + PWLAN_FR_PROBERESP pFrame + ); + +void +vMgrEncodeAuthen( + PWLAN_FR_AUTHEN pFrame + ); + +void +vMgrDecodeAuthen( + PWLAN_FR_AUTHEN pFrame + ); + +void +vMgrEncodeDeauthen( + PWLAN_FR_DEAUTHEN pFrame + ); + +void +vMgrDecodeDeauthen( + PWLAN_FR_DEAUTHEN pFrame + ); + +void +vMgrEncodeReassocResponse( + PWLAN_FR_REASSOCRESP pFrame + ); + +#endif /* __80211MGR_H__ */ diff --git a/drivers/staging/vt6656/Kconfig b/drivers/staging/vt6656/Kconfig new file mode 100644 index 00000000..f89ab205 --- /dev/null +++ b/drivers/staging/vt6656/Kconfig @@ -0,0 +1,9 @@ +config VT6656 + tristate "VIA Technologies VT6656 support" + depends on USB && WLAN && m + select WIRELESS_EXT + select WEXT_PRIV + select FW_LOADER + ---help--- + This is a vendor-written driver for VIA VT6656. + diff --git a/drivers/staging/vt6656/Makefile b/drivers/staging/vt6656/Makefile new file mode 100644 index 00000000..c9985478 --- /dev/null +++ b/drivers/staging/vt6656/Makefile @@ -0,0 +1,38 @@ +# TODO: all of these should be removed +ccflags-y := -DLINUX -D__KERNEL__ -DEXPORT_SYMTAB -D__NO_VERSION__ +ccflags-y += -DHOSTAP + +vt6656_stage-y += main_usb.o \ + card.o \ + mac.o \ + baseband.o \ + wctl.o \ + 80211mgr.o \ + wcmd.o\ + wmgr.o \ + bssdb.o \ + wpa2.o \ + rxtx.o \ + dpc.o \ + power.o \ + datarate.o \ + mib.o \ + rc4.o \ + tether.o \ + tcrc.o \ + hostap.o \ + wpa.o \ + key.o \ + tkip.o \ + michael.o \ + rf.o \ + iwctl.o \ + wpactl.o \ + aes_ccmp.o \ + usbpipe.o \ + channel.o \ + control.o \ + firmware.o \ + int.o + +obj-$(CONFIG_VT6656) += vt6656_stage.o diff --git a/drivers/staging/vt6656/TODO b/drivers/staging/vt6656/TODO new file mode 100644 index 00000000..e154b2f3 --- /dev/null +++ b/drivers/staging/vt6656/TODO @@ -0,0 +1,19 @@ +TODO: +- remove __cplusplus ifdefs -- done +- remove kernel version compatibility wrappers +- remove support for older wireless extensions +- prepare for merge with vt6655 driver: + - remove PRINT_K() macro + - split rf.c + - abstract VT3184 chipset specific code +- add common vt665x infrastructure +- kill ttype.h -- done +- switch to use LIB80211 +- switch to use MAC80211 +- use kernel coding style +- checkpatch.pl fixes +- sparse fixes +- integrate with drivers/net/wireless + +Please send any patches to Greg Kroah-Hartman <greg@kroah.com> +and Forest Bond <forest@alittletooquiet.net>. diff --git a/drivers/staging/vt6656/aes_ccmp.c b/drivers/staging/vt6656/aes_ccmp.c new file mode 100644 index 00000000..28a4c4c3 --- /dev/null +++ b/drivers/staging/vt6656/aes_ccmp.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: aes_ccmp.c + * + * Purpose: AES_CCMP decryption + * + * Author: Warren Hsu + * + * Date: Feb 15, 2005 + * + * Functions: + * AESbGenCCMP - Parsing RX-packet + * + * Revision History: + */ + +#include "device.h" +#include "80211hdr.h" + +/* + * SBOX Table + */ + +u8 sbox_table[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +u8 dot2_table[256] = { + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, + 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, + 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, + 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, + 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, + 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, + 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, + 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, + 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, + 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, + 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, + 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, + 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, + 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, + 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, + 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 +}; + +u8 dot3_table[256] = { + 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, + 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, + 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, + 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, + 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, + 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, + 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, + 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, + 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, + 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, + 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, + 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, + 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, + 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, + 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, + 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a +}; + +static void xor_128(u8 *a, u8 *b, u8 *out) +{ + u32 * dwPtrA = (u32 *) a; + u32 * dwPtrB = (u32 *) b; + u32 * dwPtrOut = (u32 *) out; + + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); +} + +static void xor_32(u8 *a, u8 *b, u8 *out) +{ + u32 * dwPtrA = (u32 *) a; + u32 * dwPtrB = (u32 *) b; + u32 * dwPtrOut = (u32 *) out; + + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); +} + +void AddRoundKey(u8 *key, int round) +{ + u8 sbox_key[4]; + u8 rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; + + sbox_key[0] = sbox_table[key[13]]; + sbox_key[1] = sbox_table[key[14]]; + sbox_key[2] = sbox_table[key[15]]; + sbox_key[3] = sbox_table[key[12]]; + + key[0] = key[0] ^ rcon_table[round]; + xor_32(&key[0], sbox_key, &key[0]); + + xor_32(&key[4], &key[0], &key[4]); + xor_32(&key[8], &key[4], &key[8]); + xor_32(&key[12], &key[8], &key[12]); +} + +void SubBytes(u8 *in, u8 *out) +{ + int i; + + for (i = 0; i < 16; i++) + out[i] = sbox_table[in[i]]; +} + +void ShiftRows(u8 *in, u8 *out) +{ + out[0] = in[0]; + out[1] = in[5]; + out[2] = in[10]; + out[3] = in[15]; + out[4] = in[4]; + out[5] = in[9]; + out[6] = in[14]; + out[7] = in[3]; + out[8] = in[8]; + out[9] = in[13]; + out[10] = in[2]; + out[11] = in[7]; + out[12] = in[12]; + out[13] = in[1]; + out[14] = in[6]; + out[15] = in[11]; +} + +void MixColumns(u8 *in, u8 *out) +{ + + out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3]; + out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3]; + out[2] = in[0] ^ in[1] ^ dot2_table[in[2]] ^ dot3_table[in[3]]; + out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]]; +} + +void AESv128(u8 *key, u8 *data, u8 *ciphertext) +{ + int i; + int round; + u8 TmpdataA[16]; + u8 TmpdataB[16]; + u8 abyRoundKey[16]; + + for (i = 0; i < 16; i++) + abyRoundKey[i] = key[i]; + + for (round = 0; round < 11; round++) { + if (round == 0) { + xor_128(abyRoundKey, data, ciphertext); + AddRoundKey(abyRoundKey, round); + } else if (round == 10) { + SubBytes(ciphertext, TmpdataA); + ShiftRows(TmpdataA, TmpdataB); + xor_128(TmpdataB, abyRoundKey, ciphertext); + } else { /* round 1 ~ 9 */ + SubBytes(ciphertext, TmpdataA); + ShiftRows(TmpdataA, TmpdataB); + MixColumns(&TmpdataB[0], &TmpdataA[0]); + MixColumns(&TmpdataB[4], &TmpdataA[4]); + MixColumns(&TmpdataB[8], &TmpdataA[8]); + MixColumns(&TmpdataB[12], &TmpdataA[12]); + xor_128(TmpdataA, abyRoundKey, ciphertext); + AddRoundKey(abyRoundKey, round); + } + } + +} + +/* + * Description: AES decryption + * + * Parameters: + * In: + * pbyRxKey - The key used to decrypt + * pbyFrame - Starting address of packet header + * wFrameSize - Total packet size including CRC + * Out: + * none + * + * Return Value: MIC compare result + * + */ + +bool AESbGenCCMP(u8 * pbyRxKey, u8 * pbyFrame, u16 wFrameSize) +{ + u8 abyNonce[13]; + u8 MIC_IV[16]; + u8 MIC_HDR1[16]; + u8 MIC_HDR2[16]; + u8 abyMIC[16]; + u8 abyCTRPLD[16]; + u8 abyTmp[16]; + u8 abyPlainText[16]; + u8 abyLastCipher[16]; + + struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *) pbyFrame; + u8 * pbyIV; + u8 * pbyPayload; + u16 wHLen = 22; + /* 8 is IV, 8 is MIC, 4 is CRC */ + u16 wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN; + bool bA4 = false; + u8 byTmp; + u16 wCnt; + int ii, jj, kk; + + pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; + if (WLAN_GET_FC_TODS(*(u16 *) pbyFrame) && + WLAN_GET_FC_FROMDS(*(u16 *) pbyFrame)) { + bA4 = true; + pbyIV += 6; /* 6 is 802.11 address4 */ + wHLen += 6; + wPayloadSize -= 6; + } + pbyPayload = pbyIV + 8; /* IV-length */ + + abyNonce[0] = 0x00; /* now is 0, if Qos here will be priority */ + memcpy(&(abyNonce[1]), pMACHeader->addr2, ETH_ALEN); + abyNonce[7] = pbyIV[7]; + abyNonce[8] = pbyIV[6]; + abyNonce[9] = pbyIV[5]; + abyNonce[10] = pbyIV[4]; + abyNonce[11] = pbyIV[1]; + abyNonce[12] = pbyIV[0]; + + /* MIC_IV */ + MIC_IV[0] = 0x59; + memcpy(&(MIC_IV[1]), &(abyNonce[0]), 13); + MIC_IV[14] = (u8)(wPayloadSize >> 8); + MIC_IV[15] = (u8)(wPayloadSize & 0xff); + + /* MIC_HDR1 */ + MIC_HDR1[0] = (u8)(wHLen >> 8); + MIC_HDR1[1] = (u8)(wHLen & 0xff); + byTmp = (u8)(pMACHeader->frame_control & 0xff); + MIC_HDR1[2] = byTmp & 0x8f; + byTmp = (u8)(pMACHeader->frame_control >> 8); + byTmp &= 0x87; + MIC_HDR1[3] = byTmp | 0x40; + memcpy(&(MIC_HDR1[4]), pMACHeader->addr1, ETH_ALEN); + memcpy(&(MIC_HDR1[10]), pMACHeader->addr2, ETH_ALEN); + + /* MIC_HDR2 */ + memcpy(&(MIC_HDR2[0]), pMACHeader->addr3, ETH_ALEN); + byTmp = (u8)(pMACHeader->seq_ctrl & 0xff); + MIC_HDR2[6] = byTmp & 0x0f; + MIC_HDR2[7] = 0; + + if (bA4) { + memcpy(&(MIC_HDR2[8]), pMACHeader->addr4, ETH_ALEN); + } else { + MIC_HDR2[8] = 0x00; + MIC_HDR2[9] = 0x00; + MIC_HDR2[10] = 0x00; + MIC_HDR2[11] = 0x00; + MIC_HDR2[12] = 0x00; + MIC_HDR2[13] = 0x00; + } + MIC_HDR2[14] = 0x00; + MIC_HDR2[15] = 0x00; + + /* CCMP */ + AESv128(pbyRxKey, MIC_IV, abyMIC); + for (kk = 0; kk < 16; kk++) + abyTmp[kk] = MIC_HDR1[kk] ^ abyMIC[kk]; + + AESv128(pbyRxKey, abyTmp, abyMIC); + for (kk = 0; kk < 16; kk++) + abyTmp[kk] = MIC_HDR2[kk] ^ abyMIC[kk]; + + AESv128(pbyRxKey, abyTmp, abyMIC); + + wCnt = 1; + abyCTRPLD[0] = 0x01; + memcpy(&(abyCTRPLD[1]), &(abyNonce[0]), 13); + + for (jj = wPayloadSize; jj > 16; jj = jj-16) { + + abyCTRPLD[14] = (u8) (wCnt >> 8); + abyCTRPLD[15] = (u8) (wCnt & 0xff); + + AESv128(pbyRxKey, abyCTRPLD, abyTmp); + + for (kk = 0; kk < 16; kk++) + abyPlainText[kk] = abyTmp[kk] ^ pbyPayload[kk]; + + for (kk = 0; kk < 16; kk++) + abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk]; + + AESv128(pbyRxKey, abyTmp, abyMIC); + + memcpy(pbyPayload, abyPlainText, 16); + wCnt++; + pbyPayload += 16; + } /* for wPayloadSize */ + + /* last payload */ + memcpy(&(abyLastCipher[0]), pbyPayload, jj); + for (ii = jj; ii < 16; ii++) + abyLastCipher[ii] = 0x00; + + abyCTRPLD[14] = (u8) (wCnt >> 8); + abyCTRPLD[15] = (u8) (wCnt & 0xff); + + AESv128(pbyRxKey, abyCTRPLD, abyTmp); + for (kk = 0; kk < 16; kk++) + abyPlainText[kk] = abyTmp[kk] ^ abyLastCipher[kk]; + + memcpy(pbyPayload, abyPlainText, jj); + pbyPayload += jj; + + /* for MIC calculation */ + for (ii = jj; ii < 16; ii++) + abyPlainText[ii] = 0x00; + for (kk = 0; kk < 16; kk++) + abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk]; + + AESv128(pbyRxKey, abyTmp, abyMIC); + + /* => above is the calculated MIC */ + + wCnt = 0; + abyCTRPLD[14] = (u8) (wCnt >> 8); + abyCTRPLD[15] = (u8) (wCnt & 0xff); + AESv128(pbyRxKey, abyCTRPLD, abyTmp); + + for (kk = 0; kk < 8; kk++) + abyTmp[kk] = abyTmp[kk] ^ pbyPayload[kk]; + + /* => above is the packet dec-MIC */ + + if (!memcmp(abyMIC, abyTmp, 8)) + return true; + else + return false; +} diff --git a/drivers/staging/vt6656/aes_ccmp.h b/drivers/staging/vt6656/aes_ccmp.h new file mode 100644 index 00000000..ed6a9ae3 --- /dev/null +++ b/drivers/staging/vt6656/aes_ccmp.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: aes_ccmp.h + * + * Purpose: AES_CCMP Decryption + * + * Author: Warren Hsu + * + * Date: Feb 15, 2005 + * + */ + +#ifndef __AES_H__ +#define __AES_H__ + +bool AESbGenCCMP(u8 * pbyRxKey, u8 * pbyFrame, u16 wFrameSize); + +#endif /* __AES_CCMP_H__ */ diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c new file mode 100644 index 00000000..55185336 --- /dev/null +++ b/drivers/staging/vt6656/baseband.c @@ -0,0 +1,1901 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: baseband.c + * + * Purpose: Implement functions to access baseband + * + * Author: Jerry Chen + * + * Date: Jun. 5, 2002 + * + * Functions: + * BBuGetFrameTime - Calculate data frame transmitting time + * BBvCalculateParameter - Calculate PhyLength, PhyService and Phy Signal parameter for baseband Tx + * BBbVT3184Init - VIA VT3184 baseband chip init code + * + * Revision History: + * + * + */ + +#include "tmacro.h" +#include "tether.h" +#include "mac.h" +#include "baseband.h" +#include "rf.h" +#include "srom.h" +#include "control.h" +#include "datarate.h" +#include "rndis.h" + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +u8 abyVT3184_AGC[] = { + 0x00, //0 + 0x00, //1 + 0x02, //2 + 0x02, //3 //RobertYu:20060505, 0x04, //3 + 0x04, //4 + 0x04, //5 //RobertYu:20060505, 0x06, //5 + 0x06, //6 + 0x06, //7 + 0x08, //8 + 0x08, //9 + 0x0A, //A + 0x0A, //B + 0x0C, //C + 0x0C, //D + 0x0E, //E + 0x0E, //F + 0x10, //10 + 0x10, //11 + 0x12, //12 + 0x12, //13 + 0x14, //14 + 0x14, //15 + 0x16, //16 + 0x16, //17 + 0x18, //18 + 0x18, //19 + 0x1A, //1A + 0x1A, //1B + 0x1C, //1C + 0x1C, //1D + 0x1E, //1E + 0x1E, //1F + 0x20, //20 + 0x20, //21 + 0x22, //22 + 0x22, //23 + 0x24, //24 + 0x24, //25 + 0x26, //26 + 0x26, //27 + 0x28, //28 + 0x28, //29 + 0x2A, //2A + 0x2A, //2B + 0x2C, //2C + 0x2C, //2D + 0x2E, //2E + 0x2E, //2F + 0x30, //30 + 0x30, //31 + 0x32, //32 + 0x32, //33 + 0x34, //34 + 0x34, //35 + 0x36, //36 + 0x36, //37 + 0x38, //38 + 0x38, //39 + 0x3A, //3A + 0x3A, //3B + 0x3C, //3C + 0x3C, //3D + 0x3E, //3E + 0x3E //3F +}; + +u8 abyVT3184_AL2230[] = { + 0x31,//00 + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x70, + 0x45,//tx //0x64 for FPGA + 0x2A, + 0x76, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00,//10 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x8e, //RobertYu:20060522, //0x8d, + 0x0a, //RobertYu:20060515, //0x09, + 0x00, + 0x00, + 0x00, + 0x00,//20 + 0x00, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x0c, //RobertYu:20060522, //0x10, + 0x26,//30 + 0x5b, + 0x00, + 0x00, + 0x00, + 0x00, + 0xaa, + 0xaa, + 0xff, + 0xff, + 0x79, + 0x00, + 0x00, + 0x0b, + 0x48, + 0x04, + 0x00,//40 + 0x08, + 0x00, + 0x08, + 0x08, + 0x14, + 0x05, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x09, + 0x73, + 0x00, + 0xc5, + 0x00,//50 //RobertYu:20060505, //0x15,//50 + 0x19, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, //RobertYu:20060505, //0xb0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe4,//60 + 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x98, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //0x80 for FPGA + 0x03, + 0x01, + 0x00, + 0x00,//70 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x8c,//80 + 0x01, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x1f, //RobertYu:20060516, //0x0f, + 0xb7, + 0x88, + 0x47, + 0xaa, + 0x00, //RobertYu:20060505, //0x02, + 0x20,//90 //RobertYu:20060505, //0x22,//90 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xeb, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00,//a0 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x15, //RobertYu:20060516, //0x00, + 0x00, + 0x18, + 0x38,//b0 + 0x30, + 0x00, + 0x00, + 0xff, + 0x0f, + 0xe4, + 0xe2, + 0x00, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x00, + 0x18,//c0 + 0x20, + 0x07, + 0x18, + 0xff, + 0xff, //RobertYu:20060509, //0x2c, + 0x0e, //RobertYu:20060530, //0x0c, + 0x0a, + 0x0e, + 0x00, //RobertYu:20060505, //0x01, + 0x82, //RobertYu:20060516, //0x8f, + 0xa7, + 0x3c, + 0x10, + 0x30, //RobertYu:20060627, //0x0b, + 0x05, //RobertYu:20060516, //0x25, + 0x40,//d0 + 0x12, + 0x00, + 0x00, + 0x10, + 0x28, + 0x80, + 0x2A, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00,//e0 + 0xf3, //RobertYu:20060516, //0xd3, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x12, //RobertYu:20060627, //0x10, + 0x00, + 0xf4, + 0x00, + 0xff, + 0x79, + 0x20, + 0x30, + 0x05, //RobertYu:20060516, //0x0c, + 0x00,//f0 + 0x3e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +//{{RobertYu:20060515, new BB setting for VT3226D0 +u8 abyVT3184_VT3226D0[] = { + 0x31,//00 + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x70, + 0x45,//tx //0x64 for FPGA + 0x2A, + 0x76, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00,//10 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x8e, //RobertYu:20060525, //0x8d, + 0x0a, //RobertYu:20060515, //0x09, + 0x00, + 0x00, + 0x00, + 0x00,//20 + 0x00, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x0c, //RobertYu:20060525, //0x10, + 0x26,//30 + 0x5b, + 0x00, + 0x00, + 0x00, + 0x00, + 0xaa, + 0xaa, + 0xff, + 0xff, + 0x79, + 0x00, + 0x00, + 0x0b, + 0x48, + 0x04, + 0x00,//40 + 0x08, + 0x00, + 0x08, + 0x08, + 0x14, + 0x05, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x09, + 0x73, + 0x00, + 0xc5, + 0x00,//50 //RobertYu:20060505, //0x15,//50 + 0x19, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, //RobertYu:20060505, //0xb0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe4,//60 + 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x98, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //0x80 for FPGA + 0x03, + 0x01, + 0x00, + 0x00,//70 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x8c,//80 + 0x01, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x1f, //RobertYu:20060515, //0x0f, + 0xb7, + 0x88, + 0x47, + 0xaa, + 0x00, //RobertYu:20060505, //0x02, + 0x20,//90 //RobertYu:20060505, //0x22,//90 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xeb, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00,//a0 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x38,//b0 + 0x30, + 0x00, + 0x00, + 0xff, + 0x0f, + 0xe4, + 0xe2, + 0x00, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x00, + 0x18,//c0 + 0x20, + 0x07, + 0x18, + 0xff, + 0xff, //RobertYu:20060509, //0x2c, + 0x10, //RobertYu:20060525, //0x0c, + 0x0a, + 0x0e, + 0x00, //RobertYu:20060505, //0x01, + 0x84, //RobertYu:20060525, //0x8f, + 0xa7, + 0x3c, + 0x10, + 0x24, //RobertYu:20060627, //0x18, + 0x05, //RobertYu:20060515, //0x25, + 0x40,//d0 + 0x12, + 0x00, + 0x00, + 0x10, + 0x28, + 0x80, + 0x2A, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00,//e0 + 0xf3, //RobertYu:20060515, //0xd3, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x10, //RobertYu:20060627, //0x0e, + 0x00, + 0xf4, + 0x00, + 0xff, + 0x79, + 0x20, + 0x30, + 0x08, //RobertYu:20060515, //0x0c, + 0x00,//f0 + 0x3e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +}; + +const u16 awcFrameTime[MAX_RATE] = +{10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216}; + +/* +static +unsigned long +s_ulGetLowSQ3(PSDevice pDevice); + +static +unsigned long +s_ulGetRatio(PSDevice pDevice); + +static +void +s_vClearSQ3Value(PSDevice pDevice); +*/ + +/* + * Description: Calculate data frame transmitting time + * + * Parameters: + * In: + * byPreambleType - Preamble Type + * byPktType - PK_TYPE_11A, PK_TYPE_11B, PK_TYPE_11GB, PK_TYPE_11GA + * cbFrameLength - Baseband Type + * wRate - Tx Rate + * Out: + * + * Return Value: FrameTime + * + */ +unsigned int +BBuGetFrameTime( + u8 byPreambleType, + u8 byPktType, + unsigned int cbFrameLength, + u16 wRate + ) +{ + unsigned int uFrameTime; + unsigned int uPreamble; + unsigned int uTmp; + unsigned int uRateIdx = (unsigned int)wRate; + unsigned int uRate = 0; + + if (uRateIdx > RATE_54M) { + ASSERT(0); + return 0; + } + + uRate = (unsigned int)awcFrameTime[uRateIdx]; + + if (uRateIdx <= 3) { //CCK mode + + if (byPreambleType == 1) {//Short + uPreamble = 96; + } else { + uPreamble = 192; + } + uFrameTime = (cbFrameLength * 80) / uRate; //????? + uTmp = (uFrameTime * uRate) / 80; + if (cbFrameLength != uTmp) { + uFrameTime ++; + } + + return (uPreamble + uFrameTime); + } + else { + uFrameTime = (cbFrameLength * 8 + 22) / uRate; //???????? + uTmp = ((uFrameTime * uRate) - 22) / 8; + if(cbFrameLength != uTmp) { + uFrameTime ++; + } + uFrameTime = uFrameTime * 4; //??????? + if(byPktType != PK_TYPE_11A) { + uFrameTime += 6; + } + return (20 + uFrameTime); //?????? + } +} + +/* + * Description: Calculate Length, Service, and Signal fields of Phy for Tx + * + * Parameters: + * In: + * pDevice - Device Structure + * cbFrameLength - Tx Frame Length + * wRate - Tx Rate + * Out: + * pwPhyLen - pointer to Phy Length field + * pbyPhySrv - pointer to Phy Service field + * pbyPhySgn - pointer to Phy Signal field + * + * Return Value: none + * + */ +void BBvCalculateParameter(struct vnt_private *pDevice, u32 cbFrameLength, + u16 wRate, u8 byPacketType, u16 *pwPhyLen, u8 *pbyPhySrv, + u8 *pbyPhySgn) +{ + u32 cbBitCount; + u32 cbUsCount = 0; + u32 cbTmp; + int bExtBit; + u8 byPreambleType = pDevice->byPreambleType; + int bCCK = pDevice->bCCK; + + cbBitCount = cbFrameLength * 8; + bExtBit = false; + + switch (wRate) { + case RATE_1M : + cbUsCount = cbBitCount; + *pbyPhySgn = 0x00; + break; + + case RATE_2M : + cbUsCount = cbBitCount / 2; + if (byPreambleType == 1) + *pbyPhySgn = 0x09; + else // long preamble + *pbyPhySgn = 0x01; + break; + + case RATE_5M : + if (bCCK == false) + cbBitCount ++; + cbUsCount = (cbBitCount * 10) / 55; + cbTmp = (cbUsCount * 55) / 10; + if (cbTmp != cbBitCount) + cbUsCount ++; + if (byPreambleType == 1) + *pbyPhySgn = 0x0a; + else // long preamble + *pbyPhySgn = 0x02; + break; + + case RATE_11M : + + if (bCCK == false) + cbBitCount ++; + cbUsCount = cbBitCount / 11; + cbTmp = cbUsCount * 11; + if (cbTmp != cbBitCount) { + cbUsCount ++; + if ((cbBitCount - cbTmp) <= 3) + bExtBit = true; + } + if (byPreambleType == 1) + *pbyPhySgn = 0x0b; + else // long preamble + *pbyPhySgn = 0x03; + break; + + case RATE_6M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9B; //1001 1011 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8B; //1000 1011 + } + break; + + case RATE_9M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9F; //1001 1111 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8F; //1000 1111 + } + break; + + case RATE_12M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9A; //1001 1010 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8A; //1000 1010 + } + break; + + case RATE_18M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9E; //1001 1110 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8E; //1000 1110 + } + break; + + case RATE_24M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x99; //1001 1001 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x89; //1000 1001 + } + break; + + case RATE_36M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9D; //1001 1101 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8D; //1000 1101 + } + break; + + case RATE_48M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x98; //1001 1000 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x88; //1000 1000 + } + break; + + case RATE_54M : + if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9C; //1001 1100 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8C; //1000 1100 + } + break; + + default : + if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9C; //1001 1100 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8C; //1000 1100 + } + break; + } + + if (byPacketType == PK_TYPE_11B) { + *pbyPhySrv = 0x00; + if (bExtBit) + *pbyPhySrv = *pbyPhySrv | 0x80; + *pwPhyLen = (u16) cbUsCount; + } + else { + *pbyPhySrv = 0x00; + *pwPhyLen = (u16)cbFrameLength; + } +} + +/* + * Description: Set Antenna mode + * + * Parameters: + * In: + * pDevice - Device Structure + * byAntennaMode - Antenna Mode + * Out: + * none + * + * Return Value: none + * + */ +void BBvSetAntennaMode(struct vnt_private *pDevice, u8 byAntennaMode) +{ + switch (byAntennaMode) { + case ANT_TXA: + case ANT_TXB: + break; + case ANT_RXA: + pDevice->byBBRxConf &= 0xFC; + break; + case ANT_RXB: + pDevice->byBBRxConf &= 0xFE; + pDevice->byBBRxConf |= 0x02; + break; + } + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_SET_ANTMD, + (u16) byAntennaMode, + 0, + 0, + NULL); +} + +/* + * Description: Set Antenna mode + * + * Parameters: + * In: + * pDevice - Device Structure + * byAntennaMode - Antenna Mode + * Out: + * none + * + * Return Value: none + * + */ + +int BBbVT3184Init(struct vnt_private *pDevice) +{ + int ntStatus; + u16 wLength; + u8 * pbyAddr; + u8 * pbyAgc; + u16 wLengthAgc; + u8 abyArray[256]; + u8 data; + + ntStatus = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + 0, + MESSAGE_REQUEST_EEPROM, + EEP_MAX_CONTEXT_SIZE, + pDevice->abyEEPROM); + if (ntStatus != STATUS_SUCCESS) { + return false; + } + +// if ((pDevice->abyEEPROM[EEP_OFS_RADIOCTL]&0x06)==0x04) +// return false; + +//zonetype initial + pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; + if(pDevice->config_file.ZoneType >= 0) { //read zonetype file ok! + if ((pDevice->config_file.ZoneType == 0)&& + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] !=0x00)){ //for USA + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :USA\n"); + } + else if((pDevice->config_file.ZoneType == 1)&& + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x01)){ //for Japan + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :Japan\n"); + } + else if((pDevice->config_file.ZoneType == 2)&& + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x02)){ //for Europe + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :Europe\n"); + } +else { + if(pDevice->config_file.ZoneType !=pDevice->abyEEPROM[EEP_OFS_ZONETYPE]) + printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n",pDevice->config_file.ZoneType,pDevice->abyEEPROM[EEP_OFS_ZONETYPE]); + else + printk("Read Zonetype file success,use default zonetype setting[%02x]\n",pDevice->config_file.ZoneType); + } +} + + if ( !pDevice->bZoneRegExist ) { + pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; + } + pDevice->byRFType = pDevice->abyEEPROM[EEP_OFS_RFTYPE]; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Zone Type %x\n", pDevice->byZoneType); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RF Type %d\n", pDevice->byRFType); + + if ((pDevice->byRFType == RF_AL2230) || (pDevice->byRFType == RF_AL2230S)) { + pDevice->byBBRxConf = abyVT3184_AL2230[10]; + wLength = sizeof(abyVT3184_AL2230); + pbyAddr = abyVT3184_AL2230; + pbyAgc = abyVT3184_AGC; + wLengthAgc = sizeof(abyVT3184_AGC); + + pDevice->abyBBVGA[0] = 0x1C; + pDevice->abyBBVGA[1] = 0x10; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -70; + pDevice->ldBmThreshold[1] = -48; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + } + else if (pDevice->byRFType == RF_AIROHA7230) { + pDevice->byBBRxConf = abyVT3184_AL2230[10]; + wLength = sizeof(abyVT3184_AL2230); + pbyAddr = abyVT3184_AL2230; + pbyAgc = abyVT3184_AGC; + wLengthAgc = sizeof(abyVT3184_AGC); + + // Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) + //pbyAddr[0x09] = 0x41; + // Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) + //pbyAddr[0x0a] = 0x28; + // Select VC1/VC2, CR215 = 0x02->0x06 + pbyAddr[0xd7] = 0x06; + + pDevice->abyBBVGA[0] = 0x1C; + pDevice->abyBBVGA[1] = 0x10; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -70; + pDevice->ldBmThreshold[1] = -48; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + } + else if ( (pDevice->byRFType == RF_VT3226) || (pDevice->byRFType == RF_VT3226D0) ) { + pDevice->byBBRxConf = abyVT3184_VT3226D0[10]; //RobertYu:20060515 + wLength = sizeof(abyVT3184_VT3226D0); //RobertYu:20060515 + pbyAddr = abyVT3184_VT3226D0; //RobertYu:20060515 + pbyAgc = abyVT3184_AGC; + wLengthAgc = sizeof(abyVT3184_AGC); + + pDevice->abyBBVGA[0] = 0x20; //RobertYu:20060104, reguest by Jack + pDevice->abyBBVGA[1] = 0x10; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -70; + pDevice->ldBmThreshold[1] = -48; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + // Fix VT3226 DFC system timing issue + MACvRegBitsOn(pDevice, MAC_REG_SOFTPWRCTL2, SOFTPWRCTL_RFLEOPT); + //}} + //{{RobertYu:20060609 + } else if ( (pDevice->byRFType == RF_VT3342A0) ) { + pDevice->byBBRxConf = abyVT3184_VT3226D0[10]; + wLength = sizeof(abyVT3184_VT3226D0); + pbyAddr = abyVT3184_VT3226D0; + pbyAgc = abyVT3184_AGC; + wLengthAgc = sizeof(abyVT3184_AGC); + + pDevice->abyBBVGA[0] = 0x20; + pDevice->abyBBVGA[1] = 0x10; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -70; + pDevice->ldBmThreshold[1] = -48; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + // Fix VT3226 DFC system timing issue + MACvRegBitsOn(pDevice, MAC_REG_SOFTPWRCTL2, SOFTPWRCTL_RFLEOPT); + //}} + } else { + return true; + } + + memcpy(abyArray, pbyAddr, wLength); + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + 0, + MESSAGE_REQUEST_BBREG, + wLength, + abyArray + ); + + memcpy(abyArray, pbyAgc, wLengthAgc); + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + 0, + MESSAGE_REQUEST_BBAGC, + wLengthAgc, + abyArray + ); + + if ((pDevice->byRFType == RF_VT3226) || //RobertYu:20051116, 20060111 remove VT3226D0 + (pDevice->byRFType == RF_VT3342A0) //RobertYu:20060609 + ) { + ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_ITRTMSET,0x23); + MACvRegBitsOn(pDevice,MAC_REG_PAPEDELAY,0x01); + } + else if (pDevice->byRFType == RF_VT3226D0) + { + ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_ITRTMSET,0x11); + MACvRegBitsOn(pDevice,MAC_REG_PAPEDELAY,0x01); + } + + ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x04,0x7F); + ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x0D,0x01); + + RFbRFTableDownload(pDevice); + + /* Fix for TX USB resets from vendors driver */ + CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, USB_REG4, + MESSAGE_REQUEST_MEM, sizeof(data), &data); + + data |= 0x2; + + CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, USB_REG4, + MESSAGE_REQUEST_MEM, sizeof(data), &data); + + return true;//ntStatus; +} + +/* + * Description: Set ShortSlotTime mode + * + * Parameters: + * In: + * pDevice - Device Structure + * Out: + * none + * + * Return Value: none + * + */ +void BBvSetShortSlotTime(struct vnt_private *pDevice) +{ + u8 byBBVGA=0; + + if (pDevice->bShortSlotTime) + pDevice->byBBRxConf &= 0xDF;//1101 1111 + else + pDevice->byBBRxConf |= 0x20;//0010 0000 + + ControlvReadByte (pDevice, MESSAGE_REQUEST_BBREG, 0xE7, &byBBVGA); + if (byBBVGA == pDevice->abyBBVGA[0]) + pDevice->byBBRxConf |= 0x20;//0010 0000 + + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0A, pDevice->byBBRxConf); +} + +void BBvSetVGAGainOffset(struct vnt_private *pDevice, u8 byData) +{ + + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xE7, byData); + + // patch for 3253B0 Baseband with Cardbus module + if (pDevice->bShortSlotTime) + pDevice->byBBRxConf &= 0xDF; /* 1101 1111 */ + else + pDevice->byBBRxConf |= 0x20; /* 0010 0000 */ + + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0A, pDevice->byBBRxConf);//CR10 +} + +/* + * Description: BBvSetDeepSleep + * + * Parameters: + * In: + * pDevice - Device Structure + * Out: + * none + * + * Return Value: none + * + */ +void BBvSetDeepSleep(struct vnt_private *pDevice) +{ + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0c, 0x17);//CR12 + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0D, 0xB9);//CR13 +} + +void BBvExitDeepSleep(struct vnt_private *pDevice) +{ + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0C, 0x00);//CR12 + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x0D, 0x01);//CR13 +} + +static unsigned long s_ulGetLowSQ3(struct vnt_private *pDevice) +{ + int ii; + unsigned long ulSQ3 = 0; + unsigned long ulMaxPacket; + + ulMaxPacket = pDevice->aulPktNum[RATE_54M]; + if (pDevice->aulPktNum[RATE_54M] != 0) + ulSQ3 = pDevice->aulSQ3Val[RATE_54M] / pDevice->aulPktNum[RATE_54M]; + + for (ii = RATE_48M; ii >= RATE_6M; ii--) + if (pDevice->aulPktNum[ii] > ulMaxPacket) { + ulMaxPacket = pDevice->aulPktNum[ii]; + ulSQ3 = pDevice->aulSQ3Val[ii] / pDevice->aulPktNum[ii]; + } + + return ulSQ3; +} + +static unsigned long s_ulGetRatio(struct vnt_private *pDevice) +{ + int ii, jj; + unsigned long ulRatio = 0; + unsigned long ulMaxPacket; + unsigned long ulPacketNum; + + //This is a thousand-ratio + ulMaxPacket = pDevice->aulPktNum[RATE_54M]; + if ( pDevice->aulPktNum[RATE_54M] != 0 ) { + ulPacketNum = pDevice->aulPktNum[RATE_54M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_54M; + } + for (ii = RATE_48M; ii >= RATE_1M; ii--) + if ( pDevice->aulPktNum[ii] > ulMaxPacket ) { + ulPacketNum = 0; + for ( jj=RATE_54M;jj>=ii;jj--) + ulPacketNum += pDevice->aulPktNum[jj]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_48M; + ulMaxPacket = pDevice->aulPktNum[ii]; + } + + return ulRatio; +} + +static void s_vClearSQ3Value(struct vnt_private *pDevice) +{ + int ii; + pDevice->uDiversityCnt = 0; + + for ( ii=RATE_1M;ii<MAX_RATE;ii++) { + pDevice->aulPktNum[ii] = 0; + pDevice->aulSQ3Val[ii] = 0; + } +} + +/* + * Description: Antenna Diversity + * + * Parameters: + * In: + * pDevice - Device Structure + * byRSR - RSR from received packet + * bySQ3 - SQ3 value from received packet + * Out: + * none + * + * Return Value: none + * + */ + +void BBvAntennaDiversity(struct vnt_private *pDevice, + u8 byRxRate, u8 bySQ3) +{ + + pDevice->uDiversityCnt++; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pDevice->uDiversityCnt = %d\n", (int)pDevice->uDiversityCnt); + + if (byRxRate == 2) { + pDevice->aulPktNum[RATE_1M]++; + } + else if (byRxRate==4) { + pDevice->aulPktNum[RATE_2M]++; + } + else if (byRxRate==11) { + pDevice->aulPktNum[RATE_5M]++; + } + else if (byRxRate==22) { + pDevice->aulPktNum[RATE_11M]++; + } + else if(byRxRate==12){ + pDevice->aulPktNum[RATE_6M]++; + pDevice->aulSQ3Val[RATE_6M] += bySQ3; + } + else if(byRxRate==18){ + pDevice->aulPktNum[RATE_9M]++; + pDevice->aulSQ3Val[RATE_9M] += bySQ3; + } + else if(byRxRate==24){ + pDevice->aulPktNum[RATE_12M]++; + pDevice->aulSQ3Val[RATE_12M] += bySQ3; + } + else if(byRxRate==36){ + pDevice->aulPktNum[RATE_18M]++; + pDevice->aulSQ3Val[RATE_18M] += bySQ3; + } + else if(byRxRate==48){ + pDevice->aulPktNum[RATE_24M]++; + pDevice->aulSQ3Val[RATE_24M] += bySQ3; + } + else if(byRxRate==72){ + pDevice->aulPktNum[RATE_36M]++; + pDevice->aulSQ3Val[RATE_36M] += bySQ3; + } + else if(byRxRate==96){ + pDevice->aulPktNum[RATE_48M]++; + pDevice->aulSQ3Val[RATE_48M] += bySQ3; + } + else if(byRxRate==108){ + pDevice->aulPktNum[RATE_54M]++; + pDevice->aulSQ3Val[RATE_54M] += bySQ3; + } + + if (pDevice->byAntennaState == 0) { + + if (pDevice->uDiversityCnt > pDevice->ulDiversityNValue) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ulDiversityNValue=[%d],54M-[%d]\n",(int)pDevice->ulDiversityNValue, (int)pDevice->aulPktNum[RATE_54M]); + + pDevice->ulSQ3_State0 = s_ulGetLowSQ3(pDevice); + pDevice->ulRatio_State0 = s_ulGetRatio(pDevice); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SQ3_State0, SQ3= [%08x] rate = [%08x]\n",(int)pDevice->ulSQ3_State0,(int)pDevice->ulRatio_State0); + + if ( ((pDevice->aulPktNum[RATE_54M] < pDevice->ulDiversityNValue/2) && + (pDevice->ulSQ3_State0 > pDevice->ulSQ3TH) ) || + (pDevice->ulSQ3_State0 == 0 ) ) { + + if ( pDevice->byTMax == 0 ) + return; + + bScheduleCommand((void *) pDevice, + WLAN_CMD_CHANGE_ANTENNA, + NULL); + + pDevice->byAntennaState = 1; + + del_timer(&pDevice->TimerSQ3Tmax3); + del_timer(&pDevice->TimerSQ3Tmax2); + pDevice->TimerSQ3Tmax1.expires = RUN_AT(pDevice->byTMax * HZ); + add_timer(&pDevice->TimerSQ3Tmax1); + + } else { + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + } + s_vClearSQ3Value(pDevice); + + } + } else { //byAntennaState == 1 + + if (pDevice->uDiversityCnt > pDevice->ulDiversityMValue) { + + del_timer(&pDevice->TimerSQ3Tmax1); + pDevice->ulSQ3_State1 = s_ulGetLowSQ3(pDevice); + pDevice->ulRatio_State1 = s_ulGetRatio(pDevice); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SQ3_State1, rate0 = %08x,rate1 = %08x\n",(int)pDevice->ulRatio_State0,(int)pDevice->ulRatio_State1); + + if ( ((pDevice->ulSQ3_State1 == 0) && (pDevice->ulSQ3_State0 != 0)) || + ((pDevice->ulSQ3_State1 == 0) && (pDevice->ulSQ3_State0 == 0) && (pDevice->ulRatio_State1 < pDevice->ulRatio_State0)) || + ((pDevice->ulSQ3_State1 != 0) && (pDevice->ulSQ3_State0 != 0) && (pDevice->ulSQ3_State0 < pDevice->ulSQ3_State1)) + ) { + + bScheduleCommand((void *) pDevice, + WLAN_CMD_CHANGE_ANTENNA, + NULL); + + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + pDevice->TimerSQ3Tmax2.expires = RUN_AT(pDevice->byTMax2 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + add_timer(&pDevice->TimerSQ3Tmax2); + + } + pDevice->byAntennaState = 0; + s_vClearSQ3Value(pDevice); + } + } //byAntennaState +} + +/*+ + * + * Description: + * Timer for SQ3 antenna diversity + * + * Parameters: + * In: + * pvSysSpec1 + * hDeviceContext - Pointer to the adapter + * pvSysSpec2 + * pvSysSpec3 + * Out: + * none + * + * Return Value: none + * +-*/ + +void TimerSQ3CallBack(struct vnt_private *pDevice) +{ + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TimerSQ3CallBack..."); + spin_lock_irq(&pDevice->lock); + + bScheduleCommand((void *) pDevice, WLAN_CMD_CHANGE_ANTENNA, NULL); + pDevice->byAntennaState = 0; + s_vClearSQ3Value(pDevice); + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + pDevice->TimerSQ3Tmax2.expires = RUN_AT(pDevice->byTMax2 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + add_timer(&pDevice->TimerSQ3Tmax2); + + spin_unlock_irq(&pDevice->lock); +} + +/*+ + * + * Description: + * Timer for SQ3 antenna diversity + * + * Parameters: + * In: + * pvSysSpec1 + * hDeviceContext - Pointer to the adapter + * pvSysSpec2 + * pvSysSpec3 + * Out: + * none + * + * Return Value: none + * +-*/ + +void TimerSQ3Tmax3CallBack(struct vnt_private *pDevice) +{ + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TimerSQ3Tmax3CallBack..."); + spin_lock_irq(&pDevice->lock); + + pDevice->ulRatio_State0 = s_ulGetRatio(pDevice); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SQ3_State0 = [%08x]\n",(int)pDevice->ulRatio_State0); + + s_vClearSQ3Value(pDevice); + if ( pDevice->byTMax == 0 ) { + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + spin_unlock_irq(&pDevice->lock); + return; + } + + bScheduleCommand((void *) pDevice, WLAN_CMD_CHANGE_ANTENNA, NULL); + pDevice->byAntennaState = 1; + del_timer(&pDevice->TimerSQ3Tmax3); + del_timer(&pDevice->TimerSQ3Tmax2); + pDevice->TimerSQ3Tmax1.expires = RUN_AT(pDevice->byTMax * HZ); + add_timer(&pDevice->TimerSQ3Tmax1); + + spin_unlock_irq(&pDevice->lock); +} + +void BBvUpdatePreEDThreshold(struct vnt_private *pDevice, int bScanning) +{ + + switch(pDevice->byRFType) + { + case RF_AL2230: + case RF_AL2230S: + case RF_AIROHA7230: + //RobertYu:20060627, update new table + + if( bScanning ) + { // need Max sensitivity //RSSI -69, -70,.... + pDevice->byBBPreEDIndex = 0; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x30); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -69, -70, -71,...\n"); + break; + } + + if(pDevice->byBBPreEDRSSI <= 45) { // RSSI 0, -1,-2,....-45 + if(pDevice->byBBPreEDIndex == 20) break; + pDevice->byBBPreEDIndex = 20; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0xFF); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI 0, -1,-2,..-45\n"); + } else if(pDevice->byBBPreEDRSSI <= 46) { //RSSI -46 + if(pDevice->byBBPreEDIndex == 19) break; + pDevice->byBBPreEDIndex = 19; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x1A); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -46\n"); + } else if(pDevice->byBBPreEDRSSI <= 47) { //RSSI -47 + if(pDevice->byBBPreEDIndex == 18) break; + pDevice->byBBPreEDIndex = 18; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x15); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -47\n"); + } else if(pDevice->byBBPreEDRSSI <= 49) { //RSSI -48, -49 + if(pDevice->byBBPreEDIndex == 17) break; + pDevice->byBBPreEDIndex = 17; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x0E); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -48,-49\n"); + } else if(pDevice->byBBPreEDRSSI <= 51) { //RSSI -50, -51 + if(pDevice->byBBPreEDIndex == 16) break; + pDevice->byBBPreEDIndex = 16; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x09); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -50,-51\n"); + } else if(pDevice->byBBPreEDRSSI <= 53) { //RSSI -52, -53 + if(pDevice->byBBPreEDIndex == 15) break; + pDevice->byBBPreEDIndex = 15; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x06); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -52,-53\n"); + } else if(pDevice->byBBPreEDRSSI <= 55) { //RSSI -54, -55 + if(pDevice->byBBPreEDIndex == 14) break; + pDevice->byBBPreEDIndex = 14; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x03); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -54,-55\n"); + } else if(pDevice->byBBPreEDRSSI <= 56) { //RSSI -56 + if(pDevice->byBBPreEDIndex == 13) break; + pDevice->byBBPreEDIndex = 13; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x02); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xA0); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -56\n"); + } else if(pDevice->byBBPreEDRSSI <= 57) { //RSSI -57 + if(pDevice->byBBPreEDIndex == 12) break; + pDevice->byBBPreEDIndex = 12; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x02); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x20); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -57\n"); + } else if(pDevice->byBBPreEDRSSI <= 58) { //RSSI -58 + if(pDevice->byBBPreEDIndex == 11) break; + pDevice->byBBPreEDIndex = 11; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xA0); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -58\n"); + } else if(pDevice->byBBPreEDRSSI <= 59) { //RSSI -59 + if(pDevice->byBBPreEDIndex == 10) break; + pDevice->byBBPreEDIndex = 10; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x54); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -59\n"); + } else if(pDevice->byBBPreEDRSSI <= 60) { //RSSI -60 + if(pDevice->byBBPreEDIndex == 9) break; + pDevice->byBBPreEDIndex = 9; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x18); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -60\n"); + } else if(pDevice->byBBPreEDRSSI <= 61) { //RSSI -61 + if(pDevice->byBBPreEDIndex == 8) break; + pDevice->byBBPreEDIndex = 8; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xE3); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -61\n"); + } else if(pDevice->byBBPreEDRSSI <= 62) { //RSSI -62 + if(pDevice->byBBPreEDIndex == 7) break; + pDevice->byBBPreEDIndex = 7; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xB9); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -62\n"); + } else if(pDevice->byBBPreEDRSSI <= 63) { //RSSI -63 + if(pDevice->byBBPreEDIndex == 6) break; + pDevice->byBBPreEDIndex = 6; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x93); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -63\n"); + } else if(pDevice->byBBPreEDRSSI <= 64) { //RSSI -64 + if(pDevice->byBBPreEDIndex == 5) break; + pDevice->byBBPreEDIndex = 5; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x79); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -64\n"); + } else if(pDevice->byBBPreEDRSSI <= 65) { //RSSI -65 + if(pDevice->byBBPreEDIndex == 4) break; + pDevice->byBBPreEDIndex = 4; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x62); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -65\n"); + } else if(pDevice->byBBPreEDRSSI <= 66) { //RSSI -66 + if(pDevice->byBBPreEDIndex == 3) break; + pDevice->byBBPreEDIndex = 3; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x51); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -66\n"); + } else if(pDevice->byBBPreEDRSSI <= 67) { //RSSI -67 + if(pDevice->byBBPreEDIndex == 2) break; + pDevice->byBBPreEDIndex = 2; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x43); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -67\n"); + } else if(pDevice->byBBPreEDRSSI <= 68) { //RSSI -68 + if(pDevice->byBBPreEDIndex == 1) break; + pDevice->byBBPreEDIndex = 1; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x36); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -68\n"); + } else { //RSSI -69, -70,.... + if(pDevice->byBBPreEDIndex == 0) break; + pDevice->byBBPreEDIndex = 0; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x30); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -69, -70,...\n"); + } + break; + + case RF_VT3226: + case RF_VT3226D0: + //RobertYu:20060627, update new table + + if( bScanning ) + { // need Max sensitivity //RSSI -69, -70, ... + pDevice->byBBPreEDIndex = 0; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x24); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -69, -70,..\n"); + break; + } + + if(pDevice->byBBPreEDRSSI <= 41) { // RSSI 0, -1,-2,....-41 + if(pDevice->byBBPreEDIndex == 22) break; + pDevice->byBBPreEDIndex = 22; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0xFF); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI 0, -1,-2,..-41\n"); + } else if(pDevice->byBBPreEDRSSI <= 42) { //RSSI -42 + if(pDevice->byBBPreEDIndex == 21) break; + pDevice->byBBPreEDIndex = 21; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x36); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -42\n"); + } else if(pDevice->byBBPreEDRSSI <= 43) { //RSSI -43 + if(pDevice->byBBPreEDIndex == 20) break; + pDevice->byBBPreEDIndex = 20; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x26); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -43\n"); + } else if(pDevice->byBBPreEDRSSI <= 45) { //RSSI -44, -45 + if(pDevice->byBBPreEDIndex == 19) break; + pDevice->byBBPreEDIndex = 19; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x18); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -44,-45\n"); + } else if(pDevice->byBBPreEDRSSI <= 47) { //RSSI -46, -47 + if(pDevice->byBBPreEDIndex == 18) break; + pDevice->byBBPreEDIndex = 18; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x11); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -46,-47\n"); + } else if(pDevice->byBBPreEDRSSI <= 49) { //RSSI -48, -49 + if(pDevice->byBBPreEDIndex == 17) break; + pDevice->byBBPreEDIndex = 17; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x0a); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -48,-49\n"); + } else if(pDevice->byBBPreEDRSSI <= 51) { //RSSI -50, -51 + if(pDevice->byBBPreEDIndex == 16) break; + pDevice->byBBPreEDIndex = 16; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x07); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -50,-51\n"); + } else if(pDevice->byBBPreEDRSSI <= 53) { //RSSI -52, -53 + if(pDevice->byBBPreEDIndex == 15) break; + pDevice->byBBPreEDIndex = 15; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x04); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -52,-53\n"); + } else if(pDevice->byBBPreEDRSSI <= 55) { //RSSI -54, -55 + if(pDevice->byBBPreEDIndex == 14) break; + pDevice->byBBPreEDIndex = 14; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x02); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xC0); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -54,-55\n"); + } else if(pDevice->byBBPreEDRSSI <= 56) { //RSSI -56 + if(pDevice->byBBPreEDIndex == 13) break; + pDevice->byBBPreEDIndex = 13; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x02); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x30); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -56\n"); + } else if(pDevice->byBBPreEDRSSI <= 57) { //RSSI -57 + if(pDevice->byBBPreEDIndex == 12) break; + pDevice->byBBPreEDIndex = 12; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xB0); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -57\n"); + } else if(pDevice->byBBPreEDRSSI <= 58) { //RSSI -58 + if(pDevice->byBBPreEDIndex == 11) break; + pDevice->byBBPreEDIndex = 11; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x70); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -58\n"); + } else if(pDevice->byBBPreEDRSSI <= 59) { //RSSI -59 + if(pDevice->byBBPreEDIndex == 10) break; + pDevice->byBBPreEDIndex = 10; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x30); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -59\n"); + } else if(pDevice->byBBPreEDRSSI <= 60) { //RSSI -60 + if(pDevice->byBBPreEDIndex == 9) break; + pDevice->byBBPreEDIndex = 9; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xEA); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -60\n"); + } else if(pDevice->byBBPreEDRSSI <= 61) { //RSSI -61 + if(pDevice->byBBPreEDIndex == 8) break; + pDevice->byBBPreEDIndex = 8; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xC0); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -61\n"); + } else if(pDevice->byBBPreEDRSSI <= 62) { //RSSI -62 + if(pDevice->byBBPreEDIndex == 7) break; + pDevice->byBBPreEDIndex = 7; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x9C); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -62\n"); + } else if(pDevice->byBBPreEDRSSI <= 63) { //RSSI -63 + if(pDevice->byBBPreEDIndex == 6) break; + pDevice->byBBPreEDIndex = 6; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x80); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -63\n"); + } else if(pDevice->byBBPreEDRSSI <= 64) { //RSSI -64 + if(pDevice->byBBPreEDIndex == 5) break; + pDevice->byBBPreEDIndex = 5; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x68); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -64\n"); + } else if(pDevice->byBBPreEDRSSI <= 65) { //RSSI -65 + if(pDevice->byBBPreEDIndex == 4) break; + pDevice->byBBPreEDIndex = 4; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x52); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -65\n"); + } else if(pDevice->byBBPreEDRSSI <= 66) { //RSSI -66 + if(pDevice->byBBPreEDIndex == 3) break; + pDevice->byBBPreEDIndex = 3; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x43); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -66\n"); + } else if(pDevice->byBBPreEDRSSI <= 67) { //RSSI -67 + if(pDevice->byBBPreEDIndex == 2) break; + pDevice->byBBPreEDIndex = 2; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x36); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -67\n"); + } else if(pDevice->byBBPreEDRSSI <= 68) { //RSSI -68 + if(pDevice->byBBPreEDIndex == 1) break; + pDevice->byBBPreEDIndex = 1; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x2D); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -68\n"); + } else { //RSSI -69, -70, ... + if(pDevice->byBBPreEDIndex == 0) break; + pDevice->byBBPreEDIndex = 0; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x24); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -69, -70,..\n"); + } + break; + + case RF_VT3342A0: //RobertYu:20060627, testing table + if( bScanning ) + { // need Max sensitivity //RSSI -67, -68, ... + pDevice->byBBPreEDIndex = 0; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x38); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -67, -68,..\n"); + break; + } + + if(pDevice->byBBPreEDRSSI <= 41) { // RSSI 0, -1,-2,....-41 + if(pDevice->byBBPreEDIndex == 20) break; + pDevice->byBBPreEDIndex = 20; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0xFF); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI 0, -1,-2,..-41\n"); + } else if(pDevice->byBBPreEDRSSI <= 42) { //RSSI -42 + if(pDevice->byBBPreEDIndex == 19) break; + pDevice->byBBPreEDIndex = 19; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x36); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -42\n"); + } else if(pDevice->byBBPreEDRSSI <= 43) { //RSSI -43 + if(pDevice->byBBPreEDIndex == 18) break; + pDevice->byBBPreEDIndex = 18; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x26); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -43\n"); + } else if(pDevice->byBBPreEDRSSI <= 45) { //RSSI -44, -45 + if(pDevice->byBBPreEDIndex == 17) break; + pDevice->byBBPreEDIndex = 17; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x18); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -44,-45\n"); + } else if(pDevice->byBBPreEDRSSI <= 47) { //RSSI -46, -47 + if(pDevice->byBBPreEDIndex == 16) break; + pDevice->byBBPreEDIndex = 16; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x11); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -46,-47\n"); + } else if(pDevice->byBBPreEDRSSI <= 49) { //RSSI -48, -49 + if(pDevice->byBBPreEDIndex == 15) break; + pDevice->byBBPreEDIndex = 15; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x0a); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -48,-49\n"); + } else if(pDevice->byBBPreEDRSSI <= 51) { //RSSI -50, -51 + if(pDevice->byBBPreEDIndex == 14) break; + pDevice->byBBPreEDIndex = 14; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x07); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -50,-51\n"); + } else if(pDevice->byBBPreEDRSSI <= 53) { //RSSI -52, -53 + if(pDevice->byBBPreEDIndex == 13) break; + pDevice->byBBPreEDIndex = 13; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x04); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x00); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -52,-53\n"); + } else if(pDevice->byBBPreEDRSSI <= 55) { //RSSI -54, -55 + if(pDevice->byBBPreEDIndex == 12) break; + pDevice->byBBPreEDIndex = 12; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x02); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xC0); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -54,-55\n"); + } else if(pDevice->byBBPreEDRSSI <= 56) { //RSSI -56 + if(pDevice->byBBPreEDIndex == 11) break; + pDevice->byBBPreEDIndex = 11; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x02); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x30); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -56\n"); + } else if(pDevice->byBBPreEDRSSI <= 57) { //RSSI -57 + if(pDevice->byBBPreEDIndex == 10) break; + pDevice->byBBPreEDIndex = 10; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xB0); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -57\n"); + } else if(pDevice->byBBPreEDRSSI <= 58) { //RSSI -58 + if(pDevice->byBBPreEDIndex == 9) break; + pDevice->byBBPreEDIndex = 9; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x70); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -58\n"); + } else if(pDevice->byBBPreEDRSSI <= 59) { //RSSI -59 + if(pDevice->byBBPreEDIndex == 8) break; + pDevice->byBBPreEDIndex = 8; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x01); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x30); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -59\n"); + } else if(pDevice->byBBPreEDRSSI <= 60) { //RSSI -60 + if(pDevice->byBBPreEDIndex == 7) break; + pDevice->byBBPreEDIndex = 7; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xEA); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -60\n"); + } else if(pDevice->byBBPreEDRSSI <= 61) { //RSSI -61 + if(pDevice->byBBPreEDIndex == 6) break; + pDevice->byBBPreEDIndex = 6; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0xC0); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -61\n"); + } else if(pDevice->byBBPreEDRSSI <= 62) { //RSSI -62 + if(pDevice->byBBPreEDIndex == 5) break; + pDevice->byBBPreEDIndex = 5; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x9C); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -62\n"); + } else if(pDevice->byBBPreEDRSSI <= 63) { //RSSI -63 + if(pDevice->byBBPreEDIndex == 4) break; + pDevice->byBBPreEDIndex = 4; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x80); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -63\n"); + } else if(pDevice->byBBPreEDRSSI <= 64) { //RSSI -64 + if(pDevice->byBBPreEDIndex == 3) break; + pDevice->byBBPreEDIndex = 3; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x68); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -64\n"); + } else if(pDevice->byBBPreEDRSSI <= 65) { //RSSI -65 + if(pDevice->byBBPreEDIndex == 2) break; + pDevice->byBBPreEDIndex = 2; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x52); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -65\n"); + } else if(pDevice->byBBPreEDRSSI <= 66) { //RSSI -66 + if(pDevice->byBBPreEDIndex == 1) break; + pDevice->byBBPreEDIndex = 1; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x43); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -66\n"); + } else { //RSSI -67, -68, ... + if(pDevice->byBBPreEDIndex == 0) break; + pDevice->byBBPreEDIndex = 0; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xC9, 0x00); //CR201(0xC9) + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xCE, 0x38); //CR206(0xCE) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->byBBPreEDRSSI -67, -68,..\n"); + } + break; + + } + +} + diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h new file mode 100644 index 00000000..0a634ada --- /dev/null +++ b/drivers/staging/vt6656/baseband.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: baseband.h + * + * Purpose: Implement functions to access baseband + * + * Author: Jerry Chen + * + * Date: Jun. 5, 2002 + * + * Revision History: + * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-26-2003 Kyle Hsu : Add defines of packet type and TX rate. + */ + +#ifndef __BASEBAND_H__ +#define __BASEBAND_H__ + +#include "tether.h" +#include "device.h" + +#define PREAMBLE_LONG 0 +#define PREAMBLE_SHORT 1 + +/* + * Registers in the BASEBAND + */ +#define BB_MAX_CONTEXT_SIZE 256 + +#define C_SIFS_A 16 /* usec */ +#define C_SIFS_BG 10 + +#define C_EIFS 80 /* usec */ + +#define C_SLOT_SHORT 9 /* usec */ +#define C_SLOT_LONG 20 + +#define C_CWMIN_A 15 /* slot time */ +#define C_CWMIN_B 31 + +#define C_CWMAX 1023 /* slot time */ + +/* 0:11A 1:11B 2:11G */ +#define BB_TYPE_11A 0 +#define BB_TYPE_11B 1 +#define BB_TYPE_11G 2 + +/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga (OFDM in BasicRate) */ +#define PK_TYPE_11A 0 +#define PK_TYPE_11B 1 +#define PK_TYPE_11GB 2 +#define PK_TYPE_11GA 3 + +#define TOP_RATE_54M 0x80000000 +#define TOP_RATE_48M 0x40000000 +#define TOP_RATE_36M 0x20000000 +#define TOP_RATE_24M 0x10000000 +#define TOP_RATE_18M 0x08000000 +#define TOP_RATE_12M 0x04000000 +#define TOP_RATE_11M 0x02000000 +#define TOP_RATE_9M 0x01000000 +#define TOP_RATE_6M 0x00800000 +#define TOP_RATE_55M 0x00400000 +#define TOP_RATE_2M 0x00200000 +#define TOP_RATE_1M 0x00100000 + +unsigned int +BBuGetFrameTime( + u8 byPreambleType, + u8 byFreqType, + unsigned int cbFrameLength, + u16 wRate + ); + +void BBvCalculateParameter(struct vnt_private *, u32 cbFrameLength, + u16 wRate, u8 byPacketType, u16 *pwPhyLen, u8 *pbyPhySrv, + u8 *pbyPhySgn); + +/* timer for antenna diversity */ + +void TimerSQ3CallBack(struct vnt_private *); +void TimerSQ3Tmax3CallBack(struct vnt_private *); + +void BBvAntennaDiversity(struct vnt_private *, u8 byRxRate, u8 bySQ3); + +void BBvSetShortSlotTime(struct vnt_private *); +void BBvSetVGAGainOffset(struct vnt_private *, u8 byData); +void BBvSetAntennaMode(struct vnt_private *, u8 byAntennaMode); +int BBbVT3184Init(struct vnt_private *); +void BBvSetDeepSleep(struct vnt_private *); +void BBvExitDeepSleep(struct vnt_private *); +void BBvUpdatePreEDThreshold(struct vnt_private *, int bScanning); + +#endif /* __BASEBAND_H__ */ diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c new file mode 100644 index 00000000..ee79bbdf --- /dev/null +++ b/drivers/staging/vt6656/bssdb.c @@ -0,0 +1,1435 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: bssdb.c + * + * Purpose: Handles the Basic Service Set & Node Database functions + * + * Functions: + * BSSpSearchBSSList - Search known BSS list for Desire SSID or BSSID + * BSSvClearBSSList - Clear BSS List + * BSSbInsertToBSSList - Insert a BSS set into known BSS list + * BSSbUpdateToBSSList - Update BSS set in known BSS list + * BSSbIsSTAInNodeDB - Search Node DB table to find the index of matched DstAddr + * BSSvCreateOneNode - Allocate an Node for Node DB + * BSSvUpdateAPNode - Update AP Node content in Index 0 of KnownNodeDB + * BSSvSecondCallBack - One second timer callback function to update Node DB info & AP link status + * BSSvUpdateNodeTxCounter - Update Tx attemps, Tx failure counter in Node DB for auto-fall back rate control + * + * Revision History: + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + */ + +#include "tmacro.h" +#include "tether.h" +#include "device.h" +#include "80211hdr.h" +#include "bssdb.h" +#include "wmgr.h" +#include "datarate.h" +#include "desc.h" +#include "wcmd.h" +#include "wpa.h" +#include "baseband.h" +#include "rf.h" +#include "card.h" +#include "mac.h" +#include "wpa2.h" +#include "control.h" +#include "rndis.h" +#include "iowpa.h" + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +const u16 awHWRetry0[5][5] = { + {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, + {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M}, + {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M}, + {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M}, + {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M} + }; +const u16 awHWRetry1[5][5] = { + {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M}, + {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M}, + {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M}, + {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M}, + {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M} + }; + +static void s_vCheckSensitivity(struct vnt_private *pDevice); +static void s_vCheckPreEDThreshold(struct vnt_private *pDevice); +static void s_uCalculateLinkQual(struct vnt_private *pDevice); + +/*+ + * + * Routine Description: + * Search known BSS list for Desire SSID or BSSID. + * + * Return Value: + * PTR to KnownBSS or NULL + * +-*/ + +PKnownBSS BSSpSearchBSSList(struct vnt_private *pDevice, + u8 *pbyDesireBSSID, u8 *pbyDesireSSID, + CARD_PHY_TYPE ePhyType) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u8 *pbyBSSID = NULL; + PWLAN_IE_SSID pSSID = NULL; + PKnownBSS pCurrBSS = NULL; + PKnownBSS pSelect = NULL; + u8 ZeroBSSID[WLAN_BSSID_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + int ii = 0; + int jj = 0; + + if (pbyDesireBSSID != NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "BSSpSearchBSSList BSSID[%pM]\n", pbyDesireBSSID); + if ((!is_broadcast_ether_addr(pbyDesireBSSID)) && + (memcmp(pbyDesireBSSID, ZeroBSSID, 6)!= 0)){ + pbyBSSID = pbyDesireBSSID; + } + } + if (pbyDesireSSID != NULL) { + if (((PWLAN_IE_SSID)pbyDesireSSID)->len != 0) { + pSSID = (PWLAN_IE_SSID) pbyDesireSSID; + } + } + + if ((pbyBSSID != NULL)&&(pDevice->bRoaming == false)) { + // match BSSID first + for (ii = 0; ii <MAX_BSS_NUM; ii++) { + pCurrBSS = &(pMgmt->sBSSList[ii]); + + pCurrBSS->bSelected = false; + + if ((pCurrBSS->bActive) && + (pCurrBSS->bSelected == false)) { + if (!compare_ether_addr(pCurrBSS->abyBSSID, pbyBSSID)) { + if (pSSID != NULL) { + // compare ssid + if ( !memcmp(pSSID->abySSID, + ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID, + pSSID->len)) { + if ((pMgmt->eConfigMode == WMAC_CONFIG_AUTO) || + ((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) || + ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) + ) { + pCurrBSS->bSelected = true; + return(pCurrBSS); + } + } + } else { + if ((pMgmt->eConfigMode == WMAC_CONFIG_AUTO) || + ((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) || + ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) + ) { + pCurrBSS->bSelected = true; + return(pCurrBSS); + } + } + } + } + } + } else { + // ignore BSSID + for (ii = 0; ii <MAX_BSS_NUM; ii++) { + pCurrBSS = &(pMgmt->sBSSList[ii]); + + //2007-0721-01<Mark>by MikeLiu + // if ((pCurrBSS->bActive) && + // (pCurrBSS->bSelected == false)) { + + pCurrBSS->bSelected = false; + if (pCurrBSS->bActive) { + + if (pSSID != NULL) { + // matched SSID + if (memcmp(pSSID->abySSID, + ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID, + pSSID->len) || + (pSSID->len != ((PWLAN_IE_SSID)pCurrBSS->abySSID)->len)) { + // SSID not match skip this BSS + continue; + } + } + if (((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) || + ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) + ){ + // Type not match skip this BSS + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSS type mismatch.... Config[%d] BSS[0x%04x]\n", pMgmt->eConfigMode, pCurrBSS->wCapInfo); + continue; + } + + if (ePhyType != PHY_TYPE_AUTO) { + if (((ePhyType == PHY_TYPE_11A) && (PHY_TYPE_11A != pCurrBSS->eNetworkTypeInUse)) || + ((ePhyType != PHY_TYPE_11A) && (PHY_TYPE_11A == pCurrBSS->eNetworkTypeInUse))) { + // PhyType not match skip this BSS + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Physical type mismatch.... ePhyType[%d] BSS[%d]\n", ePhyType, pCurrBSS->eNetworkTypeInUse); + continue; + } + } + + pMgmt->pSameBSS[jj].uChannel = pCurrBSS->uChannel; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "BSSpSearchBSSList pSelect1[%pM]\n", + pCurrBSS->abyBSSID); + jj++; + + if (pSelect == NULL) { + pSelect = pCurrBSS; + } else { + // compare RSSI, select the strongest signal + if (pCurrBSS->uRSSI < pSelect->uRSSI) { + pSelect = pCurrBSS; + } + } + } + } + +pDevice->bSameBSSMaxNum = jj; + + if (pSelect != NULL) { + pSelect->bSelected = true; + if (pDevice->bRoaming == false) { + // Einsn Add @20070907 + memcpy(pbyDesireSSID,pCurrBSS->abySSID,WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1) ; + } + + return(pSelect); + } + } + return(NULL); + +} + +/*+ + * + * Routine Description: + * Clear BSS List + * + * Return Value: + * None. + * +-*/ + +void BSSvClearBSSList(struct vnt_private *pDevice, int bKeepCurrBSSID) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int ii; + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + if (bKeepCurrBSSID) { + if (pMgmt->sBSSList[ii].bActive && + !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, + pMgmt->abyCurrBSSID)) { + //mike mark: there are two BSSID's in list. If that AP is in hidden ssid mode, one SSID is null, + // but other's might not be obvious, so if it associate's with your STA, + // you must keep the two of them!! + // bKeepCurrBSSID = false; + continue; + } + } + + pMgmt->sBSSList[ii].bActive = false; + memset(&pMgmt->sBSSList[ii], 0, sizeof(KnownBSS)); + } + BSSvClearAnyBSSJoinRecord(pDevice); +} + +/*+ + * + * Routine Description: + * search BSS list by BSSID & SSID if matched + * + * Return Value: + * true if found. + * +-*/ +PKnownBSS BSSpAddrIsInBSSList(struct vnt_private *pDevice, + u8 *abyBSSID, PWLAN_IE_SSID pSSID) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PKnownBSS pBSSList = NULL; + int ii; + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSSList = &(pMgmt->sBSSList[ii]); + if (pBSSList->bActive) { + if (!compare_ether_addr(pBSSList->abyBSSID, abyBSSID)) { + if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len){ + if (memcmp(pSSID->abySSID, + ((PWLAN_IE_SSID)pBSSList->abySSID)->abySSID, + pSSID->len) == 0) + return pBSSList; + } + } + } + } + + return NULL; +}; + +/*+ + * + * Routine Description: + * Insert a BSS set into known BSS list + * + * Return Value: + * true if success. + * +-*/ + +int BSSbInsertToBSSList(struct vnt_private *pDevice, + u8 *abyBSSIDAddr, + u64 qwTimestamp, + u16 wBeaconInterval, + u16 wCapInfo, + u8 byCurrChannel, + PWLAN_IE_SSID pSSID, + PWLAN_IE_SUPP_RATES pSuppRates, + PWLAN_IE_SUPP_RATES pExtSuppRates, + PERPObject psERP, + PWLAN_IE_RSN pRSN, + PWLAN_IE_RSN_EXT pRSNWPA, + PWLAN_IE_COUNTRY pIE_Country, + PWLAN_IE_QUIET pIE_Quiet, + u32 uIELength, + u8 *pbyIEs, + void *pRxPacketContext) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct vnt_rx_mgmt *pRxPacket = + (struct vnt_rx_mgmt *)pRxPacketContext; + PKnownBSS pBSSList = NULL; + unsigned int ii; + bool bParsingQuiet = false; + + pBSSList = (PKnownBSS)&(pMgmt->sBSSList[0]); + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSSList = (PKnownBSS)&(pMgmt->sBSSList[ii]); + if (!pBSSList->bActive) + break; + } + + if (ii == MAX_BSS_NUM){ + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Get free KnowBSS node failed.\n"); + return false; + } + // save the BSS info + pBSSList->bActive = true; + memcpy( pBSSList->abyBSSID, abyBSSIDAddr, WLAN_BSSID_LEN); + pBSSList->qwBSSTimestamp = cpu_to_le64(qwTimestamp); + pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval); + pBSSList->wCapInfo = cpu_to_le16(wCapInfo); + pBSSList->uClearCount = 0; + + if (pSSID->len > WLAN_SSID_MAXLEN) + pSSID->len = WLAN_SSID_MAXLEN; + memcpy( pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); + + pBSSList->uChannel = byCurrChannel; + + if (pSuppRates->len > WLAN_RATES_MAXLEN) + pSuppRates->len = WLAN_RATES_MAXLEN; + memcpy( pBSSList->abySuppRates, pSuppRates, pSuppRates->len + WLAN_IEHDR_LEN); + + if (pExtSuppRates != NULL) { + if (pExtSuppRates->len > WLAN_RATES_MAXLEN) + pExtSuppRates->len = WLAN_RATES_MAXLEN; + memcpy(pBSSList->abyExtSuppRates, pExtSuppRates, pExtSuppRates->len + WLAN_IEHDR_LEN); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSbInsertToBSSList: pExtSuppRates->len = %d\n", pExtSuppRates->len); + + } else { + memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + } + pBSSList->sERP.byERP = psERP->byERP; + pBSSList->sERP.bERPExist = psERP->bERPExist; + + // Check if BSS is 802.11a/b/g + if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; + } else { + if (pBSSList->sERP.bERPExist == true) { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11G; + } else { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11B; + } + } + + pBSSList->byRxRate = pRxPacket->byRxRate; + pBSSList->qwLocalTSF = pRxPacket->qwLocalTSF; + pBSSList->uRSSI = pRxPacket->uRSSI; + pBSSList->bySQ = pRxPacket->bySQ; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + // assoc with BSS + if (pBSSList == pMgmt->pCurrBSS) { + bParsingQuiet = true; + } + } + + WPA_ClearRSN(pBSSList); + + if (pRSNWPA != NULL) { + unsigned int uLen = pRSNWPA->len + 2; + + if (uLen <= (uIELength - + (unsigned int) (u32) ((u8 *) pRSNWPA - pbyIEs))) { + pBSSList->wWPALen = uLen; + memcpy(pBSSList->byWPAIE, pRSNWPA, uLen); + WPA_ParseRSN(pBSSList, pRSNWPA); + } + } + + WPA2_ClearRSN(pBSSList); + + if (pRSN != NULL) { + unsigned int uLen = pRSN->len + 2; + + if (uLen <= (uIELength - + (unsigned int) (u32) ((u8 *) pRSN - pbyIEs))) { + pBSSList->wRSNLen = uLen; + memcpy(pBSSList->byRSNIE, pRSN, uLen); + WPA2vParseRSN(pBSSList, pRSN); + } + } + + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || (pBSSList->bWPA2Valid == true)) { + + PSKeyItem pTransmitKey = NULL; + bool bIs802_1x = false; + + for (ii = 0; ii < pBSSList->wAKMSSAuthCount; ii ++) { + if (pBSSList->abyAKMSSAuthType[ii] == WLAN_11i_AKMSS_802_1X) { + bIs802_1x = true; + break; + } + } + if ((bIs802_1x == true) && (pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len) && + ( !memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID, pSSID->len))) { + + bAdd_PMKID_Candidate((void *) pDevice, + pBSSList->abyBSSID, + &pBSSList->sRSNCapObj); + + if ((pDevice->bLinkPass == true) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + if ((KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, PAIRWISE_KEY, &pTransmitKey) == true) || + (KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, GROUP_KEY, &pTransmitKey) == true)) { + pDevice->gsPMKIDCandidate.StatusType = Ndis802_11StatusType_PMKID_CandidateList; + pDevice->gsPMKIDCandidate.Version = 1; + + } + + } + } + } + + if (pDevice->bUpdateBBVGA) { + // Monitor if RSSI is too strong. + pBSSList->byRSSIStatCnt = 0; + RFvRSSITodBm(pDevice, (u8)(pRxPacket->uRSSI), &pBSSList->ldBmMAX); + pBSSList->ldBmAverage[0] = pBSSList->ldBmMAX; + pBSSList->ldBmAverRange = pBSSList->ldBmMAX; + for (ii = 1; ii < RSSI_STAT_COUNT; ii++) + pBSSList->ldBmAverage[ii] = 0; + } + + pBSSList->uIELength = uIELength; + if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN) + pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN; + memcpy(pBSSList->abyIEs, pbyIEs, pBSSList->uIELength); + + return true; +} + +/*+ + * + * Routine Description: + * Update BSS set in known BSS list + * + * Return Value: + * true if success. + * +-*/ +// TODO: input structure modify + +int BSSbUpdateToBSSList(struct vnt_private *pDevice, + u64 qwTimestamp, + u16 wBeaconInterval, + u16 wCapInfo, + u8 byCurrChannel, + int bChannelHit, + PWLAN_IE_SSID pSSID, + PWLAN_IE_SUPP_RATES pSuppRates, + PWLAN_IE_SUPP_RATES pExtSuppRates, + PERPObject psERP, + PWLAN_IE_RSN pRSN, + PWLAN_IE_RSN_EXT pRSNWPA, + PWLAN_IE_COUNTRY pIE_Country, + PWLAN_IE_QUIET pIE_Quiet, + PKnownBSS pBSSList, + u32 uIELength, + u8 *pbyIEs, + void *pRxPacketContext) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct vnt_rx_mgmt *pRxPacket = + (struct vnt_rx_mgmt *)pRxPacketContext; + int ii, jj; + signed long ldBm, ldBmSum; + bool bParsingQuiet = false; + + if (pBSSList == NULL) + return false; + + pBSSList->qwBSSTimestamp = cpu_to_le64(qwTimestamp); + + pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval); + pBSSList->wCapInfo = cpu_to_le16(wCapInfo); + pBSSList->uClearCount = 0; + pBSSList->uChannel = byCurrChannel; + + if (pSSID->len > WLAN_SSID_MAXLEN) + pSSID->len = WLAN_SSID_MAXLEN; + + if ((pSSID->len != 0) && (pSSID->abySSID[0] != 0)) + memcpy(pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); + memcpy(pBSSList->abySuppRates, pSuppRates,pSuppRates->len + WLAN_IEHDR_LEN); + + if (pExtSuppRates != NULL) { + memcpy(pBSSList->abyExtSuppRates, pExtSuppRates,pExtSuppRates->len + WLAN_IEHDR_LEN); + } else { + memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + } + pBSSList->sERP.byERP = psERP->byERP; + pBSSList->sERP.bERPExist = psERP->bERPExist; + + // Check if BSS is 802.11a/b/g + if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; + } else { + if (pBSSList->sERP.bERPExist == true) { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11G; + } else { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11B; + } + } + + pBSSList->byRxRate = pRxPacket->byRxRate; + pBSSList->qwLocalTSF = pRxPacket->qwLocalTSF; + if(bChannelHit) + pBSSList->uRSSI = pRxPacket->uRSSI; + pBSSList->bySQ = pRxPacket->bySQ; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + // assoc with BSS + if (pBSSList == pMgmt->pCurrBSS) { + bParsingQuiet = true; + } + } + + WPA_ClearRSN(pBSSList); //mike update + + if (pRSNWPA != NULL) { + unsigned int uLen = pRSNWPA->len + 2; + if (uLen <= (uIELength - + (unsigned int) (u32) ((u8 *) pRSNWPA - pbyIEs))) { + pBSSList->wWPALen = uLen; + memcpy(pBSSList->byWPAIE, pRSNWPA, uLen); + WPA_ParseRSN(pBSSList, pRSNWPA); + } + } + + WPA2_ClearRSN(pBSSList); //mike update + + if (pRSN != NULL) { + unsigned int uLen = pRSN->len + 2; + if (uLen <= (uIELength - + (unsigned int) (u32) ((u8 *) pRSN - pbyIEs))) { + pBSSList->wRSNLen = uLen; + memcpy(pBSSList->byRSNIE, pRSN, uLen); + WPA2vParseRSN(pBSSList, pRSN); + } + } + + if (pRxPacket->uRSSI != 0) { + RFvRSSITodBm(pDevice, (u8)(pRxPacket->uRSSI), &ldBm); + // Monitor if RSSI is too strong. + pBSSList->byRSSIStatCnt++; + pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT; + pBSSList->ldBmAverage[pBSSList->byRSSIStatCnt] = ldBm; + ldBmSum = 0; + for (ii = 0, jj = 0; ii < RSSI_STAT_COUNT; ii++) { + if (pBSSList->ldBmAverage[ii] != 0) { + pBSSList->ldBmMAX = + max(pBSSList->ldBmAverage[ii], ldBm); + ldBmSum += + pBSSList->ldBmAverage[ii]; + jj++; + } + } + pBSSList->ldBmAverRange = ldBmSum /jj; + } + + pBSSList->uIELength = uIELength; + if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN) + pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN; + memcpy(pBSSList->abyIEs, pbyIEs, pBSSList->uIELength); + + return true; +} + +/*+ + * + * Routine Description: + * Search Node DB table to find the index of matched DstAddr + * + * Return Value: + * None + * +-*/ + +int BSSbIsSTAInNodeDB(struct vnt_private *pDevice, + u8 *abyDstAddr, u32 *puNodeIndex) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + unsigned int ii; + + // Index = 0 reserved for AP Node + for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive) { + if (!compare_ether_addr(abyDstAddr, + pMgmt->sNodeDBTable[ii].abyMACAddr)) { + *puNodeIndex = ii; + return true; + } + } + } + + return false; +}; + +/*+ + * + * Routine Description: + * Find an empty node and allocate it; if no empty node + * is found, then use the most inactive one. + * + * Return Value: + * None + * +-*/ +void BSSvCreateOneNode(struct vnt_private *pDevice, u32 *puNodeIndex) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int ii; + u32 BigestCount = 0; + u32 SelectIndex; + struct sk_buff *skb; + + // Index = 0 reserved for AP Node (In STA mode) + // Index = 0 reserved for Broadcast/MultiCast (In AP mode) + SelectIndex = 1; + for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive) { + if (pMgmt->sNodeDBTable[ii].uInActiveCount > BigestCount) { + BigestCount = pMgmt->sNodeDBTable[ii].uInActiveCount; + SelectIndex = ii; + } + } + else { + break; + } + } + + // if not found replace uInActiveCount with the largest one. + if ( ii == (MAX_NODE_NUM + 1)) { + *puNodeIndex = SelectIndex; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Replace inactive node = %d\n", SelectIndex); + // clear ps buffer + if (pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue.next != NULL) { + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue)) != NULL) + dev_kfree_skb(skb); + } + } + else { + *puNodeIndex = ii; + } + + memset(&pMgmt->sNodeDBTable[*puNodeIndex], 0, sizeof(KnownNodeDB)); + pMgmt->sNodeDBTable[*puNodeIndex].bActive = true; + pMgmt->sNodeDBTable[*puNodeIndex].uRatePollTimeout = FALLBACK_POLL_SECOND; + // for AP mode PS queue + skb_queue_head_init(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue); + pMgmt->sNodeDBTable[*puNodeIndex].byAuthSequence = 0; + pMgmt->sNodeDBTable[*puNodeIndex].wEnQueueCnt = 0; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create node index = %d\n", ii); +}; + +/*+ + * + * Routine Description: + * Remove Node by NodeIndex + * + * + * Return Value: + * None + * +-*/ + +void BSSvRemoveOneNode(struct vnt_private *pDevice, u32 uNodeIndex) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + struct sk_buff *skb; + + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue)) != NULL) + dev_kfree_skb(skb); + // clear context + memset(&pMgmt->sNodeDBTable[uNodeIndex], 0, sizeof(KnownNodeDB)); + // clear tx bit map + pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[uNodeIndex].wAID >> 3] &= ~byMask[pMgmt->sNodeDBTable[uNodeIndex].wAID & 7]; +}; +/*+ + * + * Routine Description: + * Update AP Node content in Index 0 of KnownNodeDB + * + * + * Return Value: + * None + * +-*/ + +void BSSvUpdateAPNode(struct vnt_private *pDevice, u16 *pwCapInfo, + PWLAN_IE_SUPP_RATES pSuppRates, PWLAN_IE_SUPP_RATES pExtSuppRates) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u32 uRateLen = WLAN_RATES_MAXLEN; + + memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB)); + + pMgmt->sNodeDBTable[0].bActive = true; + if (pDevice->byBBType == BB_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + uRateLen); + pMgmt->abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pExtSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + uRateLen); + RATEvParseMaxRate((void *) pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + true, + &(pMgmt->sNodeDBTable[0].wMaxBasicRate), + &(pMgmt->sNodeDBTable[0].wMaxSuppRate), + &(pMgmt->sNodeDBTable[0].wSuppRate), + &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate) + ); + memcpy(pMgmt->sNodeDBTable[0].abyMACAddr, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxSuppRate; + pMgmt->sNodeDBTable[0].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*pwCapInfo); + pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND; + // Auto rate fallback function initiation. + // RATEbInit(pDevice); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pMgmt->sNodeDBTable[0].wTxDataRate = %d \n", pMgmt->sNodeDBTable[0].wTxDataRate); + +}; + +/*+ + * + * Routine Description: + * Add Multicast Node content in Index 0 of KnownNodeDB + * + * + * Return Value: + * None + * +-*/ + +void BSSvAddMulticastNode(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + if (!pDevice->bEnableHostWEP) + memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB)); + memset(pMgmt->sNodeDBTable[0].abyMACAddr, 0xff, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[0].bActive = true; + pMgmt->sNodeDBTable[0].bPSEnable = false; + skb_queue_head_init(&pMgmt->sNodeDBTable[0].sTxPSQueue); + RATEvParseMaxRate((void *) pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + true, + &(pMgmt->sNodeDBTable[0].wMaxBasicRate), + &(pMgmt->sNodeDBTable[0].wMaxSuppRate), + &(pMgmt->sNodeDBTable[0].wSuppRate), + &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate) + ); + pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxBasicRate; + pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND; + +}; + +/*+ + * + * Routine Description: + * + * + * Second call back function to update Node DB info & AP link status + * + * + * Return Value: + * none. + * +-*/ + +void BSSvSecondCallBack(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int ii; + PWLAN_IE_SSID pItemSSID, pCurrSSID; + u32 uSleepySTACnt = 0; + u32 uNonShortSlotSTACnt = 0; + u32 uLongPreambleSTACnt = 0; + + spin_lock_irq(&pDevice->lock); + + pDevice->uAssocCount = 0; + + //Power Saving Mode Tx Burst + if ( pDevice->bEnablePSMode == true ) { + pDevice->ulPSModeWaitTx++; + if ( pDevice->ulPSModeWaitTx >= 2 ) { + pDevice->ulPSModeWaitTx = 0; + pDevice->bPSModeTxBurst = false; + } + } + + pDevice->byERPFlag &= + ~(WLAN_SET_ERP_BARKER_MODE(1) | WLAN_SET_ERP_NONERP_PRESENT(1)); + + if (pDevice->wUseProtectCntDown > 0) { + pDevice->wUseProtectCntDown --; + } + else { + // disable protect mode + pDevice->byERPFlag &= ~(WLAN_SET_ERP_USE_PROTECTION(1)); + } + +if(pDevice->byReAssocCount > 0) { + pDevice->byReAssocCount++; + if((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != true)) { //10 sec timeout + printk("Re-association timeout!!!\n"); + pDevice->byReAssocCount = 0; + // if(pDevice->bWPASuppWextEnabled == true) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + } + else if(pDevice->bLinkPass == true) + pDevice->byReAssocCount = 0; +} + + pMgmt->eLastState = pMgmt->eCurrState ; + + s_uCalculateLinkQual(pDevice); + + for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) { + + if (pMgmt->sNodeDBTable[ii].bActive) { + // Increase in-activity counter + pMgmt->sNodeDBTable[ii].uInActiveCount++; + + if (ii > 0) { + if (pMgmt->sNodeDBTable[ii].uInActiveCount > MAX_INACTIVE_COUNT) { + BSSvRemoveOneNode(pDevice, ii); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Inactive timeout [%d] sec, STA index = [%d] remove\n", MAX_INACTIVE_COUNT, ii); + continue; + } + + if (pMgmt->sNodeDBTable[ii].eNodeState >= NODE_ASSOC) { + + pDevice->uAssocCount++; + + // check if Non ERP exist + if (pMgmt->sNodeDBTable[ii].uInActiveCount < ERP_RECOVER_COUNT) { + if (!pMgmt->sNodeDBTable[ii].bShortPreamble) { + pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1); + uLongPreambleSTACnt ++; + } + if (!pMgmt->sNodeDBTable[ii].bERPExist) { + pDevice->byERPFlag |= WLAN_SET_ERP_NONERP_PRESENT(1); + pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1); + } + if (!pMgmt->sNodeDBTable[ii].bShortSlotTime) + uNonShortSlotSTACnt++; + } + } + + // check if any STA in PS mode + if (pMgmt->sNodeDBTable[ii].bPSEnable) + uSleepySTACnt++; + + } + + // Rate fallback check + if (!pDevice->bFixRate) { + if (ii > 0) { + // ii = 0 for multicast node (AP & Adhoc) + RATEvTxRateFallBack((void *)pDevice, + &(pMgmt->sNodeDBTable[ii])); + } + else { + // ii = 0 reserved for unicast AP node (Infra STA) + if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) + RATEvTxRateFallBack((void *)pDevice, + &(pMgmt->sNodeDBTable[ii])); + } + + } + + // check if pending PS queue + if (pMgmt->sNodeDBTable[ii].wEnQueueCnt != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index= %d, Queue = %d pending \n", + ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt); + if ((ii >0) && (pMgmt->sNodeDBTable[ii].wEnQueueCnt > 15)) { + BSSvRemoveOneNode(pDevice, ii); + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Pending many queues PS STA Index = %d remove \n", ii); + continue; + } + } + } + + } + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->byBBType == BB_TYPE_11G)) { + + // on/off protect mode + if (WLAN_GET_ERP_USE_PROTECTION(pDevice->byERPFlag)) { + if (!pDevice->bProtectMode) { + MACvEnableProtectMD(pDevice); + pDevice->bProtectMode = true; + } + } + else { + if (pDevice->bProtectMode) { + MACvDisableProtectMD(pDevice); + pDevice->bProtectMode = false; + } + } + // on/off short slot time + + if (uNonShortSlotSTACnt > 0) { + if (pDevice->bShortSlotTime) { + pDevice->bShortSlotTime = false; + BBvSetShortSlotTime(pDevice); + vUpdateIFS((void *)pDevice); + } + } + else { + if (!pDevice->bShortSlotTime) { + pDevice->bShortSlotTime = true; + BBvSetShortSlotTime(pDevice); + vUpdateIFS((void *)pDevice); + } + } + + // on/off barker long preamble mode + + if (uLongPreambleSTACnt > 0) { + if (!pDevice->bBarkerPreambleMd) { + MACvEnableBarkerPreambleMd(pDevice); + pDevice->bBarkerPreambleMd = true; + } + } + else { + if (pDevice->bBarkerPreambleMd) { + MACvDisableBarkerPreambleMd(pDevice); + pDevice->bBarkerPreambleMd = false; + } + } + + } + + // Check if any STA in PS mode, enable DTIM multicast deliver + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (uSleepySTACnt > 0) + pMgmt->sNodeDBTable[0].bPSEnable = true; + else + pMgmt->sNodeDBTable[0].bPSEnable = false; + } + + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pCurrSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + + if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) || + (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) { + + if (pMgmt->sNodeDBTable[0].bActive) { // Assoc with BSS + + if (pDevice->bUpdateBBVGA) { + s_vCheckSensitivity(pDevice); + s_vCheckPreEDThreshold(pDevice); + } + + if ((pMgmt->sNodeDBTable[0].uInActiveCount >= (LOST_BEACON_COUNT/2)) && + (pDevice->byBBVGACurrent != pDevice->abyBBVGA[0]) ) { + pDevice->byBBVGANew = pDevice->abyBBVGA[0]; + bScheduleCommand((void *) pDevice, + WLAN_CMD_CHANGE_BBSENSITIVITY, + NULL); + } + + if (pMgmt->sNodeDBTable[0].uInActiveCount >= LOST_BEACON_COUNT) { + pMgmt->sNodeDBTable[0].bActive = false; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + pDevice->bRoaming = true; + pDevice->bIsRoaming = false; + + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost AP beacon [%d] sec, disconnected !\n", pMgmt->sNodeDBTable[0].uInActiveCount); + /* let wpa supplicant know AP may disconnect */ + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + } + } + else if (pItemSSID->len != 0) { +//Davidwang + if ((pDevice->bEnableRoaming == true)&&(!(pMgmt->Cisco_cckm))) { +DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bRoaming %d, !\n", pDevice->bRoaming ); +DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bIsRoaming %d, !\n", pDevice->bIsRoaming ); + if ((pDevice->bRoaming == true)&&(pDevice->bIsRoaming == true)){ + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fast Roaming ...\n"); + BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass); + bScheduleCommand((void *) pDevice, + WLAN_CMD_BSSID_SCAN, + pMgmt->abyDesireSSID); + bScheduleCommand((void *) pDevice, + WLAN_CMD_SSID, + pMgmt->abyDesireSSID); + pDevice->uAutoReConnectTime = 0; + pDevice->uIsroamingTime = 0; + pDevice->bRoaming = false; + } + else if ((pDevice->bRoaming == false)&&(pDevice->bIsRoaming == true)) { + pDevice->uIsroamingTime++; + if (pDevice->uIsroamingTime >= 20) + pDevice->bIsRoaming = false; + } + + } +else { + if (pDevice->uAutoReConnectTime < 10) { + pDevice->uAutoReConnectTime++; + //network manager support need not do Roaming scan??? + if(pDevice->bWPASuppWextEnabled ==true) + pDevice->uAutoReConnectTime = 0; + } + else { + //mike use old encryption status for wpa reauthen + if(pDevice->bWPADEVUp) + pDevice->eEncryptionStatus = pDevice->eOldEncryptionStatus; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming ...\n"); + BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass); + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + bScheduleCommand((void *) pDevice, + WLAN_CMD_BSSID_SCAN, + pMgmt->abyDesireSSID); + bScheduleCommand((void *) pDevice, + WLAN_CMD_SSID, + pMgmt->abyDesireSSID); + pDevice->uAutoReConnectTime = 0; + } + } + } + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + // if adhoc started which essid is NULL string, rescanning. + if ((pMgmt->eCurrState == WMAC_STATE_STARTED) && (pCurrSSID->len == 0)) { + if (pDevice->uAutoReConnectTime < 10) { + pDevice->uAutoReConnectTime++; + } + else { + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Adhoc re-scanning ...\n"); + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL); + bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL); + pDevice->uAutoReConnectTime = 0; + }; + } + if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { + + if (pDevice->bUpdateBBVGA) { + s_vCheckSensitivity(pDevice); + s_vCheckPreEDThreshold(pDevice); + } + if (pMgmt->sNodeDBTable[0].uInActiveCount >=ADHOC_LOST_BEACON_COUNT) { + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost other STA beacon [%d] sec, started !\n", pMgmt->sNodeDBTable[0].uInActiveCount); + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + pMgmt->eCurrState = WMAC_STATE_STARTED; + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + } + } + } + + if (pDevice->bLinkPass == true) { + if (netif_queue_stopped(pDevice->dev)) + netif_wake_queue(pDevice->dev); + } + + spin_unlock_irq(&pDevice->lock); + + pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ); + add_timer(&pMgmt->sTimerSecondCallback); +} + +/*+ + * + * Routine Description: + * + * + * Update Tx attemps, Tx failure counter in Node DB + * + * + * Return Value: + * none. + * +-*/ + +void BSSvUpdateNodeTxCounter(struct vnt_private *pDevice, + PSStatCounter pStatistic, u8 byTSR, u8 byPktNO) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u32 uNodeIndex = 0; + u8 byTxRetry; + u16 wRate; + u16 wFallBackRate = RATE_1M; + u8 byFallBack; + int ii; + u8 *pbyDestAddr; + u8 byPktNum; + u16 wFIFOCtl; + + byPktNum = (byPktNO & 0x0F) >> 4; + byTxRetry = (byTSR & 0xF0) >> 4; + wRate = (u16) (byPktNO & 0xF0) >> 4; + wFIFOCtl = pStatistic->abyTxPktInfo[byPktNum].wFIFOCtl; + pbyDestAddr = (u8 *) &( pStatistic->abyTxPktInfo[byPktNum].abyDestAddr[0]); + + if (wFIFOCtl & FIFOCTL_AUTO_FB_0) { + byFallBack = AUTO_FB_0; + } else if (wFIFOCtl & FIFOCTL_AUTO_FB_1) { + byFallBack = AUTO_FB_1; + } else { + byFallBack = AUTO_FB_NONE; + } + + // Only Unicast using support rates + if (wFIFOCtl & FIFOCTL_NEEDACK) { + if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) { + pMgmt->sNodeDBTable[0].uTxAttempts += 1; + if ( !(byTSR & (TSR_TMO | TSR_RETRYTMO))) { + // transmit success, TxAttempts at least plus one + pMgmt->sNodeDBTable[0].uTxOk[MAX_RATE]++; + if ( (byFallBack == AUTO_FB_NONE) || + (wRate < RATE_18M) ) { + wFallBackRate = wRate; + } else if (byFallBack == AUTO_FB_0) { + if (byTxRetry < 5) + wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry]; + else + wFallBackRate = awHWRetry0[wRate-RATE_18M][4]; + } else if (byFallBack == AUTO_FB_1) { + if (byTxRetry < 5) + wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry]; + else + wFallBackRate = awHWRetry1[wRate-RATE_18M][4]; + } + pMgmt->sNodeDBTable[0].uTxOk[wFallBackRate]++; + } else { + pMgmt->sNodeDBTable[0].uTxFailures ++; + } + pMgmt->sNodeDBTable[0].uTxRetry += byTxRetry; + if (byTxRetry != 0) { + pMgmt->sNodeDBTable[0].uTxFail[MAX_RATE]+=byTxRetry; + if ( (byFallBack == AUTO_FB_NONE) || + (wRate < RATE_18M) ) { + pMgmt->sNodeDBTable[0].uTxFail[wRate]+=byTxRetry; + } else if (byFallBack == AUTO_FB_0) { + for (ii = 0; ii < byTxRetry; ii++) { + if (ii < 5) + wFallBackRate = + awHWRetry0[wRate-RATE_18M][ii]; + else + wFallBackRate = + awHWRetry0[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++; + } + } else if (byFallBack == AUTO_FB_1) { + for (ii = 0; ii < byTxRetry; ii++) { + if (ii < 5) + wFallBackRate = + awHWRetry1[wRate-RATE_18M][ii]; + else + wFallBackRate = + awHWRetry1[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++; + } + } + } + } + + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) || + (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { + + if (BSSbIsSTAInNodeDB((void *) pDevice, + pbyDestAddr, + &uNodeIndex)) { + pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts += 1; + if ( !(byTSR & (TSR_TMO | TSR_RETRYTMO))) { + // transmit success, TxAttempts at least plus one + pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++; + if ( (byFallBack == AUTO_FB_NONE) || + (wRate < RATE_18M) ) { + wFallBackRate = wRate; + } else if (byFallBack == AUTO_FB_0) { + if (byTxRetry < 5) + wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry]; + else + wFallBackRate = awHWRetry0[wRate-RATE_18M][4]; + } else if (byFallBack == AUTO_FB_1) { + if (byTxRetry < 5) + wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry]; + else + wFallBackRate = awHWRetry1[wRate-RATE_18M][4]; + } + pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wFallBackRate]++; + } else { + pMgmt->sNodeDBTable[uNodeIndex].uTxFailures ++; + } + pMgmt->sNodeDBTable[uNodeIndex].uTxRetry += byTxRetry; + if (byTxRetry != 0) { + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[MAX_RATE]+=byTxRetry; + if ( (byFallBack == AUTO_FB_NONE) || + (wRate < RATE_18M) ) { + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wRate]+=byTxRetry; + } else if (byFallBack == AUTO_FB_0) { + for (ii = 0; ii < byTxRetry; ii++) { + if (ii < 5) + wFallBackRate = + awHWRetry0[wRate-RATE_18M][ii]; + else + wFallBackRate = + awHWRetry0[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++; + } + } else if (byFallBack == AUTO_FB_1) { + for (ii = 0; ii < byTxRetry; ii++) { + if (ii < 5) + wFallBackRate = awHWRetry1[wRate-RATE_18M][ii]; + else + wFallBackRate = awHWRetry1[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++; + } + } + } + } + } + } +} + +/*+ + * + * Routine Description: + * Clear Nodes & skb in DB Table + * + * + * Parameters: + * In: + * hDeviceContext - The adapter context. + * uStartIndex - starting index + * Out: + * none + * + * Return Value: + * None. + * +-*/ + +void BSSvClearNodeDBTable(struct vnt_private *pDevice, u32 uStartIndex) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct sk_buff *skb; + int ii; + + for (ii = uStartIndex; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive) { + // check if sTxPSQueue has been initial + if (pMgmt->sNodeDBTable[ii].sTxPSQueue.next != NULL) { + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL){ + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS skb != NULL %d\n", ii); + dev_kfree_skb(skb); + } + } + memset(&pMgmt->sNodeDBTable[ii], 0, sizeof(KnownNodeDB)); + } + } +}; + +static void s_vCheckSensitivity(struct vnt_private *pDevice) +{ + PKnownBSS pBSSList = NULL; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int ii; + + if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { + pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID); + if (pBSSList != NULL) { + /* Update BB register if RSSI is too strong */ + signed long LocalldBmAverage = 0; + signed long uNumofdBm = 0; + for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { + if (pBSSList->ldBmAverage[ii] != 0) { + uNumofdBm ++; + LocalldBmAverage += pBSSList->ldBmAverage[ii]; + } + } + if (uNumofdBm > 0) { + LocalldBmAverage = LocalldBmAverage/uNumofdBm; + for (ii=0;ii<BB_VGA_LEVEL;ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LocalldBmAverage:%ld, %ld %02x\n", LocalldBmAverage, pDevice->ldBmThreshold[ii], pDevice->abyBBVGA[ii]); + if (LocalldBmAverage < pDevice->ldBmThreshold[ii]) { + pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; + break; + } + } + if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { + pDevice->uBBVGADiffCount++; + if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) + bScheduleCommand(pDevice, + WLAN_CMD_CHANGE_BBSENSITIVITY, + NULL); + } else { + pDevice->uBBVGADiffCount = 0; + } + } + } + } +} + +static void s_uCalculateLinkQual(struct vnt_private *pDevice) +{ + unsigned long TxOkRatio, TxCnt; + unsigned long RxOkRatio, RxCnt; + unsigned long RssiRatio; + long ldBm; + +TxCnt = pDevice->scStatistic.TxNoRetryOkCount + + pDevice->scStatistic.TxRetryOkCount + + pDevice->scStatistic.TxFailCount; +RxCnt = pDevice->scStatistic.RxFcsErrCnt + + pDevice->scStatistic.RxOkCnt; +TxOkRatio = (TxCnt < 6) ? 4000:((pDevice->scStatistic.TxNoRetryOkCount * 4000) / TxCnt); +RxOkRatio = (RxCnt < 6) ? 2000:((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt); +//decide link quality +if(pDevice->bLinkPass !=true) +{ + pDevice->scStatistic.LinkQuality = 0; + pDevice->scStatistic.SignalStren = 0; +} +else +{ + RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm); + if(-ldBm < 50) { + RssiRatio = 4000; + } + else if(-ldBm > 90) { + RssiRatio = 0; + } + else { + RssiRatio = (40-(-ldBm-50))*4000/40; + } + pDevice->scStatistic.SignalStren = RssiRatio/40; + pDevice->scStatistic.LinkQuality = (RssiRatio+TxOkRatio+RxOkRatio)/100; +} + pDevice->scStatistic.RxFcsErrCnt = 0; + pDevice->scStatistic.RxOkCnt = 0; + pDevice->scStatistic.TxFailCount = 0; + pDevice->scStatistic.TxNoRetryOkCount = 0; + pDevice->scStatistic.TxRetryOkCount = 0; +} + +void BSSvClearAnyBSSJoinRecord(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int ii; + + for (ii = 0; ii < MAX_BSS_NUM; ii++) + pMgmt->sBSSList[ii].bSelected = false; + + return; +} + +static void s_vCheckPreEDThreshold(struct vnt_private *pDevice) +{ + PKnownBSS pBSSList = NULL; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { + pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID); + if (pBSSList != NULL) { + pDevice->byBBPreEDRSSI = (u8) (~(pBSSList->ldBmAverRange) + 1); + BBvUpdatePreEDThreshold(pDevice, false); + } + } +} + diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h new file mode 100644 index 00000000..bce3b465 --- /dev/null +++ b/drivers/staging/vt6656/bssdb.h @@ -0,0 +1,278 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: bssdb.h + * + * Purpose: Handles the Basic Service Set & Node Database functions + * + * Author: Lyndon Chen + * + * Date: July 16, 2002 + * + */ + +#ifndef __BSSDB_H__ +#define __BSSDB_H__ + +#include <linux/skbuff.h> +#include "80211hdr.h" +#include "80211mgr.h" +#include "card.h" +#include "mib.h" + +#define MAX_NODE_NUM 64 +#define MAX_BSS_NUM 42 +#define LOST_BEACON_COUNT 10 /* 10 sec, XP defined */ +#define MAX_PS_TX_BUF 32 // sta max power saving tx buf +#define ADHOC_LOST_BEACON_COUNT 30 // 30 sec, beacon lost for adhoc only +#define MAX_INACTIVE_COUNT 300 // 300 sec, inactive STA node refresh + +#define USE_PROTECT_PERIOD 10 // 10 sec, Use protect mode check period +#define ERP_RECOVER_COUNT 30 // 30 sec, ERP support callback check +#define BSS_CLEAR_COUNT 1 + +#define RSSI_STAT_COUNT 10 +#define MAX_CHECK_RSSI_COUNT 8 + +// STA dwflags +#define WLAN_STA_AUTH BIT0 +#define WLAN_STA_ASSOC BIT1 +#define WLAN_STA_PS BIT2 +#define WLAN_STA_TIM BIT3 +// permanent; do not remove entry on expiration +#define WLAN_STA_PERM BIT4 +// If 802.1X is used, this flag is +// controlling whether STA is authorized to +// send and receive non-IEEE 802.1X frames +#define WLAN_STA_AUTHORIZED BIT5 + +#define MAX_WPA_IE_LEN 64 + +// +// IEEE 802.11 Structures and definitions +// + +typedef struct tagSERPObject { + bool bERPExist; + u8 byERP; +} ERPObject, *PERPObject; + +typedef struct tagSRSNCapObject { + bool bRSNCapExist; + u16 wRSNCap; +} SRSNCapObject, *PSRSNCapObject; + +// BSS info(AP) +typedef struct tagKnownBSS { + // BSS info + bool bActive; + u8 abyBSSID[WLAN_BSSID_LEN]; + unsigned int uChannel; + u8 abySuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + u8 abyExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + unsigned int uRSSI; + u8 bySQ; + u16 wBeaconInterval; + u16 wCapInfo; + u8 abySSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + u8 byRxRate; + +// u16 wATIMWindow; + u8 byRSSIStatCnt; + signed long ldBmMAX; + signed long ldBmAverage[RSSI_STAT_COUNT]; + signed long ldBmAverRange; + //For any BSSID selection improvment + bool bSelected; + + //++ WPA informations + bool bWPAValid; + u8 byGKType; + u8 abyPKType[4]; + u16 wPKCount; + u8 abyAuthType[4]; + u16 wAuthCount; + u8 byDefaultK_as_PK; + u8 byReplayIdx; + //-- + + //++ WPA2 informations + bool bWPA2Valid; + u8 byCSSGK; + u16 wCSSPKCount; + u8 abyCSSPK[4]; + u16 wAKMSSAuthCount; + u8 abyAKMSSAuthType[4]; + + //++ wpactl + u8 byWPAIE[MAX_WPA_IE_LEN]; + u8 byRSNIE[MAX_WPA_IE_LEN]; + u16 wWPALen; + u16 wRSNLen; + + // Clear count + unsigned int uClearCount; +// u8 abyIEs[WLAN_BEACON_FR_MAXLEN]; + unsigned int uIELength; + u64 qwBSSTimestamp; + u64 qwLocalTSF;/* local TSF timer */ + + CARD_PHY_TYPE eNetworkTypeInUse; + + ERPObject sERP; + SRSNCapObject sRSNCapObj; + u8 abyIEs[1024]; // don't move this field !! + +} __attribute__ ((__packed__)) +KnownBSS , *PKnownBSS; + +typedef enum tagNODE_STATE { + NODE_FREE, + NODE_AGED, + NODE_KNOWN, + NODE_AUTH, + NODE_ASSOC +} NODE_STATE, *PNODE_STATE; + +// STA node info +typedef struct tagKnownNodeDB { + // STA info + bool bActive; + u8 abyMACAddr[WLAN_ADDR_LEN]; + u8 abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN]; + u8 abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN]; + u16 wTxDataRate; + bool bShortPreamble; + bool bERPExist; + bool bShortSlotTime; + unsigned int uInActiveCount; + u16 wMaxBasicRate; //Get from byTopOFDMBasicRate or byTopCCKBasicRate which depends on packetTyp. + u16 wMaxSuppRate; //Records the highest supported rate getting from SuppRates IE and ExtSuppRates IE in Beacon. + u16 wSuppRate; + u8 byTopOFDMBasicRate;//Records the highest basic rate in OFDM mode + u8 byTopCCKBasicRate; //Records the highest basic rate in CCK mode + + // For AP mode + struct sk_buff_head sTxPSQueue; + u16 wCapInfo; + u16 wListenInterval; + u16 wAID; + NODE_STATE eNodeState; + bool bPSEnable; + bool bRxPSPoll; + u8 byAuthSequence; + unsigned long ulLastRxJiffer; + u8 bySuppRate; + u32 dwFlags; + u16 wEnQueueCnt; + + bool bOnFly; + unsigned long long KeyRSC; + u8 byKeyIndex; + u32 dwKeyIndex; + u8 byCipherSuite; + u32 dwTSC47_16; + u16 wTSC15_0; + unsigned int uWepKeyLength; + u8 abyWepKey[WLAN_WEPMAX_KEYLEN]; + // + // Auto rate fallback vars + bool bIsInFallback; + unsigned int uAverageRSSI; + unsigned int uRateRecoveryTimeout; + unsigned int uRatePollTimeout; + unsigned int uTxFailures; + unsigned int uTxAttempts; + + unsigned int uTxRetry; + unsigned int uFailureRatio; + unsigned int uRetryRatio; + unsigned int uTxOk[MAX_RATE+1]; + unsigned int uTxFail[MAX_RATE+1]; + unsigned int uTimeCount; + +} KnownNodeDB, *PKnownNodeDB; + +PKnownBSS BSSpSearchBSSList(struct vnt_private *, u8 *pbyDesireBSSID, + u8 *pbyDesireSSID, CARD_PHY_TYPE ePhyType); + +PKnownBSS BSSpAddrIsInBSSList(struct vnt_private *, u8 *abyBSSID, + PWLAN_IE_SSID pSSID); + +void BSSvClearBSSList(struct vnt_private *, int bKeepCurrBSSID); + +int BSSbInsertToBSSList(struct vnt_private *, + u8 *abyBSSIDAddr, + u64 qwTimestamp, + u16 wBeaconInterval, + u16 wCapInfo, + u8 byCurrChannel, + PWLAN_IE_SSID pSSID, + PWLAN_IE_SUPP_RATES pSuppRates, + PWLAN_IE_SUPP_RATES pExtSuppRates, + PERPObject psERP, + PWLAN_IE_RSN pRSN, + PWLAN_IE_RSN_EXT pRSNWPA, + PWLAN_IE_COUNTRY pIE_Country, + PWLAN_IE_QUIET pIE_Quiet, + u32 uIELength, + u8 *pbyIEs, + void *pRxPacketContext); + +int BSSbUpdateToBSSList(struct vnt_private *, + u64 qwTimestamp, + u16 wBeaconInterval, + u16 wCapInfo, + u8 byCurrChannel, + int bChannelHit, + PWLAN_IE_SSID pSSID, + PWLAN_IE_SUPP_RATES pSuppRates, + PWLAN_IE_SUPP_RATES pExtSuppRates, + PERPObject psERP, + PWLAN_IE_RSN pRSN, + PWLAN_IE_RSN_EXT pRSNWPA, + PWLAN_IE_COUNTRY pIE_Country, + PWLAN_IE_QUIET pIE_Quiet, + PKnownBSS pBSSList, + u32 uIELength, + u8 *pbyIEs, + void *pRxPacketContext); + +int BSSbIsSTAInNodeDB(struct vnt_private *, u8 * abyDstAddr, + u32 *puNodeIndex); + +void BSSvCreateOneNode(struct vnt_private *, u32 *puNodeIndex); + +void BSSvUpdateAPNode(struct vnt_private *, u16 *pwCapInfo, + PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pExtSuppRates); + +void BSSvSecondCallBack(struct vnt_private *); + +void BSSvUpdateNodeTxCounter(struct vnt_private *, PSStatCounter pStatistic, + u8 byTSR, u8 byPktNO); + +void BSSvRemoveOneNode(struct vnt_private *, u32 uNodeIndex); + +void BSSvAddMulticastNode(struct vnt_private *); + +void BSSvClearNodeDBTable(struct vnt_private *, u32 uStartIndex); + +void BSSvClearAnyBSSJoinRecord(struct vnt_private *); + +#endif /* __BSSDB_H__ */ diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c new file mode 100644 index 00000000..0beb246a --- /dev/null +++ b/drivers/staging/vt6656/card.c @@ -0,0 +1,996 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: card.c + * Purpose: Provide functions to setup NIC operation mode + * Functions: + * s_vSafeResetTx - Rest Tx + * CARDvSetRSPINF - Set RSPINF + * vUpdateIFS - Update slotTime,SIFS,DIFS, and EIFS + * CARDvUpdateBasicTopRate - Update BasicTopRate + * CARDbAddBasicRate - Add to BasicRateSet + * CARDbSetBasicRate - Set Basic Tx Rate + * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet + * CARDvSetLoopbackMode - Set Loopback mode + * CARDbSoftwareReset - Sortware reset NIC + * CARDqGetTSFOffset - Calculate TSFOffset + * CARDbGetCurrentTSF - Read Current NIC TSF counter + * CARDqGetNextTBTT - Calculate Next Beacon TSF counter + * CARDvSetFirstNextTBTT - Set NIC Beacon time + * CARDvUpdateNextTBTT - Sync. NIC Beacon time + * CARDbRadioPowerOff - Turn Off NIC Radio Power + * CARDbRadioPowerOn - Turn On NIC Radio Power + * CARDbSetWEPMode - Set NIC Wep mode + * CARDbSetTxPower - Set NIC tx power + * + * Revision History: + * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-26-2003 Kyle Hsu: Modify the definition type of dwIoBase. + * 09-01-2003 Bryan YC Fan: Add vUpdateIFS(). + * + */ + +#include "device.h" +#include "tmacro.h" +#include "card.h" +#include "baseband.h" +#include "mac.h" +#include "desc.h" +#include "rf.h" +#include "power.h" +#include "key.h" +#include "rc4.h" +#include "country.h" +#include "datarate.h" +#include "rndis.h" +#include "control.h" + +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +//const u16 cwRXBCNTSFOff[MAX_RATE] = +//{17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; + +const u16 cwRXBCNTSFOff[MAX_RATE] = +{192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3}; + +/* + * Description: Set NIC media channel + * + * Parameters: + * In: + * pDevice - The adapter to be set + * uConnectionChannel - Channel to be set + * Out: + * none + */ +void CARDbSetMediaChannel(struct vnt_private *pDevice, u32 uConnectionChannel) +{ + + if (pDevice->byBBType == BB_TYPE_11A) { // 15 ~ 38 + if ((uConnectionChannel < (CB_MAX_CHANNEL_24G+1)) || (uConnectionChannel > CB_MAX_CHANNEL)) + uConnectionChannel = (CB_MAX_CHANNEL_24G+1); + } else { + if ((uConnectionChannel > CB_MAX_CHANNEL_24G) || (uConnectionChannel == 0)) // 1 ~ 14 + uConnectionChannel = 1; + } + + // clear NAV + MACvRegBitsOn(pDevice, MAC_REG_MACCR, MACCR_CLRNAV); + + // Set Channel[7] = 0 to tell H/W channel is changing now. + MACvRegBitsOff(pDevice, MAC_REG_CHANNEL, 0x80); + + //if (pMgmt->uCurrChannel == uConnectionChannel) + // return bResult; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_SELECT_CHANNLE, + (u16) uConnectionChannel, + 0, + 0, + NULL + ); + + //{{ RobertYu: 20041202 + //// TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput + + if (pDevice->byBBType == BB_TYPE_11A) { + pDevice->byCurPwr = 0xFF; + RFbRawSetPower(pDevice, pDevice->abyOFDMAPwrTbl[uConnectionChannel-15], RATE_54M); + } else if (pDevice->byBBType == BB_TYPE_11G) { + pDevice->byCurPwr = 0xFF; + RFbRawSetPower(pDevice, pDevice->abyOFDMPwrTbl[uConnectionChannel-1], RATE_54M); + } else { + pDevice->byCurPwr = 0xFF; + RFbRawSetPower(pDevice, pDevice->abyCCKPwrTbl[uConnectionChannel-1], RATE_1M); + } + ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_CHANNEL,(u8)(uConnectionChannel|0x80)); +} + +/* + * Description: Get CCK mode basic rate + * + * Parameters: + * In: + * pDevice - The adapter to be set + * wRateIdx - Receiving data rate + * Out: + * none + * + * Return Value: response Control frame rate + * + */ +static u16 swGetCCKControlRate(struct vnt_private *pDevice, u16 wRateIdx) +{ + u16 ui = wRateIdx; + + while (ui > RATE_1M) { + if (pDevice->wBasicRate & (1 << ui)) + return ui; + ui--; + } + + return RATE_1M; +} + +/* + * Description: Get OFDM mode basic rate + * + * Parameters: + * In: + * pDevice - The adapter to be set + * wRateIdx - Receiving data rate + * Out: + * none + * + * Return Value: response Control frame rate + * + */ +static u16 swGetOFDMControlRate(struct vnt_private *pDevice, u16 wRateIdx) +{ + u16 ui = wRateIdx; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BASIC RATE: %X\n", + pDevice->wBasicRate); + + if (!CARDbIsOFDMinBasicRate(pDevice)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "swGetOFDMControlRate:(NO OFDM) %d\n", wRateIdx); + if (wRateIdx > RATE_24M) + wRateIdx = RATE_24M; + return wRateIdx; + } + + while (ui > RATE_11M) { + if (pDevice->wBasicRate & (1 << ui)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "swGetOFDMControlRate: %d\n", ui); + return ui; + } + ui--; + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"swGetOFDMControlRate: 6M\n"); + + return RATE_24M; +} + +/* + * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode. + * + * Parameters: + * In: + * wRate - Tx Rate + * byPktType - Tx Packet type + * Out: + * pbyTxRate - pointer to RSPINF TxRate field + * pbyRsvTime - pointer to RSPINF RsvTime field + * + * Return Value: none + * + */ +void +CARDvCalculateOFDMRParameter ( + u16 wRate, + u8 byBBType, + u8 * pbyTxRate, + u8 * pbyRsvTime + ) +{ + switch (wRate) { + case RATE_6M : + if (byBBType == BB_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9B; + *pbyRsvTime = 24; + } + else { + *pbyTxRate = 0x8B; + *pbyRsvTime = 30; + } + break; + + case RATE_9M : + if (byBBType == BB_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9F; + *pbyRsvTime = 16; + } + else { + *pbyTxRate = 0x8F; + *pbyRsvTime = 22; + } + break; + + case RATE_12M : + if (byBBType == BB_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9A; + *pbyRsvTime = 12; + } + else { + *pbyTxRate = 0x8A; + *pbyRsvTime = 18; + } + break; + + case RATE_18M : + if (byBBType == BB_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9E; + *pbyRsvTime = 8; + } + else { + *pbyTxRate = 0x8E; + *pbyRsvTime = 14; + } + break; + + case RATE_36M : + if (byBBType == BB_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9D; + *pbyRsvTime = 4; + } + else { + *pbyTxRate = 0x8D; + *pbyRsvTime = 10; + } + break; + + case RATE_48M : + if (byBBType == BB_TYPE_11A) {//5GHZ + *pbyTxRate = 0x98; + *pbyRsvTime = 4; + } + else { + *pbyTxRate = 0x88; + *pbyRsvTime = 10; + } + break; + + case RATE_54M : + if (byBBType == BB_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9C; + *pbyRsvTime = 4; + } + else { + *pbyTxRate = 0x8C; + *pbyRsvTime = 10; + } + break; + + case RATE_24M : + default : + if (byBBType == BB_TYPE_11A) {//5GHZ + *pbyTxRate = 0x99; + *pbyRsvTime = 8; + } + else { + *pbyTxRate = 0x89; + *pbyRsvTime = 14; + } + break; + } +} + +/* + * Description: Set RSPINF + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: None. + * + */ +void CARDvSetRSPINF(struct vnt_private *pDevice, u8 byBBType) +{ + u8 abyServ[4] = {0, 0, 0, 0}; /* For CCK */ + u8 abySignal[4] = {0, 0, 0, 0}; + u16 awLen[4] = {0, 0, 0, 0}; + u8 abyTxRate[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; /* For OFDM */ + u8 abyRsvTime[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + u8 abyData[34]; + int i; + + //RSPINF_b_1 + BBvCalculateParameter(pDevice, + 14, + swGetCCKControlRate(pDevice, RATE_1M), + PK_TYPE_11B, + &awLen[0], + &abyServ[0], + &abySignal[0] + ); + + ///RSPINF_b_2 + BBvCalculateParameter(pDevice, + 14, + swGetCCKControlRate(pDevice, RATE_2M), + PK_TYPE_11B, + &awLen[1], + &abyServ[1], + &abySignal[1] + ); + + //RSPINF_b_5 + BBvCalculateParameter(pDevice, + 14, + swGetCCKControlRate(pDevice, RATE_5M), + PK_TYPE_11B, + &awLen[2], + &abyServ[2], + &abySignal[2] + ); + + //RSPINF_b_11 + BBvCalculateParameter(pDevice, + 14, + swGetCCKControlRate(pDevice, RATE_11M), + PK_TYPE_11B, + &awLen[3], + &abyServ[3], + &abySignal[3] + ); + + //RSPINF_a_6 + CARDvCalculateOFDMRParameter (RATE_6M, + byBBType, + &abyTxRate[0], + &abyRsvTime[0]); + + //RSPINF_a_9 + CARDvCalculateOFDMRParameter (RATE_9M, + byBBType, + &abyTxRate[1], + &abyRsvTime[1]); + + //RSPINF_a_12 + CARDvCalculateOFDMRParameter (RATE_12M, + byBBType, + &abyTxRate[2], + &abyRsvTime[2]); + + //RSPINF_a_18 + CARDvCalculateOFDMRParameter (RATE_18M, + byBBType, + &abyTxRate[3], + &abyRsvTime[3]); + + //RSPINF_a_24 + CARDvCalculateOFDMRParameter (RATE_24M, + byBBType, + &abyTxRate[4], + &abyRsvTime[4]); + + //RSPINF_a_36 + CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_36M), + byBBType, + &abyTxRate[5], + &abyRsvTime[5]); + + //RSPINF_a_48 + CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_48M), + byBBType, + &abyTxRate[6], + &abyRsvTime[6]); + + //RSPINF_a_54 + CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_54M), + byBBType, + &abyTxRate[7], + &abyRsvTime[7]); + + //RSPINF_a_72 + CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_54M), + byBBType, + &abyTxRate[8], + &abyRsvTime[8]); + + abyData[0] = (u8)(awLen[0]&0xFF); + abyData[1] = (u8)(awLen[0]>>8); + abyData[2] = abySignal[0]; + abyData[3] = abyServ[0]; + + abyData[4] = (u8)(awLen[1]&0xFF); + abyData[5] = (u8)(awLen[1]>>8); + abyData[6] = abySignal[1]; + abyData[7] = abyServ[1]; + + abyData[8] = (u8)(awLen[2]&0xFF); + abyData[9] = (u8)(awLen[2]>>8); + abyData[10] = abySignal[2]; + abyData[11] = abyServ[2]; + + abyData[12] = (u8)(awLen[3]&0xFF); + abyData[13] = (u8)(awLen[3]>>8); + abyData[14] = abySignal[3]; + abyData[15] = abyServ[3]; + + for (i = 0; i < 9; i++) { + abyData[16+i*2] = abyTxRate[i]; + abyData[16+i*2+1] = abyRsvTime[i]; + } + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + MAC_REG_RSPINF_B_1, + MESSAGE_REQUEST_MACREG, + 34, + &abyData[0]); + +} + +/* + * Description: Update IFS + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: None. + * + */ +void vUpdateIFS(struct vnt_private *pDevice) +{ + u8 byMaxMin = 0; + u8 byData[4]; + + if (pDevice->byPacketType==PK_TYPE_11A) {//0000 0000 0000 0000,11a + pDevice->uSlot = C_SLOT_SHORT; + pDevice->uSIFS = C_SIFS_A; + pDevice->uDIFS = C_SIFS_A + 2*C_SLOT_SHORT; + pDevice->uCwMin = C_CWMIN_A; + byMaxMin = 4; + } + else if (pDevice->byPacketType==PK_TYPE_11B) {//0000 0001 0000 0000,11b + pDevice->uSlot = C_SLOT_LONG; + pDevice->uSIFS = C_SIFS_BG; + pDevice->uDIFS = C_SIFS_BG + 2*C_SLOT_LONG; + pDevice->uCwMin = C_CWMIN_B; + byMaxMin = 5; + } + else {// PK_TYPE_11GA & PK_TYPE_11GB + u8 byRate = 0; + bool bOFDMRate = false; + unsigned int ii = 0; + PWLAN_IE_SUPP_RATES pItemRates = NULL; + + pDevice->uSIFS = C_SIFS_BG; + if (pDevice->bShortSlotTime) { + pDevice->uSlot = C_SLOT_SHORT; + } else { + pDevice->uSlot = C_SLOT_LONG; + } + pDevice->uDIFS = C_SIFS_BG + 2*pDevice->uSlot; + + pItemRates = (PWLAN_IE_SUPP_RATES)pDevice->vnt_mgmt.abyCurrSuppRates; + for (ii = 0; ii < pItemRates->len; ii++) { + byRate = (u8)(pItemRates->abyRates[ii]&0x7F); + if (RATEwGetRateIdx(byRate) > RATE_11M) { + bOFDMRate = true; + break; + } + } + if (bOFDMRate == false) { + pItemRates = (PWLAN_IE_SUPP_RATES)pDevice->vnt_mgmt + .abyCurrExtSuppRates; + for (ii = 0; ii < pItemRates->len; ii++) { + byRate = (u8)(pItemRates->abyRates[ii]&0x7F); + if (RATEwGetRateIdx(byRate) > RATE_11M) { + bOFDMRate = true; + break; + } + } + } + if (bOFDMRate == true) { + pDevice->uCwMin = C_CWMIN_A; + byMaxMin = 4; + } else { + pDevice->uCwMin = C_CWMIN_B; + byMaxMin = 5; + } + } + + pDevice->uCwMax = C_CWMAX; + pDevice->uEIFS = C_EIFS; + + byData[0] = (u8)pDevice->uSIFS; + byData[1] = (u8)pDevice->uDIFS; + byData[2] = (u8)pDevice->uEIFS; + byData[3] = (u8)pDevice->uSlot; + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + MAC_REG_SIFS, + MESSAGE_REQUEST_MACREG, + 4, + &byData[0]); + + byMaxMin |= 0xA0;//1010 1111,C_CWMAX = 1023 + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + MAC_REG_CWMAXMIN0, + MESSAGE_REQUEST_MACREG, + 1, + &byMaxMin); +} + +void CARDvUpdateBasicTopRate(struct vnt_private *pDevice) +{ + u8 byTopOFDM = RATE_24M, byTopCCK = RATE_1M; + u8 ii; + + //Determines the highest basic rate. + for (ii = RATE_54M; ii >= RATE_6M; ii --) { + if ( (pDevice->wBasicRate) & ((u16)(1<<ii)) ) { + byTopOFDM = ii; + break; + } + } + pDevice->byTopOFDMBasicRate = byTopOFDM; + + for (ii = RATE_11M;; ii --) { + if ( (pDevice->wBasicRate) & ((u16)(1<<ii)) ) { + byTopCCK = ii; + break; + } + if (ii == RATE_1M) + break; + } + pDevice->byTopCCKBasicRate = byTopCCK; + } + +/* + * Description: Set NIC Tx Basic Rate + * + * Parameters: + * In: + * pDevice - The adapter to be set + * wBasicRate - Basic Rate to be set + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +void CARDbAddBasicRate(struct vnt_private *pDevice, u16 wRateIdx) +{ + u16 wRate = (1 << wRateIdx); + + pDevice->wBasicRate |= wRate; + + //Determines the highest basic rate. + CARDvUpdateBasicTopRate(pDevice); +} + +int CARDbIsOFDMinBasicRate(struct vnt_private *pDevice) +{ + int ii; + + for (ii = RATE_54M; ii >= RATE_6M; ii --) { + if ((pDevice->wBasicRate) & ((u16)(1<<ii))) + return true; + } + return false; +} + +u8 CARDbyGetPktType(struct vnt_private *pDevice) +{ + + if (pDevice->byBBType == BB_TYPE_11A || pDevice->byBBType == BB_TYPE_11B) { + return (u8)pDevice->byBBType; + } + else if (CARDbIsOFDMinBasicRate(pDevice)) { + return PK_TYPE_11GA; + } + else { + return PK_TYPE_11GB; + } +} + +/* + * Description: Calculate TSF offset of two TSF input + * Get TSF Offset from RxBCN's TSF and local TSF + * + * Parameters: + * In: + * pDevice - The adapter to be sync. + * qwTSF1 - Rx BCN's TSF + * qwTSF2 - Local TSF + * Out: + * none + * + * Return Value: TSF Offset value + * + */ +u64 CARDqGetTSFOffset(u8 byRxRate, u64 qwTSF1, u64 qwTSF2) +{ + u64 qwTSFOffset = 0; + u16 wRxBcnTSFOffst = 0; + + wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate % MAX_RATE]; + + qwTSF2 += (u64)wRxBcnTSFOffst; + + qwTSFOffset = qwTSF1 - qwTSF2; + + return qwTSFOffset; +} + +/* + * Description: Sync. TSF counter to BSS + * Get TSF offset and write to HW + * + * Parameters: + * In: + * pDevice - The adapter to be sync. + * qwBSSTimestamp - Rx BCN's TSF + * qwLocalTSF - Local TSF + * Out: + * none + * + * Return Value: none + * + */ +void CARDvAdjustTSF(struct vnt_private *pDevice, u8 byRxRate, + u64 qwBSSTimestamp, u64 qwLocalTSF) +{ + u64 qwTSFOffset = 0; + u8 pbyData[8]; + + qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, qwLocalTSF); + // adjust TSF + // HW's TSF add TSF Offset reg + + pbyData[0] = (u8)qwTSFOffset; + pbyData[1] = (u8)(qwTSFOffset >> 8); + pbyData[2] = (u8)(qwTSFOffset >> 16); + pbyData[3] = (u8)(qwTSFOffset >> 24); + pbyData[4] = (u8)(qwTSFOffset >> 32); + pbyData[5] = (u8)(qwTSFOffset >> 40); + pbyData[6] = (u8)(qwTSFOffset >> 48); + pbyData[7] = (u8)(qwTSFOffset >> 56); + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_SET_TSFTBTT, + MESSAGE_REQUEST_TSF, + 0, + 8, + pbyData + ); + +} +/* + * Description: Read NIC TSF counter + * Get local TSF counter + * + * Parameters: + * In: + * pDevice - The adapter to be read + * Out: + * qwCurrTSF - Current TSF counter + * + * Return Value: true if success; otherwise false + * + */ +bool CARDbGetCurrentTSF(struct vnt_private *pDevice, u64 *pqwCurrTSF) +{ + + *pqwCurrTSF = pDevice->qwCurrTSF; + + return true; +} + +/* + * Description: Clear NIC TSF counter + * Clear local TSF counter + * + * Parameters: + * In: + * pDevice - The adapter to be read + * + * Return Value: true if success; otherwise false + * + */ +bool CARDbClearCurrentTSF(struct vnt_private *pDevice) +{ + + MACvRegBitsOn(pDevice, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); + + pDevice->qwCurrTSF = 0; + + return true; +} + +/* + * Description: Read NIC TSF counter + * Get NEXTTBTT from adjusted TSF and Beacon Interval + * + * Parameters: + * In: + * qwTSF - Current TSF counter + * wbeaconInterval - Beacon Interval + * Out: + * qwCurrTSF - Current TSF counter + * + * Return Value: TSF value of next Beacon + * + */ +u64 CARDqGetNextTBTT(u64 qwTSF, u16 wBeaconInterval) +{ + + unsigned int uLowNextTBTT; + unsigned int uHighRemain, uLowRemain; + unsigned int uBeaconInterval; + + uBeaconInterval = wBeaconInterval * 1024; + // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval + uLowNextTBTT = ((qwTSF & 0xffffffffULL) >> 10) << 10; + uLowRemain = (uLowNextTBTT) % uBeaconInterval; + uHighRemain = ((0x80000000 % uBeaconInterval) * 2 * (u32)(qwTSF >> 32)) + % uBeaconInterval; + uLowRemain = (uHighRemain + uLowRemain) % uBeaconInterval; + uLowRemain = uBeaconInterval - uLowRemain; + + // check if carry when add one beacon interval + if ((~uLowNextTBTT) < uLowRemain) + qwTSF = ((qwTSF >> 32) + 1) << 32; + + qwTSF = (qwTSF & 0xffffffff00000000ULL) | + (u64)(uLowNextTBTT + uLowRemain); + + return (qwTSF); +} + +/* + * Description: Set NIC TSF counter for first Beacon time + * Get NEXTTBTT from adjusted TSF and Beacon Interval + * + * Parameters: + * In: + * dwIoBase - IO Base + * wBeaconInterval - Beacon Interval + * Out: + * none + * + * Return Value: none + * + */ +void CARDvSetFirstNextTBTT(struct vnt_private *pDevice, u16 wBeaconInterval) +{ + u64 qwNextTBTT = 0; + u8 pbyData[8]; + + CARDbClearCurrentTSF(pDevice); + //CARDbGetCurrentTSF(pDevice, &qwNextTBTT); //Get Local TSF counter + qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval); + // Set NextTBTT + + pbyData[0] = (u8)qwNextTBTT; + pbyData[1] = (u8)(qwNextTBTT >> 8); + pbyData[2] = (u8)(qwNextTBTT >> 16); + pbyData[3] = (u8)(qwNextTBTT >> 24); + pbyData[4] = (u8)(qwNextTBTT >> 32); + pbyData[5] = (u8)(qwNextTBTT >> 40); + pbyData[6] = (u8)(qwNextTBTT >> 48); + pbyData[7] = (u8)(qwNextTBTT >> 56); + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_SET_TSFTBTT, + MESSAGE_REQUEST_TBTT, + 0, + 8, + pbyData + ); + + return; +} + +/* + * Description: Sync NIC TSF counter for Beacon time + * Get NEXTTBTT and write to HW + * + * Parameters: + * In: + * pDevice - The adapter to be set + * qwTSF - Current TSF counter + * wBeaconInterval - Beacon Interval + * Out: + * none + * + * Return Value: none + * + */ +void CARDvUpdateNextTBTT(struct vnt_private *pDevice, u64 qwTSF, + u16 wBeaconInterval) +{ + u8 pbyData[8]; + + qwTSF = CARDqGetNextTBTT(qwTSF, wBeaconInterval); + + // Set NextTBTT + + pbyData[0] = (u8)qwTSF; + pbyData[1] = (u8)(qwTSF >> 8); + pbyData[2] = (u8)(qwTSF >> 16); + pbyData[3] = (u8)(qwTSF >> 24); + pbyData[4] = (u8)(qwTSF >> 32); + pbyData[5] = (u8)(qwTSF >> 40); + pbyData[6] = (u8)(qwTSF >> 48); + pbyData[7] = (u8)(qwTSF >> 56); + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_SET_TSFTBTT, + MESSAGE_REQUEST_TBTT, + 0, + 8, + pbyData + ); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Card:Update Next TBTT[%8lx]\n", (unsigned long)qwTSF); + + return; +} + +/* + * Description: Turn off Radio power + * + * Parameters: + * In: + * pDevice - The adapter to be turned off + * Out: + * none + * + * Return Value: true if success; otherwise false + * + */ +int CARDbRadioPowerOff(struct vnt_private *pDevice) +{ + int bResult = true; + + //if (pDevice->bRadioOff == true) + // return true; + + pDevice->bRadioOff = true; + + switch (pDevice->byRFType) { + case RF_AL2230: + case RF_AL2230S: + case RF_AIROHA7230: + case RF_VT3226: //RobertYu:20051111 + case RF_VT3226D0: + case RF_VT3342A0: //RobertYu:20060609 + MACvRegBitsOff(pDevice, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); + break; + } + + MACvRegBitsOff(pDevice, MAC_REG_HOSTCR, HOSTCR_RXON); + + BBvSetDeepSleep(pDevice); + + return bResult; +} + +/* + * Description: Turn on Radio power + * + * Parameters: + * In: + * pDevice - The adapter to be turned on + * Out: + * none + * + * Return Value: true if success; otherwise false + * + */ +int CARDbRadioPowerOn(struct vnt_private *pDevice) +{ + int bResult = true; + + if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) { + return false; + } + + //if (pDevice->bRadioOff == false) + // return true; + + pDevice->bRadioOff = false; + + BBvExitDeepSleep(pDevice); + + MACvRegBitsOn(pDevice, MAC_REG_HOSTCR, HOSTCR_RXON); + + switch (pDevice->byRFType) { + case RF_AL2230: + case RF_AL2230S: + case RF_AIROHA7230: + case RF_VT3226: //RobertYu:20051111 + case RF_VT3226D0: + case RF_VT3342A0: //RobertYu:20060609 + MACvRegBitsOn(pDevice, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); + break; + } + + return bResult; +} + +void CARDvSetBSSMode(struct vnt_private *pDevice) +{ + // Set BB and packet type at the same time.//{{RobertYu:20050222, AL7230 have two TX PA output, only connet to b/g now + // so in 11a mode need to set the MAC Reg0x4C to 11b/g mode to turn on PA + if( (pDevice->byRFType == RF_AIROHA7230 ) && (pDevice->byBBType == BB_TYPE_11A) ) + { + MACvSetBBType(pDevice, BB_TYPE_11G); + } + else + { + MACvSetBBType(pDevice, pDevice->byBBType); + } + pDevice->byPacketType = CARDbyGetPktType(pDevice); + + if (pDevice->byBBType == BB_TYPE_11A) { + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, 0x03); + } else if (pDevice->byBBType == BB_TYPE_11B) { + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, 0x02); + } else if (pDevice->byBBType == BB_TYPE_11G) { + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, 0x08); + } + + vUpdateIFS(pDevice); + CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType); + + if ( pDevice->byBBType == BB_TYPE_11A ) { + //request by Jack 2005-04-26 + if (pDevice->byRFType == RF_AIROHA7230) { + pDevice->abyBBVGA[0] = 0x20; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xE7, pDevice->abyBBVGA[0]); + } + pDevice->abyBBVGA[2] = 0x10; + pDevice->abyBBVGA[3] = 0x10; + } else { + //request by Jack 2005-04-26 + if (pDevice->byRFType == RF_AIROHA7230) { + pDevice->abyBBVGA[0] = 0x1C; + ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xE7, pDevice->abyBBVGA[0]); + } + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + } +} diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h new file mode 100644 index 00000000..c3017a74 --- /dev/null +++ b/drivers/staging/vt6656/card.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: card.h + * + * Purpose: Provide functions to setup NIC operation mode + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + +#ifndef __CARD_H__ +#define __CARD_H__ +#include "device.h" + +/* init card type */ + +typedef enum _CARD_PHY_TYPE { + PHY_TYPE_AUTO = 0, + PHY_TYPE_11B, + PHY_TYPE_11G, + PHY_TYPE_11A +} CARD_PHY_TYPE, *PCARD_PHY_TYPE; + +typedef enum _CARD_OP_MODE { + OP_MODE_INFRASTRUCTURE = 0, + OP_MODE_ADHOC, + OP_MODE_AP, + OP_MODE_UNKNOWN +} CARD_OP_MODE, *PCARD_OP_MODE; + +#define CB_MAX_CHANNEL_24G 14 +#define CB_MAX_CHANNEL_5G 42 /* add channel9(5045MHz), 41==>42 */ +#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G+CB_MAX_CHANNEL_5G) + +struct vnt_private; + +void CARDbSetMediaChannel(struct vnt_private *pDevice, u32 uConnectionChannel); +void CARDvSetRSPINF(struct vnt_private *pDevice, u8 byBBType); +void vUpdateIFS(struct vnt_private *pDevice); +void CARDvUpdateBasicTopRate(struct vnt_private *pDevice); +void CARDbAddBasicRate(struct vnt_private *pDevice, u16 wRateIdx); +int CARDbIsOFDMinBasicRate(struct vnt_private *pDevice); +void CARDvAdjustTSF(struct vnt_private *pDevice, u8 byRxRate, + u64 qwBSSTimestamp, u64 qwLocalTSF); +bool CARDbGetCurrentTSF(struct vnt_private *pDevice, u64 *pqwCurrTSF); +bool CARDbClearCurrentTSF(struct vnt_private *pDevice); +void CARDvSetFirstNextTBTT(struct vnt_private *pDevice, u16 wBeaconInterval); +void CARDvUpdateNextTBTT(struct vnt_private *pDevice, u64 qwTSF, + u16 wBeaconInterval); +u64 CARDqGetNextTBTT(u64 qwTSF, u16 wBeaconInterval); +u64 CARDqGetTSFOffset(u8 byRxRate, u64 qwTSF1, u64 qwTSF2); +int CARDbRadioPowerOff(struct vnt_private *pDevice); +int CARDbRadioPowerOn(struct vnt_private *pDevice); +u8 CARDbyGetPktType(struct vnt_private *pDevice); +void CARDvSetBSSMode(struct vnt_private *pDevice); + +#endif /* __CARD_H__ */ diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c new file mode 100644 index 00000000..5158ff4b --- /dev/null +++ b/drivers/staging/vt6656/channel.c @@ -0,0 +1,474 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: channel.c + * + * Purpose: Channel number mapping + * + * Author: Lucas Lin + * + * Date: Dec 24, 2004 + * + * + * + * Revision History: + * 01-18-2005 RobertYu: remove the for loop searching in ChannelValid, + * change ChannelRuleTab to lookup-type, reorder table items. + * + * + */ + +#include <linux/kernel.h> +#include "country.h" +#include "channel.h" +#include "rf.h" + +static int msglevel = MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +static SChannelTblElement sChannelTbl[CB_MAX_CHANNEL+1] = +{ + {0, 0, false}, + {1, 2412, true}, + {2, 2417, true}, + {3, 2422, true}, + {4, 2427, true}, + {5, 2432, true}, + {6, 2437, true}, + {7, 2442, true}, + {8, 2447, true}, + {9, 2452, true}, + {10, 2457, true}, + {11, 2462, true}, + {12, 2467, true}, + {13, 2472, true}, + {14, 2484, true}, + {183, 4915, true}, //15 + {184, 4920, true}, //16 + {185, 4925, true}, //17 + {187, 4935, true}, //18 + {188, 4940, true}, //19 + {189, 4945, true}, //20 + {192, 4960, true}, //21 + {196, 4980, true}, //22 + {7, 5035, true}, //23 + {8, 5040, true}, //24 + {9, 5045, true}, //25 + {11, 5055, true}, //26 + {12, 5060, true}, //27 + {16, 5080, true}, //28 + {34, 5170, true}, //29 + {36, 5180, true}, //30 + {38, 5190, true}, //31 + {40, 5200, true}, //32 + {42, 5210, true}, //33 + {44, 5220, true}, //34 + {46, 5230, true}, //35 + {48, 5240, true}, //36 + {52, 5260, true}, //37 + {56, 5280, true}, //38 + {60, 5300, true}, //39 + {64, 5320, true}, //40 + {100, 5500, true}, //41 + {104, 5520, true}, //42 + {108, 5540, true}, //43 + {112, 5560, true}, //44 + {116, 5580, true}, //45 + {120, 5600, true}, //46 + {124, 5620, true}, //47 + {128, 5640, true}, //48 + {132, 5660, true}, //49 + {136, 5680, true}, //50 + {140, 5700, true}, //51 + {149, 5745, true}, //52 + {153, 5765, true}, //53 + {157, 5785, true}, //54 + {161, 5805, true}, //55 + {165, 5825, true} //56 +}; + +/************************************************************************ + * The Radar regulation rules for each country + ************************************************************************/ +static struct +{ + u8 byChannelCountryCode; /* The country code */ + char chCountryCode[2]; + u8 bChannelIdxList[CB_MAX_CHANNEL]; /* Available channels Index */ + u8 byPower[CB_MAX_CHANNEL]; +} ChannelRuleTab[] = +{ +/************************************************************************ + * This table is based on Athero driver rules + ************************************************************************/ +/* Country Available channels, ended with 0 */ +/* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 */ +{CCODE_FCC, {'U','S'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_TELEC, {'J','P'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 23, 0, 0, 23, 0, 23, 23, 0, 23, 0, 0, 23, 23, 23, 0, 23, 0, 23, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ETSI, {'E','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_RESV3, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV4, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV5, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV6, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV7, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV8, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV9, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVa, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVb, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVc, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVd, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVe, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ALLBAND, {' ',' '}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ALBANIA, {'A','L'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ALGERIA, {'D','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ARGENTINA, {'A','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 0} }, +{CCODE_ARMENIA, {'A','M'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_AUSTRALIA, {'A','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_AUSTRIA, {'A','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 15, 0, 15, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_AZERBAIJAN, {'A','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BAHRAIN, {'B','H'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BELARUS, {'B','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BELGIUM, {'B','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BELIZE, {'B','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_BOLIVIA, {'B','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_BRAZIL, {'B','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BRUNEI_DARUSSALAM, {'B','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_BULGARIA, {'B','G'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 0, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0} }, +{CCODE_CANADA, {'C','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_CHILE, {'C','L'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17} }, +{CCODE_CHINA, {'C','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_COLOMBIA, {'C','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_COSTA_RICA, {'C','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_CROATIA, {'H','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_CYPRUS, {'C','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_CZECH, {'C','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_DENMARK, {'D','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_DOMINICAN_REPUBLIC, {'D','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_ECUADOR, {'E','C'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_EGYPT, {'E','G'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_EL_SALVADOR, {'S','V'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ESTONIA, {'E','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_FINLAND, {'F','I'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_FRANCE, {'F','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_GERMANY, {'D','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_GREECE, {'G','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_GEORGIA, {'G','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_GUATEMALA, {'G','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_HONDURAS, {'H','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_HONG_KONG, {'H','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_HUNGARY, {'H','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ICELAND, {'I','S'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_INDIA, {'I','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_INDONESIA, {'I','D'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_IRAN, {'I','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_IRELAND, {'I','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_ITALY, {'I','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_ISRAEL, {'I','L'}, { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_JAPAN, {'J','P'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_JORDAN, {'J','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_KAZAKHSTAN, {'K','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_KUWAIT, {'K','W'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_LATVIA, {'L','V'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_LEBANON, {'L','B'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_LEICHTENSTEIN, {'L','I'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_LITHUANIA, {'L','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_LUXEMBURG, {'L','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_MACAU, {'M','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_MACEDONIA, {'M','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_MALTA, {'M','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 0} }, +{CCODE_MALAYSIA, {'M','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_MEXICO, {'M','X'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_MONACO, {'M','C'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_MOROCCO, {'M','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_NETHERLANDS, {'N','L'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_NEW_ZEALAND, {'N','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_NORTH_KOREA, {'K','P'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_NORWAY, {'N','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_OMAN, {'O','M'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_PAKISTAN, {'P','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_PANAMA, {'P','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_PERU, {'P','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_PHILIPPINES, {'P','H'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_POLAND, {'P','L'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_PORTUGAL, {'P','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_PUERTO_RICO, {'P','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_QATAR, {'Q','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ROMANIA, {'R','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RUSSIA, {'R','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_SAUDI_ARABIA, {'S','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_SINGAPORE, {'S','G'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20} }, +{CCODE_SLOVAKIA, {'S','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 0} }, +{CCODE_SLOVENIA, {'S','I'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_SOUTH_AFRICA, {'Z','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_SOUTH_KOREA, {'K','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_SPAIN, {'E','S'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 0} }, +{CCODE_SWEDEN, {'S','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_SWITZERLAND, {'C','H'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_SYRIA, {'S','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_TAIWAN, {'T','W'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 0} }, +{CCODE_THAILAND, {'T','H'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_TRINIDAD_TOBAGO, {'T','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_TUNISIA, {'T','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_TURKEY, {'T','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_UK, {'G','B'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_UKRAINE, {'U','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_UNITED_ARAB_EMIRATES, {'A','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_UNITED_STATES, {'U','S'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_URUGUAY, {'U','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_UZBEKISTAN, {'U','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_VENEZUELA, {'V','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_VIETNAM, {'V','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_YEMEN, {'Y','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ZIMBABWE, {'Z','W'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_JAPAN_W52_W53, {'J','J'}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_MAX, {'U','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } +/* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 */ +}; + +/************************************************************************ + * Country Channel Valid + * Input: CountryCode, ChannelNum + * ChanneIndex is defined as VT3253 MAC channel: + * 1 = 2.4G channel 1 + * 2 = 2.4G channel 2 + * ... + * 14 = 2.4G channel 14 + * 15 = 4.9G channel 183 + * 16 = 4.9G channel 184 + * ..... + * Output: true if the specified 5GHz band is allowed to be used. + False otherwise. +// 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + +// 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, +// 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + ************************************************************************/ +bool +ChannelValid(unsigned int CountryCode, unsigned int ChannelIndex) +{ + bool bValid; + + bValid = false; + /* + * If Channel Index is invalid, return invalid + */ + if ((ChannelIndex > CB_MAX_CHANNEL) || + (ChannelIndex == 0)) + { + bValid = false; + goto exit; + } + + bValid = sChannelTbl[ChannelIndex].bValid; + +exit: + return (bValid); + +} /* end ChannelValid */ + +void CHvInitChannelTable(struct vnt_private *pDevice) +{ + int bMultiBand = false; + int ii; + + for (ii = 1; ii <= CB_MAX_CHANNEL; ii++) + sChannelTbl[ii].bValid = false; + + switch (pDevice->byRFType) { + case RF_AL2230: + case RF_AL2230S: + case RF_VT3226: + case RF_VT3226D0: + bMultiBand = false; + break; + case RF_AIROHA7230: + case RF_VT3342A0: + default : + bMultiBand = true; + break; + } + + if ((pDevice->dwDiagRefCount != 0) || + (pDevice->b11hEable == true)) { + if (bMultiBand == true) { + for (ii = 0; ii < CB_MAX_CHANNEL; ii++) { + sChannelTbl[ii+1].bValid = true; + //pDevice->abyRegPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; + //pDevice->abyLocalPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; + } + for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { + //pDevice->abyRegPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; + //pDevice->abyLocalPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; + } + } else { + for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { + sChannelTbl[ii+1].bValid = true; + //pDevice->abyRegPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; + //pDevice->abyLocalPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; + } + } + } else if (pDevice->byZoneType <= CCODE_MAX) { + if (bMultiBand == true) { + for (ii = 0; ii < CB_MAX_CHANNEL; ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { + sChannelTbl[ii+1].bValid = true; + //pDevice->abyRegPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + //pDevice->abyLocalPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + } + } + } else { + for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { + sChannelTbl[ii+1].bValid = true; + //pDevice->abyRegPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + //pDevice->abyLocalPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + } + } + } + } + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO"Zone=[%d][%c][%c]!!\n",pDevice->byZoneType,ChannelRuleTab[pDevice->byZoneType].chCountryCode[0],ChannelRuleTab[pDevice->byZoneType].chCountryCode[1]); + for (ii = 0; ii < CB_MAX_CHANNEL; ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Channel[%d] is [%d]\n",sChannelTbl[ii].byChannelNumber,sChannelTbl[ii+1].bValid); + /*if (pDevice->abyRegPwr[ii+1] == 0) { + pDevice->abyRegPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; + } + if (pDevice->abyLocalPwr[ii+1] == 0) { + pDevice->abyLocalPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; + }*/ + } +} diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h new file mode 100644 index 00000000..95701e0c --- /dev/null +++ b/drivers/staging/vt6656/channel.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: channel.h + * + * Purpose: Country Regulation Rules header file + * + * Author: Lucas Lin + * + * Date: Dec 23, 2004 + * + */ + +#ifndef _CHANNEL_H_ +#define _CHANNEL_H_ + +#include "device.h" + +typedef struct tagSChannelTblElement { + u8 byChannelNumber; + unsigned int uFrequency; + bool bValid; +} SChannelTblElement, *PSChannelTblElement; + +bool ChannelValid(unsigned int CountryCode, unsigned int ChannelNum); +void CHvInitChannelTable(struct vnt_private *pDevice); + +#endif /* _CHANNEL_H_ */ diff --git a/drivers/staging/vt6656/control.c b/drivers/staging/vt6656/control.c new file mode 100644 index 00000000..026784fc --- /dev/null +++ b/drivers/staging/vt6656/control.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: control.c + * + * Purpose: Handle USB control endpoint + * + * Author: Jerry Chen + * + * Date: Apr. 5, 2004 + * + * Functions: + * CONTROLnsRequestOut - Write variable length bytes to MEM/BB/MAC/EEPROM + * CONTROLnsRequestIn - Read variable length bytes from MEM/BB/MAC/EEPROM + * ControlvWriteByte - Write one byte to MEM/BB/MAC/EEPROM + * ControlvReadByte - Read one byte from MEM/BB/MAC/EEPROM + * ControlvMaskByte - Read one byte from MEM/BB/MAC/EEPROM and clear/set + * some bits in the same address + * + * Revision History: + * 04-05-2004 Jerry Chen: Initial release + * 11-24-2004 Warren Hsu: Add ControlvWriteByte, ControlvReadByte, + * ControlvMaskByte + * + */ + +#include "control.h" +#include "rndis.h" + +/* static int msglevel =MSG_LEVEL_INFO; */ +/* static int msglevel =MSG_LEVEL_DEBUG; */ + +void ControlvWriteByte(struct vnt_private *pDevice, u8 reg, u8 reg_off, + u8 data) +{ + + CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, reg_off, reg, + sizeof(u8), &data); + + return; +} + +void ControlvReadByte(struct vnt_private *pDevice, u8 reg, u8 reg_off, + u8 *data) +{ + CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, + reg_off, reg, sizeof(u8), data); + return; +} + +void ControlvMaskByte(struct vnt_private *pDevice, u8 reg_type, u8 reg_off, + u8 reg_mask, u8 data) +{ + u8 reg_data[2]; + + reg_data[0] = data; + reg_data[1] = reg_mask; + + CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE_MASK, reg_off, + reg_type, ARRAY_SIZE(reg_data), reg_data); + + return; +} diff --git a/drivers/staging/vt6656/control.h b/drivers/staging/vt6656/control.h new file mode 100644 index 00000000..9da9b96a --- /dev/null +++ b/drivers/staging/vt6656/control.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: control.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Apr. 5, 2004 + * + */ + +#ifndef __CONTROL_H__ +#define __CONTROL_H__ + +#include "device.h" +#include "usbpipe.h" + +#define CONTROLnsRequestOut(Device, Request, Value, Index, Length, Buffer) \ + PIPEnsControlOut(Device, Request, Value, Index, Length, Buffer) + +#define CONTROLnsRequestOutAsyn(Device, Request, Value, Index, Length, Buffer) \ + PIPEnsControlOutAsyn(Device, Request, Value, Index, Length, Buffer) + +#define CONTROLnsRequestIn(Device, Request, Value, Index, Length, Buffer) \ + PIPEnsControlIn(Device, Request, Value, Index, Length, Buffer) + +void ControlvWriteByte(struct vnt_private *pDevice, u8 reg, u8 reg_off, + u8 data); + +void ControlvReadByte(struct vnt_private *pDevice, u8 reg, u8 reg_off, + u8 *data); + +void ControlvMaskByte(struct vnt_private *pDevice, u8 reg_type, u8 reg_off, + u8 reg_mask, u8 data); + +#endif /* __CONTROL_H__ */ diff --git a/drivers/staging/vt6656/country.h b/drivers/staging/vt6656/country.h new file mode 100644 index 00000000..a0320d8f --- /dev/null +++ b/drivers/staging/vt6656/country.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: country.h + * + * Purpose: Country Code information + * + * Author: Lucas Lin + * + * Date: Dec 23, 2004 + * + */ + +#ifndef __COUNTRY_H__ +#define __COUNTRY_H__ + +/************************************************************************ + * The definition here should be complied with the INF country order + * Please check with VNWL.inf/VNWL64.inf/VNWL*.inf + ************************************************************************/ +typedef enum _COUNTRY_CODE { + CCODE_FCC = 0, + CCODE_TELEC, + CCODE_ETSI, + CCODE_RESV3, + CCODE_RESV4, + CCODE_RESV5, + CCODE_RESV6, + CCODE_RESV7, + CCODE_RESV8, + CCODE_RESV9, + CCODE_RESVa, + CCODE_RESVb, + CCODE_RESVc, + CCODE_RESVd, + CCODE_RESVe, + CCODE_ALLBAND, + CCODE_ALBANIA, + CCODE_ALGERIA, + CCODE_ARGENTINA, + CCODE_ARMENIA, + CCODE_AUSTRALIA, + CCODE_AUSTRIA, + CCODE_AZERBAIJAN, + CCODE_BAHRAIN, + CCODE_BELARUS, + CCODE_BELGIUM, + CCODE_BELIZE, + CCODE_BOLIVIA, + CCODE_BRAZIL, + CCODE_BRUNEI_DARUSSALAM, + CCODE_BULGARIA, + CCODE_CANADA, + CCODE_CHILE, + CCODE_CHINA, + CCODE_COLOMBIA, + CCODE_COSTA_RICA, + CCODE_CROATIA, + CCODE_CYPRUS, + CCODE_CZECH, + CCODE_DENMARK, + CCODE_DOMINICAN_REPUBLIC, + CCODE_ECUADOR, + CCODE_EGYPT, + CCODE_EL_SALVADOR, + CCODE_ESTONIA, + CCODE_FINLAND, + CCODE_FRANCE, + CCODE_GERMANY, + CCODE_GREECE, + CCODE_GEORGIA, + CCODE_GUATEMALA, + CCODE_HONDURAS, + CCODE_HONG_KONG, + CCODE_HUNGARY, + CCODE_ICELAND, + CCODE_INDIA, + CCODE_INDONESIA, + CCODE_IRAN, + CCODE_IRELAND, + CCODE_ITALY, + CCODE_ISRAEL, + CCODE_JAPAN, + CCODE_JORDAN, + CCODE_KAZAKHSTAN, + CCODE_KUWAIT, + CCODE_LATVIA, + CCODE_LEBANON, + CCODE_LEICHTENSTEIN, + CCODE_LITHUANIA, + CCODE_LUXEMBURG, + CCODE_MACAU, + CCODE_MACEDONIA, + CCODE_MALTA, + CCODE_MALAYSIA, + CCODE_MEXICO, + CCODE_MONACO, + CCODE_MOROCCO, + CCODE_NETHERLANDS, + CCODE_NEW_ZEALAND, + CCODE_NORTH_KOREA, + CCODE_NORWAY, + CCODE_OMAN, + CCODE_PAKISTAN, + CCODE_PANAMA, + CCODE_PERU, + CCODE_PHILIPPINES, + CCODE_POLAND, + CCODE_PORTUGAL, + CCODE_PUERTO_RICO, + CCODE_QATAR, + CCODE_ROMANIA, + CCODE_RUSSIA, + CCODE_SAUDI_ARABIA, + CCODE_SINGAPORE, + CCODE_SLOVAKIA, + CCODE_SLOVENIA, + CCODE_SOUTH_AFRICA, + CCODE_SOUTH_KOREA, + CCODE_SPAIN, + CCODE_SWEDEN, + CCODE_SWITZERLAND, + CCODE_SYRIA, + CCODE_TAIWAN, + CCODE_THAILAND, + CCODE_TRINIDAD_TOBAGO, + CCODE_TUNISIA, + CCODE_TURKEY, + CCODE_UK, + CCODE_UKRAINE, + CCODE_UNITED_ARAB_EMIRATES, + CCODE_UNITED_STATES, + CCODE_URUGUAY, + CCODE_UZBEKISTAN, + CCODE_VENEZUELA, + CCODE_VIETNAM, + CCODE_YEMEN, + CCODE_ZIMBABWE, + CCODE_JAPAN_W52_W53, + CCODE_MAX +} COUNTRY_CODE; + +/************************************************************************ + * Function prototype + ************************************************************************/ +#endif /* __COUNTRY_H__ */ diff --git a/drivers/staging/vt6656/datarate.c b/drivers/staging/vt6656/datarate.c new file mode 100644 index 00000000..17fbc35e --- /dev/null +++ b/drivers/staging/vt6656/datarate.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: datarate.c + * + * Purpose: Handles the auto fallback & data rates functions + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + * Functions: + * RATEvParseMaxRate - Parsing the highest basic & support rate in rate field of frame + * RATEvTxRateFallBack - Rate fallback Algorithm Implementaion + * RATEuSetIE- Set rate IE field. + * + * Revision History: + * + */ + +#include "tmacro.h" +#include "mac.h" +#include "80211mgr.h" +#include "bssdb.h" +#include "datarate.h" +#include "card.h" +#include "baseband.h" +#include "srom.h" +#include "rf.h" + +/* static int msglevel = MSG_LEVEL_DEBUG; */ +static int msglevel =MSG_LEVEL_INFO; +const u8 acbyIERate[MAX_RATE] = +{0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + +#define AUTORATE_TXOK_CNT 0x0400 +#define AUTORATE_TXFAIL_CNT 0x0064 +#define AUTORATE_TIMEOUT 10 + +void s_vResetCounter(PKnownNodeDB psNodeDBTable); + +void s_vResetCounter(PKnownNodeDB psNodeDBTable) +{ + u8 ii; + + /* clear statistics counter for auto_rate */ + for (ii = 0; ii <= MAX_RATE; ii++) { + psNodeDBTable->uTxOk[ii] = 0; + psNodeDBTable->uTxFail[ii] = 0; + } +} + +/*+ + * + * Routine Description: + * Rate fallback Algorithm Implementaion + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * psNodeDBTable - Pointer to Node Data Base + * Out: + * none + * + * Return Value: none + * +-*/ +#define AUTORATE_TXCNT_THRESHOLD 20 +#define AUTORATE_INC_THRESHOLD 30 + +/*+ + * + * Description: + * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE + * + * Parameters: + * In: + * u8 - Rate value in SuppRates IE or ExtSuppRates IE + * Out: + * none + * + * Return Value: RateIdx + * +-*/ +u16 +RATEwGetRateIdx( + u8 byRate + ) +{ + u16 ii; + + /* erase BasicRate flag */ + byRate = byRate & 0x7F; + + for (ii = 0; ii < MAX_RATE; ii ++) { + if (acbyIERate[ii] == byRate) + return ii; + } + return 0; +} + +/*+ + * + * Description: + * Parsing the highest basic & support rate in rate field of frame. + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * pItemRates - Pointer to Rate field defined in 802.11 spec. + * pItemExtRates - Pointer to Extended Rate field defined in 802.11 spec. + * Out: + * pwMaxBasicRate - Maximum Basic Rate + * pwMaxSuppRate - Maximum Supported Rate + * pbyTopCCKRate - Maximum Basic Rate in CCK mode + * pbyTopOFDMRate - Maximum Basic Rate in OFDM mode + * + * Return Value: none + * +-*/ + +void RATEvParseMaxRate(struct vnt_private *pDevice, + PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pItemExtRates, + int bUpdateBasicRate, u16 *pwMaxBasicRate, u16 *pwMaxSuppRate, + u16 *pwSuppRate, u8 *pbyTopCCKRate, u8 *pbyTopOFDMRate) +{ + int ii; + u8 byHighSuppRate = 0, byRate = 0; + u16 wOldBasicRate = pDevice->wBasicRate; + u32 uRateLen; + + if (pItemRates == NULL) + return; + + *pwSuppRate = 0; + uRateLen = pItemRates->len; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen); + if (pDevice->byBBType != BB_TYPE_11B) { + if (uRateLen > WLAN_RATES_MAXLEN) + uRateLen = WLAN_RATES_MAXLEN; + } else { + if (uRateLen > WLAN_RATES_MAXLEN_11B) + uRateLen = WLAN_RATES_MAXLEN_11B; + } + + for (ii = 0; ii < uRateLen; ii++) { + byRate = (u8)(pItemRates->abyRates[ii]); + if (WLAN_MGMT_IS_BASICRATE(byRate) && + (bUpdateBasicRate == true)) { + /* + * add to basic rate set, update pDevice->byTopCCKBasicRate and + * pDevice->byTopOFDMBasicRate + */ + CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate)); + } + byRate = (u8)(pItemRates->abyRates[ii]&0x7F); + if (byHighSuppRate == 0) + byHighSuppRate = byRate; + if (byRate > byHighSuppRate) + byHighSuppRate = byRate; + *pwSuppRate |= (1<<RATEwGetRateIdx(byRate)); + } + if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) && + (pDevice->byBBType != BB_TYPE_11B)) { + + unsigned int uExtRateLen = pItemExtRates->len; + + if (uExtRateLen > WLAN_RATES_MAXLEN) + uExtRateLen = WLAN_RATES_MAXLEN; + + for (ii = 0; ii < uExtRateLen ; ii++) { + byRate = (u8)(pItemExtRates->abyRates[ii]); + /* select highest basic rate */ + if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) { + /* + * add to basic rate set, update pDevice->byTopCCKBasicRate and + * pDevice->byTopOFDMBasicRate + */ + CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate)); + } + byRate = (u8)(pItemExtRates->abyRates[ii]&0x7F); + if (byHighSuppRate == 0) + byHighSuppRate = byRate; + if (byRate > byHighSuppRate) + byHighSuppRate = byRate; + *pwSuppRate |= (1<<RATEwGetRateIdx(byRate)); + + /* DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", + RATEwGetRateIdx(byRate), byRate)); */ + } + } + + if ((pDevice->byPacketType == PK_TYPE_11GB) + && CARDbIsOFDMinBasicRate((void *)pDevice)) { + pDevice->byPacketType = PK_TYPE_11GA; + } + + *pbyTopCCKRate = pDevice->byTopCCKBasicRate; + *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate; + *pwMaxSuppRate = RATEwGetRateIdx(byHighSuppRate); + if ((pDevice->byPacketType==PK_TYPE_11B) || (pDevice->byPacketType==PK_TYPE_11GB)) + *pwMaxBasicRate = pDevice->byTopCCKBasicRate; + else + *pwMaxBasicRate = pDevice->byTopOFDMBasicRate; + if (wOldBasicRate != pDevice->wBasicRate) + CARDvSetRSPINF((void *)pDevice, pDevice->byBBType); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n"); +} + +/*+ + * + * Routine Description: + * Rate fallback Algorithm Implementaion + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * psNodeDBTable - Pointer to Node Data Base + * Out: + * none + * + * Return Value: none + * +-*/ +#define AUTORATE_TXCNT_THRESHOLD 20 +#define AUTORATE_INC_THRESHOLD 30 + +void RATEvTxRateFallBack(struct vnt_private *pDevice, + PKnownNodeDB psNodeDBTable) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u16 wIdxDownRate = 0; + int ii; + int bAutoRate[MAX_RATE] = {true, true, true, true, false, false, true, + true, true, true, true, true}; + u32 dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, + 240, 360, 480, 540}; + u32 dwThroughput = 0; + u16 wIdxUpRate = 0; + u32 dwTxDiff = 0; + + if (pMgmt->eScanState != WMAC_NO_SCANNING) + return; /* Don't do Fallback when scanning Channel */ + + psNodeDBTable->uTimeCount++; + + if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE]) + dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE]; + + if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) && + (dwTxDiff < AUTORATE_TXFAIL_CNT) && + (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) { + return; + } + + if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) { + psNodeDBTable->uTimeCount = 0; + } + + for (ii = 0; ii < MAX_RATE; ii++) { + if (psNodeDBTable->wSuppRate & (0x0001<<ii)) { + if (bAutoRate[ii] == true) { + wIdxUpRate = (u16) ii; + } + } else { + bAutoRate[ii] = false; + } + } + + for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) { + if ( (psNodeDBTable->uTxOk[ii] != 0) || + (psNodeDBTable->uTxFail[ii] != 0) ) { + dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii]; + if (ii < RATE_11M) { + psNodeDBTable->uTxFail[ii] *= 4; + } + dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n", + ii, (int)psNodeDBTable->uTxOk[ii], (int)psNodeDBTable->uTxFail[ii], (int)dwThroughputTbl[ii]); + } + dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate]; + + wIdxDownRate = psNodeDBTable->wTxDataRate; + for (ii = psNodeDBTable->wTxDataRate; ii > 0;) { + ii--; + if ( (dwThroughputTbl[ii] > dwThroughput) && + (bAutoRate[ii]==true) ) { + dwThroughput = dwThroughputTbl[ii]; + wIdxDownRate = (u16) ii; + } + } + psNodeDBTable->wTxDataRate = wIdxDownRate; + if (psNodeDBTable->uTxOk[MAX_RATE]) { + if (psNodeDBTable->uTxOk[MAX_RATE] > + (psNodeDBTable->uTxFail[MAX_RATE] * 4) ) { + psNodeDBTable->wTxDataRate = wIdxUpRate; + } + } else { /* adhoc, if uTxOk(total) == 0 & uTxFail(total) == 0 */ + if (psNodeDBTable->uTxFail[MAX_RATE] == 0) + psNodeDBTable->wTxDataRate = wIdxUpRate; + } + + if (pDevice->byBBType == BB_TYPE_11A) { + if (psNodeDBTable->wTxDataRate <= RATE_11M) + psNodeDBTable->wTxDataRate = RATE_6M; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uTxOk[MAX_RATE] %d, uTxFail[MAX_RATE]:%d\n",(int)psNodeDBTable->uTxOk[MAX_RATE], (int)psNodeDBTable->uTxFail[MAX_RATE]); + s_vResetCounter(psNodeDBTable); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable->wTxDataRate, (int)wIdxUpRate, (int)wIdxDownRate); + return; +} + +/*+ + * + * Description: + * This routine is used to assemble available Rate IE. + * + * Parameters: + * In: + * pDevice + * Out: + * + * Return Value: None + * +-*/ +u8 +RATEuSetIE ( + PWLAN_IE_SUPP_RATES pSrcRates, + PWLAN_IE_SUPP_RATES pDstRates, + unsigned int uRateLen + ) +{ + unsigned int ii, uu, uRateCnt = 0; + + if ((pSrcRates == NULL) || (pDstRates == NULL)) + return 0; + + if (pSrcRates->len == 0) + return 0; + + for (ii = 0; ii < uRateLen; ii++) { + for (uu = 0; uu < pSrcRates->len; uu++) { + if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) { + pDstRates->abyRates[uRateCnt ++] = pSrcRates->abyRates[uu]; + break; + } + } + } + return (u8)uRateCnt; +} + diff --git a/drivers/staging/vt6656/datarate.h b/drivers/staging/vt6656/datarate.h new file mode 100644 index 00000000..43cb7789 --- /dev/null +++ b/drivers/staging/vt6656/datarate.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: datarate.h + * + * Purpose: Handles the auto fallback & data rates functions + * + * Author: Lyndon Chen + * + * Date: July 16, 2002 + * + */ +#ifndef __DATARATE_H__ +#define __DATARATE_H__ + +#define FALLBACK_PKT_COLLECT_TR_H 50 /* pkts */ +#define FALLBACK_PKT_COLLECT_TR_L 10 /* pkts */ +#define FALLBACK_POLL_SECOND 5 /* 5 sec */ +#define FALLBACK_RECOVER_SECOND 30 /* 30 sec */ +#define FALLBACK_THRESHOLD 15 /* percent */ +#define UPGRADE_THRESHOLD 5 /* percent */ +#define UPGRADE_CNT_THRD 3 /* times */ +#define RETRY_TIMES_THRD_H 2 /* times */ +#define RETRY_TIMES_THRD_L 1 /* times */ + +#define RATE_1M 0 +#define RATE_2M 1 +#define RATE_5M 2 +#define RATE_11M 3 +#define RATE_6M 4 +#define RATE_9M 5 +#define RATE_12M 6 +#define RATE_18M 7 +#define RATE_24M 8 +#define RATE_36M 9 +#define RATE_48M 10 +#define RATE_54M 11 +#define RATE_AUTO 12 +#define MAX_RATE 12 + +void RATEvParseMaxRate(struct vnt_private *, PWLAN_IE_SUPP_RATES pItemRates, + PWLAN_IE_SUPP_RATES pItemExtRates, int bUpdateBasicRate, + u16 *pwMaxBasicRate, u16 *pwMaxSuppRate, u16 *pwSuppRate, + u8 *pbyTopCCKRate, u8 *pbyTopOFDMRate); + +void RATEvTxRateFallBack(struct vnt_private *pDevice, + PKnownNodeDB psNodeDBTable); + +u8 +RATEuSetIE( + PWLAN_IE_SUPP_RATES pSrcRates, + PWLAN_IE_SUPP_RATES pDstRates, + unsigned int uRateLen + ); + +u16 +RATEwGetRateIdx( + u8 byRate + ); + +#endif /* __DATARATE_H__ */ diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h new file mode 100644 index 00000000..64cb046f --- /dev/null +++ b/drivers/staging/vt6656/desc.h @@ -0,0 +1,416 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: desc.h + * + * Purpose:The header file of descriptor + * + * Revision History: + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + +#ifndef __DESC_H__ +#define __DESC_H__ + +#include <linux/types.h> +#include <linux/mm.h> + +#include "tether.h" + +/* max transmit or receive buffer size */ +#define CB_MAX_BUF_SIZE 2900U /* NOTE: must be multiple of 4 */ + +/* max TX buffer size */ +#define CB_MAX_TX_BUF_SIZE CB_MAX_BUF_SIZE +/* max RX buffer size when not use Multi-RD */ +#define CB_MAX_RX_BUF_SIZE_NORMAL CB_MAX_BUF_SIZE + +#define CB_BEACON_BUF_SIZE 512U /* default beacon buffer size */ + +#define MAX_TOTAL_SIZE_WITH_ALL_HEADERS CB_MAX_BUF_SIZE + +#define MAX_INTERRUPT_SIZE 32 + +#define RX_BLOCKS 64 /* from 0x60 to 0xA0 */ +#define TX_BLOCKS 32 /* from 0xA0 to 0xC0 */ + +#define CB_MAX_RX_DESC 128 /* max # of descriptors */ +#define CB_MIN_RX_DESC 16 /* min # of RX descriptors */ +#define CB_MAX_TX_DESC 128 /* max # of descriptors */ +#define CB_MIN_TX_DESC 16 /* min # of TX descriptors */ + +#define CB_RD_NUM 64 /* default # of RD */ +#define CB_TD_NUM 64 /* default # of TD */ + +/* + * bits in the RSR register + */ +#define RSR_ADDRBROAD 0x80 +#define RSR_ADDRMULTI 0x40 +#define RSR_ADDRUNI 0x00 +#define RSR_IVLDTYP 0x20 /* invalid packet type */ +#define RSR_IVLDLEN 0x10 /* invalid len (> 2312 byte) */ +#define RSR_BSSIDOK 0x08 +#define RSR_CRCOK 0x04 +#define RSR_BCNSSIDOK 0x02 +#define RSR_ADDROK 0x01 + +/* + * bits in the new RSR register + */ +#define NEWRSR_DECRYPTOK 0x10 +#define NEWRSR_CFPIND 0x08 +#define NEWRSR_HWUTSF 0x04 +#define NEWRSR_BCNHITAID 0x02 +#define NEWRSR_BCNHITAID0 0x01 + +/* + * bits in the TSR register + */ +#define TSR_RETRYTMO 0x08 +#define TSR_TMO 0x04 +#define TSR_ACKDATA 0x02 +#define TSR_VALID 0x01 + +#define CB_PROTOCOL_RESERVED_SECTION 16 + +/* + * if retries exceed 15 times, TX will abort, and + * if TX fifo underflow, TX will fail + * we should try to resend it + */ +#define CB_MAX_TX_ABORT_RETRY 3 + +#define FIFOCTL_AUTO_FB_1 0x1000 +#define FIFOCTL_AUTO_FB_0 0x0800 +#define FIFOCTL_GRPACK 0x0400 +#define FIFOCTL_11GA 0x0300 +#define FIFOCTL_11GB 0x0200 +#define FIFOCTL_11B 0x0100 +#define FIFOCTL_11A 0x0000 +#define FIFOCTL_RTS 0x0080 +#define FIFOCTL_ISDMA0 0x0040 +#define FIFOCTL_GENINT 0x0020 +#define FIFOCTL_TMOEN 0x0010 +#define FIFOCTL_LRETRY 0x0008 +#define FIFOCTL_CRCDIS 0x0004 +#define FIFOCTL_NEEDACK 0x0002 +#define FIFOCTL_LHEAD 0x0001 + +/* WMAC definition Frag Control */ +#define FRAGCTL_AES 0x0300 +#define FRAGCTL_TKIP 0x0200 +#define FRAGCTL_LEGACY 0x0100 +#define FRAGCTL_NONENCRYPT 0x0000 +#define FRAGCTL_ENDFRAG 0x0003 +#define FRAGCTL_MIDFRAG 0x0002 +#define FRAGCTL_STAFRAG 0x0001 +#define FRAGCTL_NONFRAG 0x0000 + +#define TYPE_TXDMA0 0 +#define TYPE_AC0DMA 1 +#define TYPE_ATIMDMA 2 +#define TYPE_SYNCDMA 3 +#define TYPE_MAXTD 2 + +#define TYPE_BEACONDMA 4 + +#define TYPE_RXDMA0 0 +#define TYPE_RXDMA1 1 +#define TYPE_MAXRD 2 + +/* TD_INFO flags control bit */ +#define TD_FLAGS_NETIF_SKB 0x01 /* check if need release skb */ +#define TD_FLAGS_PRIV_SKB 0x02 /* check if called from private skb(hostap) */ +#define TD_FLAGS_PS_RETRY 0x04 /* check if PS STA frame re-transmit */ + +/* + * RsvTime buffer header + */ +typedef struct tagSRrvTime_gRTS { + u16 wRTSTxRrvTime_ba; + u16 wRTSTxRrvTime_aa; + u16 wRTSTxRrvTime_bb; + u16 wReserved; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; +} __attribute__ ((__packed__)) +SRrvTime_gRTS, *PSRrvTime_gRTS; + +typedef const SRrvTime_gRTS *PCSRrvTime_gRTS; + +typedef struct tagSRrvTime_gCTS { + u16 wCTSTxRrvTime_ba; + u16 wReserved; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; +} __attribute__ ((__packed__)) +SRrvTime_gCTS, *PSRrvTime_gCTS; + +typedef const SRrvTime_gCTS *PCSRrvTime_gCTS; + +typedef struct tagSRrvTime_ab { + u16 wRTSTxRrvTime; + u16 wTxRrvTime; +} __attribute__ ((__packed__)) +SRrvTime_ab, *PSRrvTime_ab; + +typedef const SRrvTime_ab *PCSRrvTime_ab; + +typedef struct tagSRrvTime_atim { + u16 wCTSTxRrvTime_ba; + u16 wTxRrvTime_a; +} __attribute__ ((__packed__)) +SRrvTime_atim, *PSRrvTime_atim; + +typedef const SRrvTime_atim *PCSRrvTime_atim; + +/* + * RTS buffer header + */ +typedef struct tagSRTSData { + u16 wFrameControl; + u16 wDurationID; + u8 abyRA[ETH_ALEN]; + u8 abyTA[ETH_ALEN]; +} __attribute__ ((__packed__)) +SRTSData, *PSRTSData; + +typedef const SRTSData *PCSRTSData; + +typedef struct tagSRTS_g { + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_ba; + u16 wDuration_aa; + u16 wDuration_bb; + u16 wReserved; + SRTSData Data; +} __attribute__ ((__packed__)) +SRTS_g, *PSRTS_g; +typedef const SRTS_g *PCSRTS_g; + +typedef struct tagSRTS_g_FB { + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_ba; + u16 wDuration_aa; + u16 wDuration_bb; + u16 wReserved; + u16 wRTSDuration_ba_f0; + u16 wRTSDuration_aa_f0; + u16 wRTSDuration_ba_f1; + u16 wRTSDuration_aa_f1; + SRTSData Data; +} __attribute__ ((__packed__)) +SRTS_g_FB, *PSRTS_g_FB; + +typedef const SRTS_g_FB *PCSRTS_g_FB; + +typedef struct tagSRTS_ab { + u8 bySignalField; + u8 byServiceField; + u16 wTransmitLength; + u16 wDuration; + u16 wReserved; + SRTSData Data; +} __attribute__ ((__packed__)) +SRTS_ab, *PSRTS_ab; + +typedef const SRTS_ab *PCSRTS_ab; + +typedef struct tagSRTS_a_FB { + u8 bySignalField; + u8 byServiceField; + u16 wTransmitLength; + u16 wDuration; + u16 wReserved; + u16 wRTSDuration_f0; + u16 wRTSDuration_f1; + SRTSData Data; +} __attribute__ ((__packed__)) +SRTS_a_FB, *PSRTS_a_FB; + +typedef const SRTS_a_FB *PCSRTS_a_FB; + +/* + * CTS buffer header + */ +typedef struct tagSCTSData { + u16 wFrameControl; + u16 wDurationID; + u8 abyRA[ETH_ALEN]; + u16 wReserved; +} __attribute__ ((__packed__)) +SCTSData, *PSCTSData; + +typedef struct tagSCTS { + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u16 wDuration_ba; + u16 wReserved; + SCTSData Data; +} __attribute__ ((__packed__)) +SCTS, *PSCTS; + +typedef const SCTS *PCSCTS; + +typedef struct tagSCTS_FB { + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u16 wDuration_ba; + u16 wReserved; + u16 wCTSDuration_ba_f0; + u16 wCTSDuration_ba_f1; + SCTSData Data; +} __attribute__ ((__packed__)) +SCTS_FB, *PSCTS_FB; + +typedef const SCTS_FB *PCSCTS_FB; + +/* + * TX FIFO header + */ +typedef struct tagSTxBufHead { + u32 adwTxKey[4]; + u16 wFIFOCtl; + u16 wTimeStamp; + u16 wFragCtl; + u16 wReserved; +} __attribute__ ((__packed__)) +STxBufHead, *PSTxBufHead; +typedef const STxBufHead *PCSTxBufHead; + +typedef struct tagSTxShortBufHead { + u16 wFIFOCtl; + u16 wTimeStamp; +} __attribute__ ((__packed__)) +STxShortBufHead, *PSTxShortBufHead; +typedef const STxShortBufHead *PCSTxShortBufHead; + +/* + * TX data header + */ +typedef struct tagSTxDataHead_g { + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; +} __attribute__ ((__packed__)) +STxDataHead_g, *PSTxDataHead_g; + +typedef const STxDataHead_g *PCSTxDataHead_g; + +typedef struct tagSTxDataHead_g_FB { + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; +} __attribute__ ((__packed__)) +STxDataHead_g_FB, *PSTxDataHead_g_FB; +typedef const STxDataHead_g_FB *PCSTxDataHead_g_FB; + +typedef struct tagSTxDataHead_ab { + u8 bySignalField; + u8 byServiceField; + u16 wTransmitLength; + u16 wDuration; + u16 wTimeStampOff; +} __attribute__ ((__packed__)) +STxDataHead_ab, *PSTxDataHead_ab; +typedef const STxDataHead_ab *PCSTxDataHead_ab; + +typedef struct tagSTxDataHead_a_FB { + u8 bySignalField; + u8 byServiceField; + u16 wTransmitLength; + u16 wDuration; + u16 wTimeStampOff; + u16 wDuration_f0; + u16 wDuration_f1; +} __attribute__ ((__packed__)) +STxDataHead_a_FB, *PSTxDataHead_a_FB; +typedef const STxDataHead_a_FB *PCSTxDataHead_a_FB; + +/* + * MICHDR data header + */ +typedef struct tagSMICHDRHead { + u32 adwHDR0[4]; + u32 adwHDR1[4]; + u32 adwHDR2[4]; +} __attribute__ ((__packed__)) +SMICHDRHead, *PSMICHDRHead; + +typedef const SMICHDRHead *PCSMICHDRHead; + +typedef struct tagSBEACONCtl { + u32 BufReady:1; + u32 TSF:15; + u32 BufLen:11; + u32 Reserved:5; +} __attribute__ ((__packed__)) +SBEACONCtl; + +typedef struct tagSSecretKey { + u32 dwLowDword; + u8 byHighByte; +} __attribute__ ((__packed__)) +SSecretKey; + +typedef struct tagSKeyEntry { + u8 abyAddrHi[2]; + u16 wKCTL; + u8 abyAddrLo[4]; + u32 dwKey0[4]; + u32 dwKey1[4]; + u32 dwKey2[4]; + u32 dwKey3[4]; + u32 dwKey4[4]; +} __attribute__ ((__packed__)) +SKeyEntry; + +#endif /* __DESC_H__ */ diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h new file mode 100644 index 00000000..f07ba242 --- /dev/null +++ b/drivers/staging/vt6656/device.h @@ -0,0 +1,820 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: device.h + * + * Purpose: MAC Data structure + * + * Author: Tevin Chen + * + * Date: Mar 17, 1997 + * + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/firmware.h> +#include <linux/etherdevice.h> +#include <linux/suspend.h> +#include <linux/if_arp.h> +#include <linux/wireless.h> +#include <net/iw_handler.h> +#include <net/cfg80211.h> +#include <linux/timer.h> +#include <linux/usb.h> + +#ifdef SIOCETHTOOL +#define DEVICE_ETHTOOL_IOCTL_SUPPORT +#include <linux/ethtool.h> +#else +#undef DEVICE_ETHTOOL_IOCTL_SUPPORT +#endif + +/* please copy below macro to driver_event.c for API */ +#define RT_INSMOD_EVENT_FLAG 0x0101 +#define RT_UPDEV_EVENT_FLAG 0x0102 +#define RT_DISCONNECTED_EVENT_FLAG 0x0103 +#define RT_WPACONNECTED_EVENT_FLAG 0x0104 +#define RT_DOWNDEV_EVENT_FLAG 0x0105 +#define RT_RMMOD_EVENT_FLAG 0x0106 + +/* + * device specific + */ + +#include "device_cfg.h" +#include "80211hdr.h" +#include "tether.h" +#include "wmgr.h" +#include "wcmd.h" +#include "mib.h" +#include "srom.h" +#include "rc4.h" +#include "desc.h" +#include "key.h" +#include "card.h" + +#define VNT_USB_VENDOR_ID 0x160a +#define VNT_USB_PRODUCT_ID 0x3184 + +#define MAC_MAX_CONTEXT_REG (256+128) + +#define MAX_MULTICAST_ADDRESS_NUM 32 +#define MULTICAST_ADDRESS_LIST_SIZE (MAX_MULTICAST_ADDRESS_NUM * ETH_ALEN) + +#define DUPLICATE_RX_CACHE_LENGTH 5 + +#define NUM_KEY_ENTRY 11 + +#define TX_WEP_NONE 0 +#define TX_WEP_OTF 1 +#define TX_WEP_SW 2 +#define TX_WEP_SWOTP 3 +#define TX_WEP_OTPSW 4 +#define TX_WEP_SW232 5 + +#define KEYSEL_WEP40 0 +#define KEYSEL_WEP104 1 +#define KEYSEL_TKIP 2 +#define KEYSEL_CCMP 3 + +#define AUTO_FB_NONE 0 +#define AUTO_FB_0 1 +#define AUTO_FB_1 2 + +#define FB_RATE0 0 +#define FB_RATE1 1 + +/* Antenna Mode */ +#define ANT_A 0 +#define ANT_B 1 +#define ANT_DIVERSITY 2 +#define ANT_RXD_TXA 3 +#define ANT_RXD_TXB 4 +#define ANT_UNKNOWN 0xFF +#define ANT_TXA 0 +#define ANT_TXB 1 +#define ANT_RXA 2 +#define ANT_RXB 3 + +#define MAXCHECKHANGCNT 4 + +/* Packet type */ +#define TX_PKT_UNI 0x00 +#define TX_PKT_MULTI 0x01 +#define TX_PKT_BROAD 0x02 + +#define BB_VGA_LEVEL 4 +#define BB_VGA_CHANGE_THRESHOLD 3 + +#ifndef RUN_AT +#define RUN_AT(x) (jiffies+(x)) +#endif + +/* DMA related */ +#define RESERV_AC0DMA 4 + +#define PRIVATE_Message 0 + +#define DBG_PRT(l, p, args...) { if (l <= msglevel) printk(p, ##args); } +#define PRINT_K(p, args...) { if (PRIVATE_Message) printk(p, ##args); } + +typedef enum __device_msg_level { + MSG_LEVEL_ERR = 0, /* Errors causing abnormal operation */ + MSG_LEVEL_NOTICE = 1, /* Errors needing user notification */ + MSG_LEVEL_INFO = 2, /* Normal message. */ + MSG_LEVEL_VERBOSE = 3, /* Will report all trival errors. */ + MSG_LEVEL_DEBUG = 4 /* Only for debug purpose. */ +} DEVICE_MSG_LEVEL, *PDEVICE_MSG_LEVEL; + +typedef enum __device_init_type { + DEVICE_INIT_COLD = 0, /* cold init */ + DEVICE_INIT_RESET, /* reset init or Dx to D0 power remain */ + DEVICE_INIT_DXPL /* Dx to D0 power lost init */ +} DEVICE_INIT_TYPE, *PDEVICE_INIT_TYPE; + +/* USB */ + +/* + * Enum of context types for SendPacket + */ +typedef enum _CONTEXT_TYPE { + CONTEXT_DATA_PACKET = 1, + CONTEXT_MGMT_PACKET +} CONTEXT_TYPE; + +/* RCB (Receive Control Block) */ +typedef struct _RCB +{ + void *Next; + signed long Ref; + void *pDevice; + struct urb *pUrb; + struct vnt_rx_mgmt sMngPacket; + struct sk_buff *skb; + int bBoolInUse; + +} RCB, *PRCB; + +/* used to track bulk out irps */ +typedef struct _USB_SEND_CONTEXT { + void *pDevice; + struct sk_buff *pPacket; + struct urb *pUrb; + unsigned int uBufLen; + CONTEXT_TYPE Type; + struct ethhdr sEthHeader; + void *Next; + bool bBoolInUse; + unsigned char Data[MAX_TOTAL_SIZE_WITH_ALL_HEADERS]; +} USB_SEND_CONTEXT, *PUSB_SEND_CONTEXT; + +/* structure got from configuration file as user-desired default settings */ +typedef struct _DEFAULT_CONFIG { + signed int ZoneType; + signed int eConfigMode; + signed int eAuthenMode; /* open/wep/wpa */ + signed int bShareKeyAlgorithm; /* open-open/{open,wep}-sharekey */ + signed int keyidx; /* wepkey index */ + signed int eEncryptionStatus; +} DEFAULT_CONFIG, *PDEFAULT_CONFIG; + +/* + * Structure to keep track of USB interrupt packets + */ +typedef struct { + unsigned int uDataLen; + u8 * pDataBuf; + /* struct urb *pUrb; */ + bool bInUse; +} INT_BUFFER, *PINT_BUFFER; + +/* 0:11A 1:11B 2:11G */ +typedef enum _VIA_BB_TYPE +{ + BB_TYPE_11A = 0, + BB_TYPE_11B, + BB_TYPE_11G +} VIA_BB_TYPE, *PVIA_BB_TYPE; + +/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga(OFDM in BasicRate) */ +typedef enum _VIA_PKT_TYPE +{ + PK_TYPE_11A = 0, + PK_TYPE_11B, + PK_TYPE_11GB, + PK_TYPE_11GA +} VIA_PKT_TYPE, *PVIA_PKT_TYPE; + +/*++ NDIS related */ + +typedef enum __DEVICE_NDIS_STATUS { + STATUS_SUCCESS = 0, + STATUS_FAILURE, + STATUS_RESOURCES, + STATUS_PENDING, +} DEVICE_NDIS_STATUS, *PDEVICE_NDIS_STATUS; + +#define MAX_BSSIDINFO_4_PMKID 16 +#define MAX_PMKIDLIST 5 +/* flags for PMKID Candidate list structure */ +#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 + +/* PMKID Structures */ +typedef unsigned char NDIS_802_11_PMKID_VALUE[16]; + +typedef enum _NDIS_802_11_WEP_STATUS +{ + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, + Ndis802_11Encryption3KeyAbsent +} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, + NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + +typedef enum _NDIS_802_11_STATUS_TYPE +{ + Ndis802_11StatusType_Authentication, + Ndis802_11StatusType_MediaStreamMode, + Ndis802_11StatusType_PMKID_CandidateList, + Ndis802_11StatusTypeMax, /* not a real type, defined as upper bound */ +} NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE; + +/* added new types for PMKID Candidate lists */ +typedef struct _PMKID_CANDIDATE { + NDIS_802_11_MAC_ADDRESS BSSID; + unsigned long Flags; +} PMKID_CANDIDATE, *PPMKID_CANDIDATE; + +typedef struct _BSSID_INFO +{ + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_PMKID_VALUE PMKID; +} BSSID_INFO, *PBSSID_INFO; + +typedef struct tagSPMKID { + unsigned long Length; + unsigned long BSSIDInfoCount; + BSSID_INFO BSSIDInfo[MAX_BSSIDINFO_4_PMKID]; +} SPMKID, *PSPMKID; + +typedef struct tagSPMKIDCandidateEvent { + NDIS_802_11_STATUS_TYPE StatusType; + unsigned long Version; /* Version of the structure */ + unsigned long NumCandidates; /* No. of pmkid candidates */ + PMKID_CANDIDATE CandidateList[MAX_PMKIDLIST]; +} SPMKIDCandidateEvent, *PSPMKIDCandidateEvent; + +/*++ 802.11h related */ +#define MAX_QUIET_COUNT 8 + +typedef struct tagSQuietControl { + bool bEnable; + u32 dwStartTime; + u8 byPeriod; + u16 wDuration; +} SQuietControl, *PSQuietControl; + +/* The receive duplicate detection cache entry */ +typedef struct tagSCacheEntry{ + u16 wFmSequence; + u8 abyAddr2[ETH_ALEN]; + u16 wFrameCtl; +} SCacheEntry, *PSCacheEntry; + +typedef struct tagSCache{ +/* The receive cache is updated circularly. The next entry to be written is + * indexed by the "InPtr". + */ + unsigned int uInPtr; /* Place to use next */ + SCacheEntry asCacheEntry[DUPLICATE_RX_CACHE_LENGTH]; +} SCache, *PSCache; + +#define CB_MAX_RX_FRAG 64 +/* + * DeFragment Control Block, used for collecting fragments prior to reassembly + */ +typedef struct tagSDeFragControlBlock +{ + u16 wSequence; + u16 wFragNum; + u8 abyAddr2[ETH_ALEN]; + unsigned int uLifetime; + struct sk_buff* skb; + u8 * pbyRxBuffer; + unsigned int cbFrameLength; + bool bInUse; +} SDeFragControlBlock, *PSDeFragControlBlock; + +/* flags for options */ +#define DEVICE_FLAGS_UNPLUG 0x00000001UL +#define DEVICE_FLAGS_PREAMBLE_TYPE 0x00000002UL +#define DEVICE_FLAGS_OP_MODE 0x00000004UL +#define DEVICE_FLAGS_PS_MODE 0x00000008UL +#define DEVICE_FLAGS_80211h_MODE 0x00000010UL + +/* flags for driver status */ +#define DEVICE_FLAGS_OPENED 0x00010000UL +#define DEVICE_FLAGS_WOL_ENABLED 0x00080000UL +/* flags for capabilities */ +#define DEVICE_FLAGS_TX_ALIGN 0x01000000UL +#define DEVICE_FLAGS_HAVE_CAM 0x02000000UL +#define DEVICE_FLAGS_FLOW_CTRL 0x04000000UL + +/* flags for MII status */ +#define DEVICE_LINK_FAIL 0x00000001UL +#define DEVICE_SPEED_10 0x00000002UL +#define DEVICE_SPEED_100 0x00000004UL +#define DEVICE_SPEED_1000 0x00000008UL +#define DEVICE_DUPLEX_FULL 0x00000010UL +#define DEVICE_AUTONEG_ENABLE 0x00000020UL +#define DEVICE_FORCED_BY_EEPROM 0x00000040UL +/* for device_set_media_duplex */ +#define DEVICE_LINK_CHANGE 0x00000001UL + +typedef struct __device_opt { + int nRxDescs0; /* number of RX descriptors 0 */ + int nTxDescs0; /* number of TX descriptors 0, 1, 2, 3 */ + int rts_thresh; /* RTS threshold */ + int frag_thresh; + int OpMode; + int data_rate; + int channel_num; + int short_retry; + int long_retry; + int bbp_type; + u32 flags; +} OPTIONS, *POPTIONS; + +struct vnt_private { + /* netdev */ + struct usb_device *usb; + struct net_device *dev; + struct net_device_stats stats; + + OPTIONS sOpts; + + struct tasklet_struct CmdWorkItem; + struct tasklet_struct EventWorkItem; + struct tasklet_struct ReadWorkItem; + struct tasklet_struct RxMngWorkItem; + + u32 rx_buf_sz; + int multicast_limit; + u8 byRxMode; + + spinlock_t lock; + + u32 rx_bytes; + + u8 byRevId; + + u32 flags; + unsigned long Flags; + + SCache sDupRxCache; + + SDeFragControlBlock sRxDFCB[CB_MAX_RX_FRAG]; + u32 cbDFCB; + u32 cbFreeDFCB; + u32 uCurrentDFCBIdx; + + /* USB */ + struct urb *pControlURB; + struct urb *pInterruptURB; + struct usb_ctrlrequest sUsbCtlRequest; + u32 int_interval; + + /* Variables to track resources for the BULK In Pipe */ + PRCB pRCBMem; + PRCB apRCB[CB_MAX_RX_DESC]; + u32 cbRD; + PRCB FirstRecvFreeList; + PRCB LastRecvFreeList; + u32 NumRecvFreeList; + PRCB FirstRecvMngList; + PRCB LastRecvMngList; + u32 NumRecvMngList; + int bIsRxWorkItemQueued; + int bIsRxMngWorkItemQueued; + unsigned long ulRcvRefCount; /* packets that have not returned back */ + + /* Variables to track resources for the BULK Out Pipe */ + PUSB_SEND_CONTEXT apTD[CB_MAX_TX_DESC]; + u32 cbTD; + + /* Variables to track resources for the Interrupt In Pipe */ + INT_BUFFER intBuf; + int fKillEventPollingThread; + int bEventAvailable; + + /* default config from file by user setting */ + DEFAULT_CONFIG config_file; + + /* Statistic for USB */ + unsigned long ulBulkInPosted; + unsigned long ulBulkInError; + unsigned long ulBulkInContCRCError; + unsigned long ulBulkInBytesRead; + + unsigned long ulBulkOutPosted; + unsigned long ulBulkOutError; + unsigned long ulBulkOutContCRCError; + unsigned long ulBulkOutBytesWrite; + + unsigned long ulIntInPosted; + unsigned long ulIntInError; + unsigned long ulIntInContCRCError; + unsigned long ulIntInBytesRead; + + /* Version control */ + u16 wFirmwareVersion; + u8 byLocalID; + u8 byRFType; + u8 byBBRxConf; + + u8 byZoneType; + int bZoneRegExist; + + u8 byOriginalZonetype; + + int bLinkPass; /* link status: OK or fail */ + u8 abyCurrentNetAddr[ETH_ALEN]; + u8 abyPermanentNetAddr[ETH_ALEN]; + + int bExistSWNetAddr; + + /* Adapter statistics */ + SStatCounter scStatistic; + /* 802.11 counter */ + SDot11Counters s802_11Counter; + + /* Maintain statistical debug info. */ + unsigned long packetsReceived; + unsigned long packetsReceivedDropped; + unsigned long packetsReceivedOverflow; + unsigned long packetsSent; + unsigned long packetsSentDropped; + unsigned long SendContextsInUse; + unsigned long RcvBuffersInUse; + + /* 802.11 management */ + struct vnt_manager vnt_mgmt; + + u64 qwCurrTSF; + u32 cbBulkInMax; + int bPSRxBeacon; + + /* 802.11 MAC specific */ + u32 uCurrRSSI; + u8 byCurrSQ; + + /* Antenna Diversity */ + int bTxRxAntInv; + u32 dwRxAntennaSel; + u32 dwTxAntennaSel; + u8 byAntennaCount; + u8 byRxAntennaMode; + u8 byTxAntennaMode; + u8 byRadioCtl; + u8 bHWRadioOff; + + /* SQ3 functions for antenna diversity */ + struct timer_list TimerSQ3Tmax1; + struct timer_list TimerSQ3Tmax2; + struct timer_list TimerSQ3Tmax3; + + int bDiversityRegCtlON; + int bDiversityEnable; + unsigned long ulDiversityNValue; + unsigned long ulDiversityMValue; + u8 byTMax; + u8 byTMax2; + u8 byTMax3; + unsigned long ulSQ3TH; + + unsigned long uDiversityCnt; + u8 byAntennaState; + unsigned long ulRatio_State0; + unsigned long ulRatio_State1; + unsigned long ulSQ3_State0; + unsigned long ulSQ3_State1; + + unsigned long aulSQ3Val[MAX_RATE]; + unsigned long aulPktNum[MAX_RATE]; + + /* IFS & Cw */ + u32 uSIFS; /* Current SIFS */ + u32 uDIFS; /* Current DIFS */ + u32 uEIFS; /* Current EIFS */ + u32 uSlot; /* Current SlotTime */ + u32 uCwMin; /* Current CwMin */ + u32 uCwMax; /* CwMax is fixed on 1023 */ + + /* PHY parameter */ + u8 bySIFS; + u8 byDIFS; + u8 byEIFS; + u8 bySlot; + u8 byCWMaxMin; + + /* Rate */ + VIA_BB_TYPE byBBType; /* 0: 11A, 1:11B, 2:11G */ + VIA_PKT_TYPE byPacketType; /* 0:11a 1:11b 2:11gb 3:11ga */ + u16 wBasicRate; + u8 byACKRate; + u8 byTopOFDMBasicRate; + u8 byTopCCKBasicRate; + + u32 dwAotoRateTxOkCnt; + u32 dwAotoRateTxFailCnt; + u32 dwErrorRateThreshold[13]; + u32 dwTPTable[MAX_RATE]; + u8 abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /*u32 alignment */ + + u8 byMinChannel; + u8 byMaxChannel; + u32 uConnectionRate; + + u8 byPreambleType; + u8 byShortPreamble; + /* CARD_PHY_TYPE */ + u8 eConfigPHYMode; + + /* For RF Power table */ + u8 byCCKPwr; + u8 byOFDMPwrG; + u8 byOFDMPwrA; + u8 byCurPwr; + u8 abyCCKPwrTbl[14]; + u8 abyOFDMPwrTbl[14]; + u8 abyOFDMAPwrTbl[42]; + + u16 wCurrentRate; + u16 wRTSThreshold; + u16 wFragmentationThreshold; + u8 byShortRetryLimit; + u8 byLongRetryLimit; + CARD_OP_MODE eOPMode; + int bBSSIDFilter; + u16 wMaxTransmitMSDULifetime; + u8 abyBSSID[ETH_ALEN]; + u8 abyDesireBSSID[ETH_ALEN]; + + u16 wCTSDuration; /* update while speed change */ + u16 wACKDuration; + u16 wRTSTransmitLen; + u8 byRTSServiceField; + u8 byRTSSignalField; + + u32 dwMaxReceiveLifetime; /* dot11MaxReceiveLifetime */ + + int bCCK; + int bEncryptionEnable; + int bLongHeader; + int bSoftwareGenCrcErr; + int bShortSlotTime; + int bProtectMode; + int bNonERPPresent; + int bBarkerPreambleMd; + + u8 byERPFlag; + u16 wUseProtectCntDown; + + int bRadioControlOff; + int bRadioOff; + + /* Power save */ + int bEnablePSMode; + u16 wListenInterval; + int bPWBitOn; + WMAC_POWER_MODE ePSMode; + unsigned long ulPSModeWaitTx; + int bPSModeTxBurst; + + /* Beacon releated */ + u16 wSeqCounter; + int bBeaconBufReady; + int bBeaconSent; + int bFixRate; + u8 byCurrentCh; + u32 uScanTime; + + CMD_STATE eCommandState; + + CMD_CODE eCommand; + int bBeaconTx; + u8 byScanBBType; + + int bStopBeacon; + int bStopDataPkt; + int bStopTx0Pkt; + u32 uAutoReConnectTime; + u32 uIsroamingTime; + + /* 802.11 counter */ + + CMD_ITEM eCmdQueue[CMD_Q_SIZE]; + u32 uCmdDequeueIdx; + u32 uCmdEnqueueIdx; + u32 cbFreeCmdQueue; + int bCmdRunning; + int bCmdClear; + int bNeedRadioOFF; + + int bEnableRoaming; + int bIsRoaming; + int bFastRoaming; + u8 bSameBSSMaxNum; + u8 bSameBSSCurNum; + int bRoaming; + int b11hEable; + unsigned long ulTxPower; + + /* Encryption */ + NDIS_802_11_WEP_STATUS eEncryptionStatus; + int bTransmitKey; + NDIS_802_11_WEP_STATUS eOldEncryptionStatus; + SKeyManagement sKey; + u32 dwIVCounter; + + RC4Ext SBox; + u8 abyPRNG[WLAN_WEPMAX_KEYLEN+3]; + u8 byKeyIndex; + + int bAES; + + u32 uKeyLength; + u8 abyKey[WLAN_WEP232_KEYLEN]; + + /* for AP mode */ + u32 uAssocCount; + int bMoreData; + + /* QoS */ + int bGrpAckPolicy; + + u8 byAutoFBCtrl; + + int bTxMICFail; + int bRxMICFail; + + /* For Update BaseBand VGA Gain Offset */ + int bUpdateBBVGA; + u32 uBBVGADiffCount; + u8 byBBVGANew; + u8 byBBVGACurrent; + u8 abyBBVGA[BB_VGA_LEVEL]; + signed long ldBmThreshold[BB_VGA_LEVEL]; + + u8 byBBPreEDRSSI; + u8 byBBPreEDIndex; + + int bRadioCmd; + u32 dwDiagRefCount; + + /* For FOE Tuning */ + u8 byFOETuning; + + /* For Auto Power Tunning */ + u8 byAutoPwrTunning; + + /* BaseBand Loopback Use */ + u8 byBBCR4d; + u8 byBBCRc9; + u8 byBBCR88; + u8 byBBCR09; + + /* command timer */ + struct timer_list sTimerCommand; + + struct timer_list sTimerTxData; + unsigned long nTxDataTimeCout; + int fTxDataInSleep; + int IsTxDataTrigger; + + int fWPA_Authened; /*is WPA/WPA-PSK or WPA2/WPA2-PSK authen?? */ + u8 byReAssocCount; + u8 byLinkWaitCount; + + struct ethhdr sTxEthHeader; + struct ethhdr sRxEthHeader; + u8 abyBroadcastAddr[ETH_ALEN]; + u8 abySNAP_RFC1042[ETH_ALEN]; + u8 abySNAP_Bridgetunnel[ETH_ALEN]; + + /* Pre-Authentication & PMK cache */ + SPMKID gsPMKID; + SPMKIDCandidateEvent gsPMKIDCandidate; + + /* for 802.11h */ + int b11hEnable; + + int bChannelSwitch; + u8 byNewChannel; + u8 byChannelSwitchCount; + + /* WPA supplicant daemon */ + int bWPADEVUp; + int bwextstep0; + int bwextstep1; + int bwextstep2; + int bwextstep3; + int bWPASuppWextEnabled; + + /* user space daemon: hostapd, is used for HOSTAP */ + int bEnableHostapd; + int bEnable8021x; + int bEnableHostWEP; + struct net_device *apdev; + int (*tx_80211)(struct sk_buff *skb, struct net_device *dev); + + u32 uChannel; + + struct iw_statistics wstats; /* wireless stats */ + + int bCommit; + +}; + +#define EnqueueRCB(_Head, _Tail, _RCB) \ +{ \ + if (!_Head) { \ + _Head = _RCB; \ + } \ + else { \ + _Tail->Next = _RCB; \ + } \ + _RCB->Next = NULL; \ + _Tail = _RCB; \ +} + +#define DequeueRCB(Head, Tail) \ +{ \ + PRCB RCB = Head; \ + if (!RCB->Next) { \ + Tail = NULL; \ + } \ + Head = RCB->Next; \ +} + +#define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) { \ + if ((uVar) >= ((uModulo) - 1)) \ + (uVar) = 0; \ + else \ + (uVar)++; \ +} + +#define fMP_RESET_IN_PROGRESS 0x00000001 +#define fMP_DISCONNECTED 0x00000002 +#define fMP_HALT_IN_PROGRESS 0x00000004 +#define fMP_SURPRISE_REMOVED 0x00000008 +#define fMP_RECV_LOOKASIDE 0x00000010 +#define fMP_INIT_IN_PROGRESS 0x00000020 +#define fMP_SEND_SIDE_RESOURCE_ALLOCATED 0x00000040 +#define fMP_RECV_SIDE_RESOURCE_ALLOCATED 0x00000080 +#define fMP_POST_READS 0x00000100 +#define fMP_POST_WRITES 0x00000200 +#define fMP_CONTROL_READS 0x00000400 +#define fMP_CONTROL_WRITES 0x00000800 + +#define MP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F)) +#define MP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F)) +#define MP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) + +#define MP_IS_READY(_M) (((_M)->Flags & \ + (fMP_DISCONNECTED | fMP_RESET_IN_PROGRESS | fMP_HALT_IN_PROGRESS | fMP_INIT_IN_PROGRESS | fMP_SURPRISE_REMOVED)) == 0) + +int device_alloc_frag_buf(struct vnt_private *, PSDeFragControlBlock pDeF); + +#endif diff --git a/drivers/staging/vt6656/device_cfg.h b/drivers/staging/vt6656/device_cfg.h new file mode 100644 index 00000000..ea66b975 --- /dev/null +++ b/drivers/staging/vt6656/device_cfg.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: device_cfg.h + * + * Purpose: Driver configuration header + * Author: Lyndon Chen + * + * Date: Dec 9, 2005 + * + */ +#ifndef __DEVICE_CONFIG_H +#define __DEVICE_CONFIG_H + +#include <linux/types.h> + +typedef +struct _version { + unsigned char major; + unsigned char minor; + unsigned char build; +} version_t, *pversion_t; + +#ifndef false +#define false (0) +#endif + +#ifndef true +#define true (!(false)) +#endif + +#define VID_TABLE_SIZE 64 +#define MCAST_TABLE_SIZE 64 +#define MCAM_SIZE 32 +#define VCAM_SIZE 32 +#define TX_QUEUE_NO 8 + +#define DEVICE_NAME "vt6656" +#define DEVICE_FULL_DRV_NAM "VIA Networking Wireless LAN USB Driver" + +#ifndef MAJOR_VERSION +#define MAJOR_VERSION 1 +#endif + +#ifndef MINOR_VERSION +#define MINOR_VERSION 13 +#endif + +#ifndef DEVICE_VERSION +#define DEVICE_VERSION "1.19_12" +#endif + +/* config file */ +#include <linux/fs.h> +#include <linux/fcntl.h> +#ifndef CONFIG_PATH +#define CONFIG_PATH "/etc/vntconfiguration.dat" +#endif + +/* Max: 2378 = 2312 Payload + 30HD + 4CRC + 2Padding + 4Len + 8TSF + 4RSR */ +#define PKT_BUF_SZ 2390 + +#define MAX_UINTS 8 +#define OPTION_DEFAULT { [0 ... MAX_UINTS-1] = -1} + +typedef enum _chip_type { + VT3184 = 1 +} CHIP_TYPE, *PCHIP_TYPE; + +#ifdef VIAWET_DEBUG +#define ASSERT(x) { \ + if (!(x)) { \ + printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x, \ + __FUNCTION__, __LINE__);\ + *(int *) 0 = 0; \ + } \ +} +#define DBG_PORT80(value) outb(value, 0x80) +#else +#define ASSERT(x) +#define DBG_PORT80(value) +#endif + +#endif diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c new file mode 100644 index 00000000..7ec166a2 --- /dev/null +++ b/drivers/staging/vt6656/dpc.c @@ -0,0 +1,1430 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: dpc.c + * + * Purpose: handle dpc rx functions + * + * Author: Lyndon Chen + * + * Date: May 20, 2003 + * + * Functions: + * device_receive_frame - Rcv 802.11 frame function + * s_bAPModeRxCtl- AP Rcv frame filer Ctl. + * s_bAPModeRxData- AP Rcv data frame handle + * s_bHandleRxEncryption- Rcv decrypted data via on-fly + * s_bHostWepRxEncryption- Rcv encrypted data via host + * s_byGetRateIdx- get rate index + * s_vGetDASA- get data offset + * s_vProcessRxMACHeader- Rcv 802.11 and translate to 802.3 + * + * Revision History: + * + */ + +#include "device.h" +#include "rxtx.h" +#include "tether.h" +#include "card.h" +#include "bssdb.h" +#include "mac.h" +#include "baseband.h" +#include "michael.h" +#include "tkip.h" +#include "tcrc.h" +#include "wctl.h" +#include "hostap.h" +#include "rf.h" +#include "iowpa.h" +#include "aes_ccmp.h" +#include "datarate.h" +#include "usbpipe.h" + +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +const u8 acbyRxRate[MAX_RATE] = +{2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; + +static u8 s_byGetRateIdx(u8 byRate); + +static +void +s_vGetDASA( + u8 * pbyRxBufferAddr, + unsigned int *pcbHeaderSize, + struct ethhdr *psEthHeader + ); + +static void s_vProcessRxMACHeader(struct vnt_private *pDevice, + u8 *pbyRxBufferAddr, u32 cbPacketSize, int bIsWEP, int bExtIV, + u32 *pcbHeadSize); + +static int s_bAPModeRxCtl(struct vnt_private *pDevice, u8 *pbyFrame, + s32 iSANodeIndex); + +static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb, + u32 FrameSize, u32 cbHeaderOffset, s32 iSANodeIndex, s32 iDANodeIndex); + +static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame, + u32 FrameSize, u8 *pbyRsr, u8 *pbyNewRsr, PSKeyItem *pKeyOut, + s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16); + +static int s_bHostWepRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame, + u32 FrameSize, u8 *pbyRsr, int bOnFly, PSKeyItem pKey, u8 *pbyNewRsr, + s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16); + +/*+ + * + * Description: + * Translate Rcv 802.11 header to 802.3 header with Rx buffer + * + * Parameters: + * In: + * pDevice + * dwRxBufferAddr - Address of Rcv Buffer + * cbPacketSize - Rcv Packet size + * bIsWEP - If Rcv with WEP + * Out: + * pcbHeaderSize - 802.11 header size + * + * Return Value: None + * +-*/ + +static void s_vProcessRxMACHeader(struct vnt_private *pDevice, + u8 *pbyRxBufferAddr, u32 cbPacketSize, int bIsWEP, int bExtIV, + u32 *pcbHeadSize) +{ + u8 *pbyRxBuffer; + u32 cbHeaderSize = 0; + u16 *pwType; + struct ieee80211_hdr *pMACHeader; + int ii; + + pMACHeader = (struct ieee80211_hdr *) (pbyRxBufferAddr + cbHeaderSize); + + s_vGetDASA((u8 *)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader); + + if (bIsWEP) { + if (bExtIV) { + // strip IV&ExtIV , add 8 byte + cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 8); + } else { + // strip IV , add 4 byte + cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 4); + } + } + else { + cbHeaderSize += WLAN_HDR_ADDR3_LEN; + }; + + pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize); + if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) { + cbHeaderSize += 6; + } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { + cbHeaderSize += 6; + pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); + if ((*pwType == cpu_to_be16(ETH_P_IPX)) || + (*pwType == cpu_to_le16(0xF380))) { + cbHeaderSize -= 8; + pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); + if (bIsWEP) { + if (bExtIV) { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV + } else { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV + } + } + else { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); + } + } + } + else { + cbHeaderSize -= 2; + pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize); + if (bIsWEP) { + if (bExtIV) { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV + } else { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV + } + } + else { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); + } + } + + cbHeaderSize -= (ETH_ALEN * 2); + pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize); + for (ii = 0; ii < ETH_ALEN; ii++) + *pbyRxBuffer++ = pDevice->sRxEthHeader.h_dest[ii]; + for (ii = 0; ii < ETH_ALEN; ii++) + *pbyRxBuffer++ = pDevice->sRxEthHeader.h_source[ii]; + + *pcbHeadSize = cbHeaderSize; +} + +static u8 s_byGetRateIdx(u8 byRate) +{ + u8 byRateIdx; + + for (byRateIdx = 0; byRateIdx <MAX_RATE ; byRateIdx++) { + if (acbyRxRate[byRateIdx%MAX_RATE] == byRate) + return byRateIdx; + } + return 0; +} + +static +void +s_vGetDASA ( + u8 * pbyRxBufferAddr, + unsigned int *pcbHeaderSize, + struct ethhdr *psEthHeader + ) +{ + unsigned int cbHeaderSize = 0; + struct ieee80211_hdr *pMACHeader; + int ii; + + pMACHeader = (struct ieee80211_hdr *) (pbyRxBufferAddr + cbHeaderSize); + + if ((pMACHeader->frame_control & FC_TODS) == 0) { + if (pMACHeader->frame_control & FC_FROMDS) { + for (ii = 0; ii < ETH_ALEN; ii++) { + psEthHeader->h_dest[ii] = + pMACHeader->addr1[ii]; + psEthHeader->h_source[ii] = + pMACHeader->addr3[ii]; + } + } else { + /* IBSS mode */ + for (ii = 0; ii < ETH_ALEN; ii++) { + psEthHeader->h_dest[ii] = + pMACHeader->addr1[ii]; + psEthHeader->h_source[ii] = + pMACHeader->addr2[ii]; + } + } + } else { + /* Is AP mode.. */ + if (pMACHeader->frame_control & FC_FROMDS) { + for (ii = 0; ii < ETH_ALEN; ii++) { + psEthHeader->h_dest[ii] = + pMACHeader->addr3[ii]; + psEthHeader->h_source[ii] = + pMACHeader->addr4[ii]; + cbHeaderSize += 6; + } + } else { + for (ii = 0; ii < ETH_ALEN; ii++) { + psEthHeader->h_dest[ii] = + pMACHeader->addr3[ii]; + psEthHeader->h_source[ii] = + pMACHeader->addr2[ii]; + } + } + }; + *pcbHeaderSize = cbHeaderSize; +} + +int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB, + unsigned long BytesToIndicate) +{ + struct net_device_stats *pStats = &pDevice->stats; + struct sk_buff *skb; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct vnt_rx_mgmt *pRxPacket = &pMgmt->sRxPacket; + struct ieee80211_hdr *p802_11Header; + u8 *pbyRsr, *pbyNewRsr, *pbyRSSI, *pbyFrame; + u64 *pqwTSFTime; + u32 bDeFragRx = false; + u32 cbHeaderOffset, cbIVOffset; + u32 FrameSize; + u16 wEtherType = 0; + s32 iSANodeIndex = -1, iDANodeIndex = -1; + int ii; + u8 *pbyRxSts, *pbyRxRate, *pbySQ, *pby3SQ; + u32 cbHeaderSize; + PSKeyItem pKey = NULL; + u16 wRxTSC15_0 = 0; + u32 dwRxTSC47_16 = 0; + SKeyItem STempKey; + /* signed long ldBm = 0; */ + int bIsWEP = false; int bExtIV = false; + u32 dwWbkStatus; + PRCB pRCBIndicate = pRCB; + u8 *pbyDAddress; + u16 *pwPLCP_Length; + u8 abyVaildRate[MAX_RATE] + = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; + u16 wPLCPwithPadding; + struct ieee80211_hdr *pMACHeader; + int bRxeapol_key = false; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- RXbBulkInProcessData---\n"); + + skb = pRCB->skb; + + /* [31:16]RcvByteCount ( not include 4-byte Status ) */ + dwWbkStatus = *((u32 *)(skb->data)); + FrameSize = dwWbkStatus >> 16; + FrameSize += 4; + + if (BytesToIndicate != FrameSize) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"------- WRONG Length 1\n"); + return false; + } + + if ((BytesToIndicate > 2372) || (BytesToIndicate <= 40)) { + // Frame Size error drop this packet. + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 2\n"); + return false; + } + + pbyDAddress = (u8 *)(skb->data); + pbyRxSts = pbyDAddress+4; + pbyRxRate = pbyDAddress+5; + + //real Frame Size = USBFrameSize -4WbkStatus - 4RxStatus - 8TSF - 4RSR - 4SQ3 - ?Padding + //if SQ3 the range is 24~27, if no SQ3 the range is 20~23 + //real Frame size in PLCPLength field. + pwPLCP_Length = (u16 *) (pbyDAddress + 6); + //Fix hardware bug => PLCP_Length error + if ( ((BytesToIndicate - (*pwPLCP_Length)) > 27) || + ((BytesToIndicate - (*pwPLCP_Length)) < 24) || + (BytesToIndicate < (*pwPLCP_Length)) ) { + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong PLCP Length %x\n", (int) *pwPLCP_Length); + ASSERT(0); + return false; + } + for ( ii=RATE_1M;ii<MAX_RATE;ii++) { + if ( *pbyRxRate == abyVaildRate[ii] ) { + break; + } + } + if ( ii==MAX_RATE ) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong RxRate %x\n",(int) *pbyRxRate); + return false; + } + + wPLCPwithPadding = ( (*pwPLCP_Length / 4) + ( (*pwPLCP_Length % 4) ? 1:0 ) ) *4; + + pqwTSFTime = (u64 *)(pbyDAddress + 8 + wPLCPwithPadding); + if(pDevice->byBBType == BB_TYPE_11G) { + pby3SQ = pbyDAddress + 8 + wPLCPwithPadding + 12; + pbySQ = pby3SQ; + } + else { + pbySQ = pbyDAddress + 8 + wPLCPwithPadding + 8; + pby3SQ = pbySQ; + } + pbyNewRsr = pbyDAddress + 8 + wPLCPwithPadding + 9; + pbyRSSI = pbyDAddress + 8 + wPLCPwithPadding + 10; + pbyRsr = pbyDAddress + 8 + wPLCPwithPadding + 11; + + FrameSize = *pwPLCP_Length; + + pbyFrame = pbyDAddress + 8; + // update receive statistic counter + + STAvUpdateRDStatCounter(&pDevice->scStatistic, + *pbyRsr, + *pbyNewRsr, + *pbyRxSts, + *pbyRxRate, + pbyFrame, + FrameSize + ); + + pMACHeader = (struct ieee80211_hdr *) pbyFrame; + +//mike add: to judge if current AP is activated? + if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) || + (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) { + if (pMgmt->sNodeDBTable[0].bActive) { + if (!compare_ether_addr(pMgmt->abyCurrBSSID, pMACHeader->addr2)) { + if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + } + } + } + + if (!is_multicast_ether_addr(pMACHeader->addr1)) { + if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (struct ieee80211_hdr *) pbyFrame)) { + pDevice->s802_11Counter.FrameDuplicateCount++; + return false; + } + + if (compare_ether_addr(pDevice->abyCurrentNetAddr, + pMACHeader->addr1)) { + return false; + } + } + + // Use for TKIP MIC + s_vGetDASA(pbyFrame, &cbHeaderSize, &pDevice->sRxEthHeader); + + if (!compare_ether_addr((u8 *)&(pDevice->sRxEthHeader.h_source[0]), + pDevice->abyCurrentNetAddr)) + return false; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { + if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { + p802_11Header = (struct ieee80211_hdr *) (pbyFrame); + // get SA NodeIndex + if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(p802_11Header->addr2), &iSANodeIndex)) { + pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies; + pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0; + } + } + } + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex) == true) { + return false; + } + } + + if (IS_FC_WEP(pbyFrame)) { + bool bRxDecryOK = false; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rx WEP pkt\n"); + bIsWEP = true; + if ((pDevice->bEnableHostWEP) && (iSANodeIndex >= 0)) { + pKey = &STempKey; + pKey->byCipherSuite = pMgmt->sNodeDBTable[iSANodeIndex].byCipherSuite; + pKey->dwKeyIndex = pMgmt->sNodeDBTable[iSANodeIndex].dwKeyIndex; + pKey->uKeyLength = pMgmt->sNodeDBTable[iSANodeIndex].uWepKeyLength; + pKey->dwTSC47_16 = pMgmt->sNodeDBTable[iSANodeIndex].dwTSC47_16; + pKey->wTSC15_0 = pMgmt->sNodeDBTable[iSANodeIndex].wTSC15_0; + memcpy(pKey->abyKey, + &pMgmt->sNodeDBTable[iSANodeIndex].abyWepKey[0], + pKey->uKeyLength + ); + + bRxDecryOK = s_bHostWepRxEncryption(pDevice, + pbyFrame, + FrameSize, + pbyRsr, + pMgmt->sNodeDBTable[iSANodeIndex].bOnFly, + pKey, + pbyNewRsr, + &bExtIV, + &wRxTSC15_0, + &dwRxTSC47_16); + } else { + bRxDecryOK = s_bHandleRxEncryption(pDevice, + pbyFrame, + FrameSize, + pbyRsr, + pbyNewRsr, + &pKey, + &bExtIV, + &wRxTSC15_0, + &dwRxTSC47_16); + } + + if (bRxDecryOK) { + if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV Fail\n"); + if ( (pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { + + if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { + pDevice->s802_11Counter.TKIPICVErrors++; + } else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) { + pDevice->s802_11Counter.CCMPDecryptErrors++; + } else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_WEP)) { +// pDevice->s802_11Counter.WEPICVErrorCount.QuadPart++; + } + } + return false; + } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WEP Func Fail\n"); + return false; + } + if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) + FrameSize -= 8; // Message Integrity Code + else + FrameSize -= 4; // 4 is ICV + } + + // + // RX OK + // + /* remove the FCS/CRC length */ + FrameSize -= ETH_FCS_LEN; + + if ( !(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) && // unicast address + (IS_FRAGMENT_PKT((pbyFrame))) + ) { + // defragment + bDeFragRx = WCTLbHandleFragment(pDevice, (struct ieee80211_hdr *) (pbyFrame), FrameSize, bIsWEP, bExtIV); + pDevice->s802_11Counter.ReceivedFragmentCount++; + if (bDeFragRx) { + // defrag complete + // TODO skb, pbyFrame + skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb; + FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength; + pbyFrame = skb->data + 8; + } + else { + return false; + } + } + + // + // Management & Control frame Handle + // + if ((IS_TYPE_DATA((pbyFrame))) == false) { + // Handle Control & Manage Frame + + if (IS_TYPE_MGMT((pbyFrame))) { + u8 * pbyData1; + u8 * pbyData2; + + pRxPacket = &(pRCB->sMngPacket); + pRxPacket->p80211Header = (PUWLAN_80211HDR)(pbyFrame); + pRxPacket->cbMPDULen = FrameSize; + pRxPacket->uRSSI = *pbyRSSI; + pRxPacket->bySQ = *pbySQ; + pRxPacket->qwLocalTSF = cpu_to_le64(*pqwTSFTime); + if (bIsWEP) { + // strip IV + pbyData1 = WLAN_HDR_A3_DATA_PTR(pbyFrame); + pbyData2 = WLAN_HDR_A3_DATA_PTR(pbyFrame) + 4; + for (ii = 0; ii < (FrameSize - 4); ii++) { + *pbyData1 = *pbyData2; + pbyData1++; + pbyData2++; + } + } + + pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate); + + if ( *pbyRxSts == 0 ) { + //Discard beacon packet which channel is 0 + if ( (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_BEACON) || + (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_PROBERESP) ) { + return false; + } + } + pRxPacket->byRxChannel = (*pbyRxSts) >> 2; + + // hostap Deamon handle 802.11 management + if (pDevice->bEnableHostapd) { + skb->dev = pDevice->apdev; + //skb->data += 4; + //skb->tail += 4; + skb->data += 8; + skb->tail += 8; + skb_put(skb, FrameSize); + skb_reset_mac_header(skb); + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); + return true; + } + + // + // Insert the RCB in the Recv Mng list + // + EnqueueRCB(pDevice->FirstRecvMngList, pDevice->LastRecvMngList, pRCBIndicate); + pDevice->NumRecvMngList++; + if ( bDeFragRx == false) { + pRCB->Ref++; + } + if (pDevice->bIsRxMngWorkItemQueued == false) { + pDevice->bIsRxMngWorkItemQueued = true; + tasklet_schedule(&pDevice->RxMngWorkItem); + } + + } + else { + // Control Frame + }; + return false; + } + else { + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + //In AP mode, hw only check addr1(BSSID or RA) if equal to local MAC. + if ( !(*pbyRsr & RSR_BSSIDOK)) { + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return false; + } + } + else { + // discard DATA packet while not associate || BSSID error + if ((pDevice->bLinkPass == false) || + !(*pbyRsr & RSR_BSSIDOK)) { + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return false; + } + //mike add:station mode check eapol-key challenge---> + { + u8 Protocol_Version; //802.1x Authentication + u8 Packet_Type; //802.1x Authentication + u8 Descriptor_type; + u16 Key_info; + if (bIsWEP) + cbIVOffset = 8; + else + cbIVOffset = 0; + wEtherType = (skb->data[cbIVOffset + 8 + 24 + 6] << 8) | + skb->data[cbIVOffset + 8 + 24 + 6 + 1]; + Protocol_Version = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1]; + Packet_Type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1]; + if (wEtherType == ETH_P_PAE) { //Protocol Type in LLC-Header + if(((Protocol_Version==1) ||(Protocol_Version==2)) && + (Packet_Type==3)) { //802.1x OR eapol-key challenge frame receive + bRxeapol_key = true; + Descriptor_type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2]; + Key_info = (skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2+1]<<8) |skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1+1+2+2] ; + if(Descriptor_type==2) { //RSN + // printk("WPA2_Rx_eapol-key_info<-----:%x\n",Key_info); + } + else if(Descriptor_type==254) { + // printk("WPA_Rx_eapol-key_info<-----:%x\n",Key_info); + } + } + } + } + //mike add:station mode check eapol-key challenge<--- + } + } + +// Data frame Handle + + if (pDevice->bEnablePSMode) { + if (IS_FC_MOREDATA((pbyFrame))) { + if (*pbyRsr & RSR_ADDROK) { + //PSbSendPSPOLL((PSDevice)pDevice); + } + } + else { + if (pMgmt->bInTIMWake == true) { + pMgmt->bInTIMWake = false; + } + } + } + + // Now it only supports 802.11g Infrastructure Mode, and support rate must up to 54 Mbps + if (pDevice->bDiversityEnable && (FrameSize>50) && + (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) && + (pDevice->bLinkPass == true)) { + BBvAntennaDiversity(pDevice, s_byGetRateIdx(*pbyRxRate), 0); + } + + // ++++++++ For BaseBand Algorithm +++++++++++++++ + pDevice->uCurrRSSI = *pbyRSSI; + pDevice->byCurrSQ = *pbySQ; + + // todo +/* + if ((*pbyRSSI != 0) && + (pMgmt->pCurrBSS!=NULL)) { + RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); + // Monitor if RSSI is too strong. + pMgmt->pCurrBSS->byRSSIStatCnt++; + pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT; + pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm; + for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { + if (pMgmt->pCurrBSS->ldBmAverage[ii] != 0) { + pMgmt->pCurrBSS->ldBmMAX = + max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm); + } + } + } +*/ + + // ----------------------------------------------- + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnable8021x == true)){ + u8 abyMacHdr[24]; + + // Only 802.1x packet incoming allowed + if (bIsWEP) + cbIVOffset = 8; + else + cbIVOffset = 0; + wEtherType = (skb->data[cbIVOffset + 8 + 24 + 6] << 8) | + skb->data[cbIVOffset + 8 + 24 + 6 + 1]; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wEtherType = %04x \n", wEtherType); + if (wEtherType == ETH_P_PAE) { + skb->dev = pDevice->apdev; + + if (bIsWEP == true) { + // strip IV header(8) + memcpy(&abyMacHdr[0], (skb->data + 8), 24); + memcpy((skb->data + 8 + cbIVOffset), &abyMacHdr[0], 24); + } + + skb->data += (cbIVOffset + 8); + skb->tail += (cbIVOffset + 8); + skb_put(skb, FrameSize); + skb_reset_mac_header(skb); + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); + return true; + + } + // check if 802.1x authorized + if (!(pMgmt->sNodeDBTable[iSANodeIndex].dwFlags & WLAN_STA_AUTHORIZED)) + return false; + } + + if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { + if (bIsWEP) { + FrameSize -= 8; //MIC + } + } + + //-------------------------------------------------------------------------------- + // Soft MIC + if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { + if (bIsWEP) { + u32 * pdwMIC_L; + u32 * pdwMIC_R; + u32 dwMIC_Priority; + u32 dwMICKey0 = 0, dwMICKey1 = 0; + u32 dwLocalMIC_L = 0; + u32 dwLocalMIC_R = 0; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[24])); + dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[28])); + } + else { + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[16])); + dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[20])); + } else if ((pKey->dwKeyIndex & BIT28) == 0) { + dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[16])); + dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[20])); + } else { + dwMICKey0 = cpu_to_le32(*(u32 *)(&pKey->abyKey[24])); + dwMICKey1 = cpu_to_le32(*(u32 *)(&pKey->abyKey[28])); + } + } + + MIC_vInit(dwMICKey0, dwMICKey1); + MIC_vAppend((u8 *)&(pDevice->sRxEthHeader.h_dest[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((u8 *)&dwMIC_Priority, 4); + // 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV. + MIC_vAppend((u8 *)(skb->data + 8 + WLAN_HDR_ADDR3_LEN + 8), + FrameSize - WLAN_HDR_ADDR3_LEN - 8); + MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R); + MIC_vUnInit(); + + pdwMIC_L = (u32 *)(skb->data + 8 + FrameSize); + pdwMIC_R = (u32 *)(skb->data + 8 + FrameSize + 4); + + if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) || + (pDevice->bRxMICFail == true)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC comparison is fail!\n"); + pDevice->bRxMICFail = false; + //pDevice->s802_11Counter.TKIPLocalMICFailures.QuadPart++; + pDevice->s802_11Counter.TKIPLocalMICFailures++; + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + //send event to wpa_supplicant + //if(pDevice->bWPASuppWextEnabled == true) + { + union iwreq_data wrqu; + struct iw_michaelmicfailure ev; + int keyidx = pbyFrame[cbHeaderSize+3] >> 6; //top two-bits + memset(&ev, 0, sizeof(ev)); + ev.flags = keyidx & IW_MICFAILURE_KEY_ID; + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC) && + (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) { + ev.flags |= IW_MICFAILURE_PAIRWISE; + } else { + ev.flags |= IW_MICFAILURE_GROUP; + } + + ev.src_addr.sa_family = ARPHRD_ETHER; + memcpy(ev.src_addr.sa_data, pMACHeader->addr2, ETH_ALEN); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(ev); + PRINT_K("wireless_send_event--->IWEVMICHAELMICFAILURE\n"); + wireless_send_event(pDevice->dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); + + } + + return false; + + } + } + } //---end of SOFT MIC----------------------------------------------------------------------- + + // ++++++++++ Reply Counter Check +++++++++++++ + + if ((pKey != NULL) && ((pKey->byCipherSuite == KEY_CTL_TKIP) || + (pKey->byCipherSuite == KEY_CTL_CCMP))) { + if (bIsWEP) { + u16 wLocalTSC15_0 = 0; + u32 dwLocalTSC47_16 = 0; + unsigned long long RSC = 0; + // endian issues + RSC = *((unsigned long long *) &(pKey->KeyRSC)); + wLocalTSC15_0 = (u16) RSC; + dwLocalTSC47_16 = (u32) (RSC>>16); + + RSC = dwRxTSC47_16; + RSC <<= 16; + RSC += wRxTSC15_0; + memcpy(&(pKey->KeyRSC), &RSC, sizeof(u64)); + + if (pDevice->vnt_mgmt.eCurrMode == WMAC_MODE_ESS_STA && + pDevice->vnt_mgmt.eCurrState == WMAC_STATE_ASSOC) { + /* check RSC */ + if ( (wRxTSC15_0 < wLocalTSC15_0) && + (dwRxTSC47_16 <= dwLocalTSC47_16) && + !((dwRxTSC47_16 == 0) && (dwLocalTSC47_16 == 0xFFFFFFFF))) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC is illegal~~!\n "); + if (pKey->byCipherSuite == KEY_CTL_TKIP) + //pDevice->s802_11Counter.TKIPReplays.QuadPart++; + pDevice->s802_11Counter.TKIPReplays++; + else + //pDevice->s802_11Counter.CCMPReplays.QuadPart++; + pDevice->s802_11Counter.CCMPReplays++; + + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return false; + } + } + } + } // ----- End of Reply Counter Check -------------------------- + + s_vProcessRxMACHeader(pDevice, (u8 *)(skb->data+8), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset); + FrameSize -= cbHeaderOffset; + cbHeaderOffset += 8; // 8 is Rcv buffer header + + // Null data, framesize = 12 + if (FrameSize < 12) + return false; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (s_bAPModeRxData(pDevice, + skb, + FrameSize, + cbHeaderOffset, + iSANodeIndex, + iDANodeIndex + ) == false) { + + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return false; + } + + } + + skb->data += cbHeaderOffset; + skb->tail += cbHeaderOffset; + skb_put(skb, FrameSize); + skb->protocol=eth_type_trans(skb, skb->dev); + skb->ip_summed=CHECKSUM_NONE; + pStats->rx_bytes +=skb->len; + pStats->rx_packets++; + netif_rx(skb); + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + return false; + } + + return true; +} + +static int s_bAPModeRxCtl(struct vnt_private *pDevice, u8 *pbyFrame, + s32 iSANodeIndex) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct ieee80211_hdr *p802_11Header; + CMD_STATUS Status; + + if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { + + p802_11Header = (struct ieee80211_hdr *) (pbyFrame); + if (!IS_TYPE_MGMT(pbyFrame)) { + + // Data & PS-Poll packet + // check frame class + if (iSANodeIndex > 0) { + // frame class 3 fliter & checking + if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_AUTH) { + // send deauth notification + // reason = (6) class 2 received from nonauth sta + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + (u8 *)(p802_11Header->addr2), + (WLAN_MGMT_REASON_CLASS2_NONAUTH), + &Status + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 1\n"); + return true; + } + if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_ASSOC) { + // send deassoc notification + // reason = (7) class 3 received from nonassoc sta + vMgrDisassocBeginSta(pDevice, + pMgmt, + (u8 *)(p802_11Header->addr2), + (WLAN_MGMT_REASON_CLASS3_NONASSOC), + &Status + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDisassocBeginSta 2\n"); + return true; + } + + if (pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable) { + // delcare received ps-poll event + if (IS_CTL_PSPOLL(pbyFrame)) { + pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; + bScheduleCommand((void *) pDevice, + WLAN_CMD_RX_PSPOLL, + NULL); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 1\n"); + } + else { + // check Data PS state + // if PW bit off, send out all PS bufferring packets. + if (!IS_FC_POWERMGT(pbyFrame)) { + pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false; + pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; + bScheduleCommand((void *) pDevice, + WLAN_CMD_RX_PSPOLL, + NULL); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 2\n"); + } + } + } + else { + if (IS_FC_POWERMGT(pbyFrame)) { + pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = true; + // Once if STA in PS state, enable multicast bufferring + pMgmt->sNodeDBTable[0].bPSEnable = true; + } + else { + // clear all pending PS frame. + if (pMgmt->sNodeDBTable[iSANodeIndex].wEnQueueCnt > 0) { + pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = false; + pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = true; + bScheduleCommand((void *) pDevice, + WLAN_CMD_RX_PSPOLL, + NULL); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 3\n"); + + } + } + } + } + else { + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + (u8 *)(p802_11Header->addr2), + (WLAN_MGMT_REASON_CLASS2_NONAUTH), + &Status + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%pM\n", + p802_11Header->addr3); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%pM\n", + p802_11Header->addr2); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%pM\n", + p802_11Header->addr1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: frame_control= %x\n", p802_11Header->frame_control); + return true; + } + } + } + return false; + +} + +static int s_bHandleRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame, + u32 FrameSize, u8 *pbyRsr, u8 *pbyNewRsr, PSKeyItem *pKeyOut, + s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u32 PayloadLen = FrameSize; + u8 *pbyIV; + u8 byKeyIdx; + PSKeyItem pKey = NULL; + u8 byDecMode = KEY_CTL_WEP; + + *pwRxTSC15_0 = 0; + *pdwRxTSC47_16 = 0; + + pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; + if ( WLAN_GET_FC_TODS(*(u16 *)pbyFrame) && + WLAN_GET_FC_FROMDS(*(u16 *)pbyFrame) ) { + pbyIV += 6; // 6 is 802.11 address4 + PayloadLen -= 6; + } + byKeyIdx = (*(pbyIV+3) & 0xc0); + byKeyIdx >>= 6; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx); + + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { + if (((*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) && + (pMgmt->byCSSPK != KEY_CTL_NONE)) { + // unicast pkt use pairwise key + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt\n"); + if (KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, 0xFFFFFFFF, &pKey) == true) { + if (pMgmt->byCSSPK == KEY_CTL_TKIP) + byDecMode = KEY_CTL_TKIP; + else if (pMgmt->byCSSPK == KEY_CTL_CCMP) + byDecMode = KEY_CTL_CCMP; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt: %d, %p\n", byDecMode, pKey); + } else { + // use group key + KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, byKeyIdx, &pKey); + if (pMgmt->byCSSGK == KEY_CTL_TKIP) + byDecMode = KEY_CTL_TKIP; + else if (pMgmt->byCSSGK == KEY_CTL_CCMP) + byDecMode = KEY_CTL_CCMP; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"group pkt: %d, %d, %p\n", byKeyIdx, byDecMode, pKey); + } + } + // our WEP only support Default Key + if (pKey == NULL) { + // use default group key + KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, byKeyIdx, &pKey); + if (pMgmt->byCSSGK == KEY_CTL_TKIP) + byDecMode = KEY_CTL_TKIP; + else if (pMgmt->byCSSGK == KEY_CTL_CCMP) + byDecMode = KEY_CTL_CCMP; + } + *pKeyOut = pKey; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pMgmt->byCSSPK, pMgmt->byCSSGK, byDecMode); + + if (pKey == NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey == NULL\n"); + if (byDecMode == KEY_CTL_WEP) { +// pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; + } else if (pDevice->bLinkPass == true) { +// pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; + } + return false; + } + if (byDecMode != pKey->byCipherSuite) { + if (byDecMode == KEY_CTL_WEP) { +// pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; + } else if (pDevice->bLinkPass == true) { +// pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; + } + *pKeyOut = NULL; + return false; + } + if (byDecMode == KEY_CTL_WEP) { + // handle WEP + if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || + (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true)) { + // Software WEP + // 1. 3253A + // 2. WEP 256 + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc + memcpy(pDevice->abyPRNG, pbyIV, 3); + memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength); + rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3); + rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen); + + if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + } + } + } else if ((byDecMode == KEY_CTL_TKIP) || + (byDecMode == KEY_CTL_CCMP)) { + // TKIP/AES + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc + *pdwRxTSC47_16 = cpu_to_le32(*(u32 *)(pbyIV + 4)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); + if (byDecMode == KEY_CTL_TKIP) { + *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); + } else { + *pwRxTSC15_0 = cpu_to_le16(*(u16 *)pbyIV); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); + + if ((byDecMode == KEY_CTL_TKIP) && + (pDevice->byLocalID <= REV_ID_VT3253_A1)) { + // Software TKIP + // 1. 3253 A + struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *) (pbyFrame); + TKIPvMixKey(pKey->abyKey, pMACHeader->addr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG); + rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); + rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen); + if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n"); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen); + } + } + }// end of TKIP/AES + + if ((*(pbyIV+3) & 0x20) != 0) + *pbExtIV = true; + return true; +} + +static int s_bHostWepRxEncryption(struct vnt_private *pDevice, u8 *pbyFrame, + u32 FrameSize, u8 *pbyRsr, int bOnFly, PSKeyItem pKey, u8 *pbyNewRsr, + s32 *pbExtIV, u16 *pwRxTSC15_0, u32 *pdwRxTSC47_16) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct ieee80211_hdr *pMACHeader; + u32 PayloadLen = FrameSize; + u8 *pbyIV; + u8 byKeyIdx; + u8 byDecMode = KEY_CTL_WEP; + + *pwRxTSC15_0 = 0; + *pdwRxTSC47_16 = 0; + + pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; + if ( WLAN_GET_FC_TODS(*(u16 *)pbyFrame) && + WLAN_GET_FC_FROMDS(*(u16 *)pbyFrame) ) { + pbyIV += 6; // 6 is 802.11 address4 + PayloadLen -= 6; + } + byKeyIdx = (*(pbyIV+3) & 0xc0); + byKeyIdx >>= 6; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx); + + if (pMgmt->byCSSGK == KEY_CTL_TKIP) + byDecMode = KEY_CTL_TKIP; + else if (pMgmt->byCSSGK == KEY_CTL_CCMP) + byDecMode = KEY_CTL_CCMP; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pMgmt->byCSSPK, pMgmt->byCSSGK, byDecMode); + + if (byDecMode != pKey->byCipherSuite) { + if (byDecMode == KEY_CTL_WEP) { +// pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; + } else if (pDevice->bLinkPass == true) { +// pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; + } + return false; + } + + if (byDecMode == KEY_CTL_WEP) { + // handle WEP + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byDecMode == KEY_CTL_WEP\n"); + if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || + (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == true) || + (bOnFly == false)) { + // Software WEP + // 1. 3253A + // 2. WEP 256 + // 3. NotOnFly + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc + memcpy(pDevice->abyPRNG, pbyIV, 3); + memcpy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength); + rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3); + rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen); + + if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + } + } + } else if ((byDecMode == KEY_CTL_TKIP) || + (byDecMode == KEY_CTL_CCMP)) { + // TKIP/AES + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc + *pdwRxTSC47_16 = cpu_to_le32(*(u32 *)(pbyIV + 4)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); + + if (byDecMode == KEY_CTL_TKIP) { + *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); + } else { + *pwRxTSC15_0 = cpu_to_le16(*(u16 *)pbyIV); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); + + if (byDecMode == KEY_CTL_TKIP) { + + if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || (bOnFly == false)) { + // Software TKIP + // 1. 3253 A + // 2. NotOnFly + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_TKIP \n"); + pMACHeader = (struct ieee80211_hdr *) (pbyFrame); + TKIPvMixKey(pKey->abyKey, pMACHeader->addr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG); + rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); + rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen); + if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n"); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen); + } + } + } + + if (byDecMode == KEY_CTL_CCMP) { + if (bOnFly == false) { + // Software CCMP + // NotOnFly + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_CCMP\n"); + if (AESbGenCCMP(pKey->abyKey, pbyFrame, FrameSize)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CCMP MIC compare OK!\n"); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CCMP MIC fail!\n"); + } + } + } + + }// end of TKIP/AES + + if ((*(pbyIV+3) & 0x20) != 0) + *pbExtIV = true; + return true; +} + +static int s_bAPModeRxData(struct vnt_private *pDevice, struct sk_buff *skb, + u32 FrameSize, u32 cbHeaderOffset, s32 iSANodeIndex, s32 iDANodeIndex) +{ + struct sk_buff *skbcpy; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int bRelayAndForward = false; + int bRelayOnly = false; + u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + u16 wAID; + + if (FrameSize > CB_MAX_BUF_SIZE) + return false; + // check DA + if (is_multicast_ether_addr((u8 *)(skb->data+cbHeaderOffset))) { + if (pMgmt->sNodeDBTable[0].bPSEnable) { + + skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz); + + // if any node in PS mode, buffer packet until DTIM. + if (skbcpy == NULL) { + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n"); + } + else { + skbcpy->dev = pDevice->dev; + skbcpy->len = FrameSize; + memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize); + skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy); + pMgmt->sNodeDBTable[0].wEnQueueCnt++; + // set tx map + pMgmt->abyPSTxMap[0] |= byMask[0]; + } + } + else { + bRelayAndForward = true; + } + } + else { + // check if relay + if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(skb->data+cbHeaderOffset), &iDANodeIndex)) { + if (pMgmt->sNodeDBTable[iDANodeIndex].eNodeState >= NODE_ASSOC) { + if (pMgmt->sNodeDBTable[iDANodeIndex].bPSEnable) { + // queue this skb until next PS tx, and then release. + + skb->data += cbHeaderOffset; + skb->tail += cbHeaderOffset; + skb_put(skb, FrameSize); + skb_queue_tail(&pMgmt->sNodeDBTable[iDANodeIndex].sTxPSQueue, skb); + + pMgmt->sNodeDBTable[iDANodeIndex].wEnQueueCnt++; + wAID = pMgmt->sNodeDBTable[iDANodeIndex].wAID; + pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "relay: index= %d, pMgmt->abyPSTxMap[%d]= %d\n", + iDANodeIndex, (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]); + return true; + } + else { + bRelayOnly = true; + } + } + } + } + + if (bRelayOnly || bRelayAndForward) { + // relay this packet right now + if (bRelayAndForward) + iDANodeIndex = 0; + + if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) { + bRelayPacketSend(pDevice, (u8 *) (skb->data + cbHeaderOffset), + FrameSize, (unsigned int) iDANodeIndex); + } + + if (bRelayOnly) + return false; + } + // none associate, don't forward + if (pDevice->uAssocCount == 0) + return false; + + return true; +} + +void RXvWorkItem(struct vnt_private *pDevice) +{ + int ntStatus; + PRCB pRCB = NULL; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n"); + spin_lock_irq(&pDevice->lock); + + while ((pDevice->Flags & fMP_POST_READS) && + MP_IS_READY(pDevice) && + (pDevice->NumRecvFreeList != 0) ) { + pRCB = pDevice->FirstRecvFreeList; + pDevice->NumRecvFreeList--; + ASSERT(pRCB);// cannot be NULL + DequeueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList); + ntStatus = PIPEnsBulkInUsbRead(pDevice, pRCB); + } + pDevice->bIsRxWorkItemQueued = false; + spin_unlock_irq(&pDevice->lock); + +} + +void RXvFreeRCB(PRCB pRCB, int bReAllocSkb) +{ + struct vnt_private *pDevice = pRCB->pDevice; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n"); + + ASSERT(!pRCB->Ref); // should be 0 + ASSERT(pRCB->pDevice); // shouldn't be NULL + + if (bReAllocSkb == false) { + kfree_skb(pRCB->skb); + bReAllocSkb = true; + } + + if (bReAllocSkb == true) { + pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + // todo error handling + if (pRCB->skb == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to re-alloc rx skb\n"); + }else { + pRCB->skb->dev = pDevice->dev; + } + } + // + // Insert the RCB back in the Recv free list + // + EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB); + pDevice->NumRecvFreeList++; + + if ((pDevice->Flags & fMP_POST_READS) && MP_IS_READY(pDevice) && + (pDevice->bIsRxWorkItemQueued == false) ) { + + pDevice->bIsRxWorkItemQueued = true; + tasklet_schedule(&pDevice->ReadWorkItem); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",pDevice->NumRecvFreeList, pDevice->NumRecvMngList); +} + +void RXvMngWorkItem(struct vnt_private *pDevice) +{ + PRCB pRCB = NULL; + struct vnt_rx_mgmt *pRxPacket; + int bReAllocSkb = false; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Mng Thread\n"); + + spin_lock_irq(&pDevice->lock); + while (pDevice->NumRecvMngList!=0) + { + pRCB = pDevice->FirstRecvMngList; + pDevice->NumRecvMngList--; + DequeueRCB(pDevice->FirstRecvMngList, pDevice->LastRecvMngList); + if(!pRCB){ + break; + } + ASSERT(pRCB);// cannot be NULL + pRxPacket = &(pRCB->sMngPacket); + vMgrRxManagePacket(pDevice, &pDevice->vnt_mgmt, pRxPacket); + pRCB->Ref--; + if(pRCB->Ref == 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeMng %d %d\n",pDevice->NumRecvFreeList, pDevice->NumRecvMngList); + RXvFreeRCB(pRCB, bReAllocSkb); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rx Mng Only we have the right to free RCB\n"); + } + } + + pDevice->bIsRxMngWorkItemQueued = false; + spin_unlock_irq(&pDevice->lock); + +} + diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h new file mode 100644 index 00000000..876468f2 --- /dev/null +++ b/drivers/staging/vt6656/dpc.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: dpc.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + */ + +#ifndef __DPC_H__ +#define __DPC_H__ + +#include "device.h" +#include "wcmd.h" + +void RXvWorkItem(void *Context); + +void RXvMngWorkItem(void *Context); + +void RXvFreeRCB(PRCB pRCB, int bReAllocSkb); + +int RXbBulkInProcessData(struct vnt_private *, PRCB pRCB, + unsigned long BytesToIndicate); + +#endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c new file mode 100644 index 00000000..a1dc3a4c --- /dev/null +++ b/drivers/staging/vt6656/firmware.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: baseband.c + * + * Purpose: Implement functions to access baseband + * + * Author: Yiching Chen + * + * Date: May 20, 2004 + * + * Functions: + * + * Revision History: + * + */ + +#include "firmware.h" +#include "control.h" +#include "rndis.h" + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +#define FIRMWARE_VERSION 0x133 /* version 1.51 */ +#define FIRMWARE_NAME "vntwusb.fw" + +#define FIRMWARE_CHUNK_SIZE 0x400 + +int FIRMWAREbDownload(struct vnt_private *pDevice) +{ + struct device *dev = &pDevice->usb->dev; + const struct firmware *fw; + int NdisStatus; + void *pBuffer = NULL; + bool result = false; + u16 wLength; + int ii, rc; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n"); + spin_unlock_irq(&pDevice->lock); + + rc = request_firmware(&fw, FIRMWARE_NAME, dev); + if (rc) { + dev_err(dev, "firmware file %s request failed (%d)\n", + FIRMWARE_NAME, rc); + goto out; + } + + pBuffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); + if (!pBuffer) + goto out; + + for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) { + wLength = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE); + memcpy(pBuffer, fw->data + ii, wLength); + + NdisStatus = CONTROLnsRequestOutAsyn(pDevice, + 0, + 0x1200+ii, + 0x0000, + wLength, + pBuffer + ); + + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO"Download firmware...%d %zu\n", ii, fw->size); + if (NdisStatus != STATUS_SUCCESS) + goto free_fw; + } + + result = true; +free_fw: + release_firmware(fw); + +out: + kfree(pBuffer); + + spin_lock_irq(&pDevice->lock); + return result; +} +MODULE_FIRMWARE(FIRMWARE_NAME); + +int FIRMWAREbBrach2Sram(struct vnt_private *pDevice) +{ + int NdisStatus; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Branch to Sram\n"); + + NdisStatus = CONTROLnsRequestOut(pDevice, + 1, + 0x1200, + 0x0000, + 0, + NULL + ); + + if (NdisStatus != STATUS_SUCCESS) { + return (false); + } else { + return (true); + } +} + +int FIRMWAREbCheckVersion(struct vnt_private *pDevice) +{ + int ntStatus; + + ntStatus = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + 0, + MESSAGE_REQUEST_VERSION, + 2, + (u8 *) &(pDevice->wFirmwareVersion)); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion); + if (ntStatus != STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Invalid.\n"); + return false; + } + if (pDevice->wFirmwareVersion == 0xFFFF) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"In Loader.\n"); + return false; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion); + if (pDevice->wFirmwareVersion < FIRMWARE_VERSION) { + // branch to loader for download new firmware + FIRMWAREbBrach2Sram(pDevice); + return false; + } + return true; +} diff --git a/drivers/staging/vt6656/firmware.h b/drivers/staging/vt6656/firmware.h new file mode 100644 index 00000000..e3b08db6 --- /dev/null +++ b/drivers/staging/vt6656/firmware.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: firmware.h + * + * Purpose: Version and Release Information + * + * Author: Yiching Chen + * + * Date: May 20, 2004 + * + */ + +#ifndef __FIRMWARE_H__ +#define __FIRMWARE_H__ + +#include "device.h" + +int FIRMWAREbDownload(struct vnt_private *); +int FIRMWAREbBrach2Sram(struct vnt_private *); +int FIRMWAREbCheckVersion(struct vnt_private *); + +#endif /* __FIRMWARE_H__ */ diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c new file mode 100644 index 00000000..c699a305 --- /dev/null +++ b/drivers/staging/vt6656/hostap.c @@ -0,0 +1,778 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: hostap.c + * + * Purpose: handle hostap daemon ioctl input/out functions + * + * Author: Lyndon Chen + * + * Date: Oct. 20, 2003 + * + * Functions: + * + * Revision History: + * + */ + +#include "hostap.h" +#include "iocmd.h" +#include "mac.h" +#include "card.h" +#include "baseband.h" +#include "wpactl.h" +#include "key.h" +#include "datarate.h" + +#define VIAWGET_HOSTAPD_MAX_BUF_SIZE 1024 +#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT0 +#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 +#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 + +static int msglevel =MSG_LEVEL_INFO; + +/* + * Description: + * register net_device (AP) for hostap daemon + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +static int hostap_enable_hostapd(struct vnt_private *pDevice, int rtnl_locked) +{ + struct vnt_private *apdev_priv; + struct net_device *dev = pDevice->dev; + int ret; + const struct net_device_ops apdev_netdev_ops = { + .ndo_start_xmit = pDevice->tx_80211, + }; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Enabling hostapd mode\n", dev->name); + + pDevice->apdev = kzalloc(sizeof(struct net_device), GFP_KERNEL); + if (pDevice->apdev == NULL) + return -ENOMEM; + + apdev_priv = netdev_priv(pDevice->apdev); + *apdev_priv = *pDevice; + memcpy(pDevice->apdev->dev_addr, dev->dev_addr, ETH_ALEN); + + pDevice->apdev->netdev_ops = &apdev_netdev_ops; + + pDevice->apdev->type = ARPHRD_IEEE80211; + + pDevice->apdev->base_addr = dev->base_addr; + pDevice->apdev->irq = dev->irq; + pDevice->apdev->mem_start = dev->mem_start; + pDevice->apdev->mem_end = dev->mem_end; + sprintf(pDevice->apdev->name, "%sap", dev->name); + if (rtnl_locked) + ret = register_netdevice(pDevice->apdev); + else + ret = register_netdev(pDevice->apdev); + if (ret) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(AP) failed!\n", + dev->name); + return -1; + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %s for AP management\n", + dev->name, pDevice->apdev->name); + + KeyvInitTable(pDevice,&pDevice->sKey); + + return 0; +} + +/* + * Description: + * unregister net_device(AP) + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +static int hostap_disable_hostapd(struct vnt_private *pDevice, int rtnl_locked) +{ + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: disabling hostapd mode\n", pDevice->dev->name); + + if (pDevice->apdev && pDevice->apdev->name && pDevice->apdev->name[0]) { + if (rtnl_locked) + unregister_netdevice(pDevice->apdev); + else + unregister_netdev(pDevice->apdev); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", + pDevice->dev->name, pDevice->apdev->name); + } + free_netdev(pDevice->apdev); + pDevice->apdev = NULL; + pDevice->bEnable8021x = false; + pDevice->bEnableHostWEP = false; + pDevice->bEncryptionEnable = false; + + return 0; +} + +/* + * Description: + * Set enable/disable hostapd mode + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +int vt6656_hostap_set_hostapd(struct vnt_private *pDevice, + int val, int rtnl_locked) +{ + if (val < 0 || val > 1) + return -EINVAL; + + if (pDevice->bEnableHostapd == val) + return 0; + + pDevice->bEnableHostapd = val; + + if (val) + return hostap_enable_hostapd(pDevice, rtnl_locked); + else + return hostap_disable_hostapd(pDevice, rtnl_locked); +} + +/* + * Description: + * remove station function supported for hostap daemon + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_remove_sta(struct vnt_private *pDevice, + struct viawget_hostapd_param *param) +{ + unsigned int uNodeIndex; + + if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) { + BSSvRemoveOneNode(pDevice, uNodeIndex); + } + else { + return -ENOENT; + } + return 0; +} + +/* + * Description: + * add a station from hostap daemon + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_add_sta(struct vnt_private *pDevice, + struct viawget_hostapd_param *param) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + unsigned int uNodeIndex; + + if (!BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) + BSSvCreateOneNode(pDevice, &uNodeIndex); + + memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, param->sta_addr, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC; + pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = param->u.add_sta.capability; +// TODO listenInterval +// pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = 1; + pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = false; + pMgmt->sNodeDBTable[uNodeIndex].bySuppRate = param->u.add_sta.tx_supp_rates; + + // set max tx rate + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; + // set max basic rate + pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate = RATE_2M; + // Todo: check sta preamble, if ap can't support, set status code + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = + WLAN_GET_CAP_INFO_SHORTPREAMBLE(pMgmt->sNodeDBTable[uNodeIndex].wCapInfo); + + pMgmt->sNodeDBTable[uNodeIndex].wAID = (u16)param->u.add_sta.aid; + + pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Add STA AID= %d \n", pMgmt->sNodeDBTable[uNodeIndex].wAID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n", + param->sta_addr[0], + param->sta_addr[1], + param->sta_addr[2], + param->sta_addr[3], + param->sta_addr[4], + param->sta_addr[5] + ) ; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Max Support rate = %d \n", + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate); + + return 0; +} + +/* + * Description: + * get station info + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int hostap_get_info_sta(struct vnt_private *pDevice, + struct viawget_hostapd_param *param) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + unsigned int uNodeIndex; + + if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) { + param->u.get_info_sta.inactive_sec = + (jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ; + + //param->u.get_info_sta.txexc = pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts; + } + else { + return -ENOENT; + } + + return 0; +} + +/* + * Description: + * set station flag + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_flags_sta(struct vnt_private *pDevice, + struct viawget_hostapd_param *param) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + unsigned int uNodeIndex; + + if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) { + pMgmt->sNodeDBTable[uNodeIndex].dwFlags |= param->u.set_flags_sta.flags_or; + pMgmt->sNodeDBTable[uNodeIndex].dwFlags &= param->u.set_flags_sta.flags_and; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " dwFlags = %x\n", + (unsigned int) pMgmt->sNodeDBTable[uNodeIndex].dwFlags); + } + else { + return -ENOENT; + } + + return 0; +} + +/* + * Description: + * set generic element (wpa ie) + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_generic_element(struct vnt_private *pDevice, + struct viawget_hostapd_param *param) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + memcpy( pMgmt->abyWPAIE, + param->u.generic_elem.data, + param->u.generic_elem.len + ); + + pMgmt->wWPAIELen = param->u.generic_elem.len; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pMgmt->wWPAIELen = %d\n", pMgmt->wWPAIELen); + + // disable wpa + if (pMgmt->wWPAIELen == 0) { + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " No WPAIE, Disable WPA \n"); + } else { + // enable wpa + if ((pMgmt->abyWPAIE[0] == WLAN_EID_RSN_WPA) || + (pMgmt->abyWPAIE[0] == WLAN_EID_RSN)) { + pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set WPAIE enable WPA\n"); + } else + return -EINVAL; + } + + return 0; +} + +/* + * Description: + * flush station nodes table. + * + * Parameters: + * In: + * pDevice - + * Out: + * + * Return Value: + * + */ + +static void hostap_flush_sta(struct vnt_private *pDevice) +{ + // reserved node index =0 for multicast node. + BSSvClearNodeDBTable(pDevice, 1); + pDevice->uAssocCount = 0; + + return; +} + +/* + * Description: + * set each stations encryption key + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_encryption(struct vnt_private *pDevice, + struct viawget_hostapd_param *param, int param_len) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u32 dwKeyIndex = 0; + u8 abyKey[MAX_KEY_LEN]; + u8 abySeq[MAX_KEY_LEN]; + NDIS_802_11_KEY_RSC KeyRSC; + u8 byKeyDecMode = KEY_CTL_WEP; + int ret = 0; + s32 iNodeIndex = -1; + int ii; + int bKeyTableFull = false; + u16 wKeyCtl = 0; + + param->u.crypt.err = 0; + + if (param->u.crypt.alg > WPA_ALG_CCMP) + return -EINVAL; + + if ((param->u.crypt.idx > 3) || (param->u.crypt.key_len > MAX_KEY_LEN)) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_KEY_SET_FAILED\n"); + return -EINVAL; + } + + if (is_broadcast_ether_addr(param->sta_addr)) { + if (param->u.crypt.idx >= MAX_GROUP_KEY) + return -EINVAL; + iNodeIndex = 0; + + } else { + if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &iNodeIndex) == false) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n"); + return -EINVAL; + } + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: sta_index %d \n", iNodeIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: alg %d \n", param->u.crypt.alg); + + if (param->u.crypt.alg == WPA_ALG_NONE) { + + if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly == true) { + if (KeybRemoveKey( pDevice, + &(pDevice->sKey), + param->sta_addr, + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex + ) == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybRemoveKey fail \n"); + } + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false; + } + pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = 0; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = 0; + pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = 0; + pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = 0; + pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0; + pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = 0; + memset(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + 0, + MAX_KEY_LEN + ); + + return ret; + } + + memcpy(abyKey, param->u.crypt.key, param->u.crypt.key_len); + // copy to node key tbl + pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = param->u.crypt.idx; + pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = param->u.crypt.key_len; + memcpy(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + param->u.crypt.key, + param->u.crypt.key_len + ); + + dwKeyIndex = (u32)(param->u.crypt.idx); + if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) { + pDevice->byKeyIndex = (u8)dwKeyIndex; + pDevice->bTransmitKey = true; + dwKeyIndex |= (1 << 31); + } + + if (param->u.crypt.alg == WPA_ALG_WEP) { + + if ((pDevice->bEnable8021x == false) || (iNodeIndex == 0)) { + KeybSetDefaultKey( pDevice, + &(pDevice->sKey), + dwKeyIndex & ~(BIT30 | USE_KEYRSC), + param->u.crypt.key_len, + NULL, + abyKey, + KEY_CTL_WEP + ); + + } else { + // 8021x enable, individual key + dwKeyIndex |= (1 << 30); // set pairwise key + if (KeybSetKey(pDevice, &(pDevice->sKey), + ¶m->sta_addr[0], + dwKeyIndex & ~(USE_KEYRSC), + param->u.crypt.key_len, + &KeyRSC, (u8 *)abyKey, + KEY_CTL_WEP + ) == true) { + + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true; + + } else { + // Key Table Full + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false; + bKeyTableFull = true; + } + } + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + pDevice->bEncryptionEnable = true; + pMgmt->byCSSPK = KEY_CTL_WEP; + pMgmt->byCSSGK = KEY_CTL_WEP; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = KEY_CTL_WEP; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex; + return ret; + } + + if (param->u.crypt.seq) { + memcpy(&abySeq, param->u.crypt.seq, 8); + for (ii = 0 ; ii < 8 ; ii++) + KeyRSC |= (unsigned long)abySeq[ii] << (ii * 8); + + dwKeyIndex |= 1 << 29; + pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC; + } + + if (param->u.crypt.alg == WPA_ALG_TKIP) { + if (param->u.crypt.key_len != MAX_KEY_LEN) + return -EINVAL; + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + byKeyDecMode = KEY_CTL_TKIP; + pMgmt->byCSSPK = KEY_CTL_TKIP; + pMgmt->byCSSGK = KEY_CTL_TKIP; + } + + if (param->u.crypt.alg == WPA_ALG_CCMP) { + if ((param->u.crypt.key_len != AES_KEY_LEN) || + (pDevice->byLocalID <= REV_ID_VT3253_A1)) + return -EINVAL; + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + byKeyDecMode = KEY_CTL_CCMP; + pMgmt->byCSSPK = KEY_CTL_CCMP; + pMgmt->byCSSGK = KEY_CTL_CCMP; + } + + if (iNodeIndex == 0) { + KeybSetDefaultKey( pDevice, + &(pDevice->sKey), + dwKeyIndex, + param->u.crypt.key_len, + &KeyRSC, + abyKey, + byKeyDecMode + ); + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true; + + } else { + dwKeyIndex |= (1 << 30); // set pairwise key + if (KeybSetKey(pDevice, + &(pDevice->sKey), + ¶m->sta_addr[0], + dwKeyIndex, + param->u.crypt.key_len, + &KeyRSC, + (u8 *)abyKey, + byKeyDecMode + ) == true) { + + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true; + + } else { + // Key Table Full + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false; + bKeyTableFull = true; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Key Table Full\n"); + } + + } + + if (bKeyTableFull == true) { + wKeyCtl &= 0x7F00; // clear all key control filed + wKeyCtl |= (byKeyDecMode << 4); + wKeyCtl |= (byKeyDecMode); + wKeyCtl |= 0x0044; // use group key for all address + wKeyCtl |= 0x4000; // disable KeyTable[MAX_KEY_TABLE-1] on-fly to genernate rx int +// Todo.. xxxxxx + //MACvSetDefaultKeyCtl(pDevice->PortOffset, wKeyCtl, MAX_KEY_TABLE-1, pDevice->byLocalID); + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set key sta_index= %d \n", iNodeIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " tx_index=%d len=%d \n", param->u.crypt.idx, + param->u.crypt.key_len ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n", + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[1], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[2], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[3], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[4] + ); + + // set wep key + pDevice->bEncryptionEnable = true; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = byKeyDecMode; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex; + pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0; + pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0; + + return ret; +} + +/* + * Description: + * get each stations encryption key + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_get_encryption(struct vnt_private *pDevice, + struct viawget_hostapd_param *param, + int param_len) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int ret = 0; + int ii; + s32 iNodeIndex = 0; + + param->u.crypt.err = 0; + + if (is_broadcast_ether_addr(param->sta_addr)) { + iNodeIndex = 0; + } else { + if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &iNodeIndex) == false) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n"); + return -EINVAL; + } + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: %d\n", iNodeIndex); + memset(param->u.crypt.seq, 0, 8); + for (ii = 0 ; ii < 8 ; ii++) { + param->u.crypt.seq[ii] = (u8)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8); + } + + return ret; +} + +/* + * Description: + * vt6656_hostap_ioctl main function supported for hostap daemon. + * + * Parameters: + * In: + * pDevice - + * iw_point - + * Out: + * + * Return Value: + * + */ + +int vt6656_hostap_ioctl(struct vnt_private *pDevice, struct iw_point *p) +{ + struct viawget_hostapd_param *param; + int ret = 0; + int ap_ioctl = 0; + + if (p->length < sizeof(struct viawget_hostapd_param) || + p->length > VIAWGET_HOSTAPD_MAX_BUF_SIZE || !p->pointer) + return -EINVAL; + + param = kmalloc((int)p->length, (int)GFP_KERNEL); + if (param == NULL) + return -ENOMEM; + + if (copy_from_user(param, p->pointer, p->length)) { + ret = -EFAULT; + goto out; + } + + switch (param->cmd) { + case VIAWGET_HOSTAPD_SET_ENCRYPTION: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ENCRYPTION \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_set_encryption(pDevice, param, p->length); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_GET_ENCRYPTION: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_ENCRYPTION \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_get_encryption(pDevice, param, p->length); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n"); + ret = -EOPNOTSUPP; + goto out; + case VIAWGET_HOSTAPD_FLUSH: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n"); + spin_lock_irq(&pDevice->lock); + hostap_flush_sta(pDevice); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_ADD_STA: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_ADD_STA \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_add_sta(pDevice, param); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_REMOVE_STA: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_REMOVE_STA \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_remove_sta(pDevice, param); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_GET_INFO_STA: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_INFO_STA \n"); + ret = hostap_get_info_sta(pDevice, param); + ap_ioctl = 1; + break; + case VIAWGET_HOSTAPD_SET_FLAGS_STA: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_FLAGS_STA \n"); + ret = hostap_set_flags_sta(pDevice, param); + break; + + case VIAWGET_HOSTAPD_MLME: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_MLME \n"); + return -EOPNOTSUPP; + + case VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT \n"); + ret = hostap_set_generic_element(pDevice, param); + break; + + case VIAWGET_HOSTAPD_SCAN_REQ: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SCAN_REQ \n"); + return -EOPNOTSUPP; + + case VIAWGET_HOSTAPD_STA_CLEAR_STATS: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n"); + ret = -EOPNOTSUPP; + goto out; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vt6656_hostap_ioctl: unknown cmd=%d\n", + (int)param->cmd); + ret = -EOPNOTSUPP; + goto out; + } + + if ((ret == 0) && ap_ioctl) { + if (copy_to_user(p->pointer, param, p->length)) { + ret = -EFAULT; + goto out; + } + } + + out: + kfree(param); + + return ret; +} + diff --git a/drivers/staging/vt6656/hostap.h b/drivers/staging/vt6656/hostap.h new file mode 100644 index 00000000..6a68f7e6 --- /dev/null +++ b/drivers/staging/vt6656/hostap.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: hostap.h + * + * Purpose: + * + * Author: Lyndon Chen + * + * Date: May 21, 2003 + * + */ + +#ifndef __HOSTAP_H__ +#define __HOSTAP_H__ + +#include "device.h" + +#define WLAN_RATE_1M BIT0 +#define WLAN_RATE_2M BIT1 +#define WLAN_RATE_5M5 BIT2 +#define WLAN_RATE_11M BIT3 +#define WLAN_RATE_6M BIT4 +#define WLAN_RATE_9M BIT5 +#define WLAN_RATE_12M BIT6 +#define WLAN_RATE_18M BIT7 +#define WLAN_RATE_24M BIT8 +#define WLAN_RATE_36M BIT9 +#define WLAN_RATE_48M BIT10 +#define WLAN_RATE_54M BIT11 + +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#endif /* ETH_P_PAE */ + +#ifndef ARPHRD_IEEE80211 +#define ARPHRD_IEEE80211 801 +#endif + +int vt6656_hostap_set_hostapd(struct vnt_private *, int val, int rtnl_locked); +int vt6656_hostap_ioctl(struct vnt_private *, struct iw_point *p); + +#endif /* __HOSTAP_H__ */ diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c new file mode 100644 index 00000000..a2b4ba6d --- /dev/null +++ b/drivers/staging/vt6656/int.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: int.c + * + * Purpose: Handle USB interrupt endpoint + * + * Author: Jerry Chen + * + * Date: Apr. 2, 2004 + * + * Functions: + * + * Revision History: + * 04-02-2004 Jerry Chen: Initial release + * + */ + +#include "int.h" +#include "mib.h" +#include "tmacro.h" +#include "mac.h" +#include "power.h" +#include "bssdb.h" +#include "usbpipe.h" + +static int msglevel = MSG_LEVEL_INFO; /* MSG_LEVEL_DEBUG */ + +/*+ + * + * Function: InterruptPollingThread + * + * Synopsis: Thread running at IRQL PASSIVE_LEVEL. + * + * Arguments: Device Extension + * + * Returns: + * + * Algorithm: Call USBD for input data; + * + * History: dd-mm-yyyy Author Comment + * + * + * Notes: + * + * USB reads are by nature 'Blocking', and when in a read, the device looks + * like it's in a 'stall' condition, so we deliberately time out every second + * if we've gotten no data + * +-*/ +void INTvWorkItem(struct vnt_private *pDevice) +{ + int ntStatus; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Interrupt Polling Thread\n"); + + spin_lock_irq(&pDevice->lock); + if (pDevice->fKillEventPollingThread != true) + ntStatus = PIPEnsInterruptRead(pDevice); + spin_unlock_irq(&pDevice->lock); +} + +void INTnsProcessData(struct vnt_private *pDevice) +{ + PSINTData pINTData; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct net_device_stats *pStats = &pDevice->stats; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptProcessData\n"); + + pINTData = (PSINTData) pDevice->intBuf.pDataBuf; + if (pINTData->byTSR0 & TSR_VALID) { + STAvUpdateTDStatCounter(&(pDevice->scStatistic), + (u8)(pINTData->byPkt0 & 0x0F), + (u8)(pINTData->byPkt0>>4), + pINTData->byTSR0); + BSSvUpdateNodeTxCounter(pDevice, + &(pDevice->scStatistic), + pINTData->byTSR0, + pINTData->byPkt0); + /*DBG_PRN_GRP01(("TSR0 %02x\n", pINTData->byTSR0));*/ + } + if (pINTData->byTSR1 & TSR_VALID) { + STAvUpdateTDStatCounter(&(pDevice->scStatistic), + (u8)(pINTData->byPkt1 & 0x0F), + (u8)(pINTData->byPkt1>>4), + pINTData->byTSR1); + BSSvUpdateNodeTxCounter(pDevice, + &(pDevice->scStatistic), + pINTData->byTSR1, + pINTData->byPkt1); + /*DBG_PRN_GRP01(("TSR1 %02x\n", pINTData->byTSR1));*/ + } + if (pINTData->byTSR2 & TSR_VALID) { + STAvUpdateTDStatCounter(&(pDevice->scStatistic), + (u8)(pINTData->byPkt2 & 0x0F), + (u8)(pINTData->byPkt2>>4), + pINTData->byTSR2); + BSSvUpdateNodeTxCounter(pDevice, + &(pDevice->scStatistic), + pINTData->byTSR2, + pINTData->byPkt2); + /*DBG_PRN_GRP01(("TSR2 %02x\n", pINTData->byTSR2));*/ + } + if (pINTData->byTSR3 & TSR_VALID) { + STAvUpdateTDStatCounter(&(pDevice->scStatistic), + (u8)(pINTData->byPkt3 & 0x0F), + (u8)(pINTData->byPkt3>>4), + pINTData->byTSR3); + BSSvUpdateNodeTxCounter(pDevice, + &(pDevice->scStatistic), + pINTData->byTSR3, + pINTData->byPkt3); + /*DBG_PRN_GRP01(("TSR3 %02x\n", pINTData->byTSR3));*/ + } + if (pINTData->byISR0 != 0) { + if (pINTData->byISR0 & ISR_BNTX) { + if (pDevice->eOPMode == OP_MODE_AP) { + if (pMgmt->byDTIMCount > 0) { + pMgmt->byDTIMCount--; + pMgmt->sNodeDBTable[0].bRxPSPoll = + false; + } else if (pMgmt->byDTIMCount == 0) { + /* check if multicast tx buffering */ + pMgmt->byDTIMCount = + pMgmt->byDTIMPeriod-1; + pMgmt->sNodeDBTable[0].bRxPSPoll = true; + if (pMgmt->sNodeDBTable[0].bPSEnable) + bScheduleCommand((void *) pDevice, + WLAN_CMD_RX_PSPOLL, + NULL); + } + bScheduleCommand((void *) pDevice, + WLAN_CMD_BECON_SEND, + NULL); + } /* if (pDevice->eOPMode == OP_MODE_AP) */ + pDevice->bBeaconSent = true; + } else { + pDevice->bBeaconSent = false; + } + if (pINTData->byISR0 & ISR_TBTT) { + if (pDevice->bEnablePSMode) + bScheduleCommand((void *) pDevice, + WLAN_CMD_TBTT_WAKEUP, + NULL); + if (pDevice->bChannelSwitch) { + pDevice->byChannelSwitchCount--; + if (pDevice->byChannelSwitchCount == 0) + bScheduleCommand((void *) pDevice, + WLAN_CMD_11H_CHSW, + NULL); + } + } + pDevice->qwCurrTSF = cpu_to_le64(pINTData->qwTSF); + /*DBG_PRN_GRP01(("ISR0 = %02x , + LoTsf = %08x, + HiTsf = %08x\n", + pINTData->byISR0, + pINTData->dwLoTSF, + pINTData->dwHiTSF)); */ + + STAvUpdate802_11Counter(&pDevice->s802_11Counter, + &pDevice->scStatistic, + pINTData->byRTSSuccess, + pINTData->byRTSFail, + pINTData->byACKFail, + pINTData->byFCSErr); + STAvUpdateIsrStatCounter(&pDevice->scStatistic, + pINTData->byISR0, + pINTData->byISR1); + } + if (pINTData->byISR1 != 0) + if (pINTData->byISR1 & ISR_GPIO3) + bScheduleCommand((void *) pDevice, + WLAN_CMD_RADIO, + NULL); + pDevice->intBuf.uDataLen = 0; + pDevice->intBuf.bInUse = false; + + pStats->tx_packets = pDevice->scStatistic.ullTsrOK; + pStats->tx_bytes = pDevice->scStatistic.ullTxDirectedBytes + + pDevice->scStatistic.ullTxMulticastBytes + + pDevice->scStatistic.ullTxBroadcastBytes; + pStats->tx_errors = pDevice->scStatistic.dwTsrErr; + pStats->tx_dropped = pDevice->scStatistic.dwTsrErr; +} diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h new file mode 100644 index 00000000..8e6e217b --- /dev/null +++ b/drivers/staging/vt6656/int.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: int.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Apr. 2, 2004 + * + */ + +#ifndef __INT_H__ +#define __INT_H__ + +#include "device.h" + +typedef struct tagSINTData { + u8 byTSR0; + u8 byPkt0; + u16 wTime0; + u8 byTSR1; + u8 byPkt1; + u16 wTime1; + u8 byTSR2; + u8 byPkt2; + u16 wTime2; + u8 byTSR3; + u8 byPkt3; + u16 wTime3; + u64 qwTSF; + u8 byISR0; + u8 byISR1; + u8 byRTSSuccess; + u8 byRTSFail; + u8 byACKFail; + u8 byFCSErr; + u8 abySW[2]; +} __attribute__ ((__packed__)) +SINTData, *PSINTData; + +void INTvWorkItem(struct vnt_private *); +void INTnsProcessData(struct vnt_private *); + +#endif /* __INT_H__ */ diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h new file mode 100644 index 00000000..f3406da7 --- /dev/null +++ b/drivers/staging/vt6656/iocmd.h @@ -0,0 +1,425 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: iocmd.h + * + * Purpose: Handles the viawget ioctl private interface functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + */ + +#ifndef __IOCMD_H__ +#define __IOCMD_H__ + +// ioctl Command code +#define MAGIC_CODE 0x3142 +#define IOCTL_CMD_TEST (SIOCDEVPRIVATE + 0) +#define IOCTL_CMD_SET (SIOCDEVPRIVATE + 1) +#define IOCTL_CMD_HOSTAPD (SIOCDEVPRIVATE + 2) +#define IOCTL_CMD_WPA (SIOCDEVPRIVATE + 3) + +typedef enum tagWMAC_CMD { + + WLAN_CMD_BSS_SCAN, + WLAN_CMD_BSS_JOIN, + WLAN_CMD_DISASSOC, + WLAN_CMD_SET_WEP, + WLAN_CMD_GET_LINK, + WLAN_CMD_GET_LISTLEN, + WLAN_CMD_GET_LIST, + WLAN_CMD_GET_MIB, + WLAN_CMD_GET_STAT, + WLAN_CMD_STOP_MAC, + WLAN_CMD_START_MAC, + WLAN_CMD_AP_START, + WLAN_CMD_SET_HOSTAPD, + WLAN_CMD_SET_HOSTAPD_STA, + WLAN_CMD_SET_802_1X, + WLAN_CMD_SET_HOST_WEP, + WLAN_CMD_SET_WPA, + WLAN_CMD_GET_NODE_CNT, + WLAN_CMD_ZONETYPE_SET, + WLAN_CMD_GET_NODE_LIST + +} WMAC_CMD, *PWMAC_CMD; + +typedef enum tagWZONETYPE { + ZoneType_USA = 0, + ZoneType_Japan = 1, + ZoneType_Europe = 2 +} WZONETYPE; + +#define ADHOC 0 +#define INFRA 1 +#define BOTH 2 +#define AP 3 + +#define ADHOC_STARTED 1 +#define ADHOC_JOINTED 2 + +#define PHY80211a 0 +#define PHY80211b 1 +#define PHY80211g 2 + +#define SSID_ID 0 +#define SSID_MAXLEN 32 +#define BSSID_LEN 6 +#define WEP_NKEYS 4 +#define WEP_KEYMAXLEN 29 +#define WEP_40BIT_LEN 5 +#define WEP_104BIT_LEN 13 +#define WEP_232BIT_LEN 16 + +// Ioctl interface structure +// Command structure +// +typedef struct tagSCmdRequest { + u8 name[16]; + void *data; + u16 wResult; + u16 wCmdCode; +} __packed SCmdRequest, *PSCmdRequest; + +// +// Scan +// + +typedef struct tagSCmdScan { + + u8 ssid[SSID_MAXLEN + 2]; + +} __packed SCmdScan, *PSCmdScan; + +// +// BSS Join +// + +typedef struct tagSCmdBSSJoin { + + u16 wBSSType; + u16 wBBPType; + u8 ssid[SSID_MAXLEN + 2]; + u32 uChannel; + bool bPSEnable; + bool bShareKeyAuth; + +} __packed SCmdBSSJoin, *PSCmdBSSJoin; + +// +// Zonetype Setting +// + +typedef struct tagSCmdZoneTypeSet { + + bool bWrite; + WZONETYPE ZoneType; + +} __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet; + +typedef struct tagSWPAResult { + char ifname[100]; + u8 proto; + u8 key_mgmt; + u8 eap_type; + bool authenticated; +} __packed SWPAResult, *PSWPAResult; + +typedef struct tagSCmdStartAP { + + u16 wBSSType; + u16 wBBPType; + u8 ssid[SSID_MAXLEN + 2]; + u32 uChannel; + u32 uBeaconInt; + bool bShareKeyAuth; + u8 byBasicRate; + +} __packed SCmdStartAP, *PSCmdStartAP; + +typedef struct tagSCmdSetWEP { + + bool bEnableWep; + u8 byKeyIndex; + u8 abyWepKey[WEP_NKEYS][WEP_KEYMAXLEN]; + bool bWepKeyAvailable[WEP_NKEYS]; + u32 auWepKeyLength[WEP_NKEYS]; + +} __packed SCmdSetWEP, *PSCmdSetWEP; + +typedef struct tagSBSSIDItem { + + u32 uChannel; + u8 abyBSSID[BSSID_LEN]; + u8 abySSID[SSID_MAXLEN + 1]; + u16 wBeaconInterval; + u16 wCapInfo; + u8 byNetType; + bool bWEPOn; + u32 uRSSI; + +} __packed SBSSIDItem; + +typedef struct tagSBSSIDList { + + u32 uItem; + SBSSIDItem sBSSIDList[0]; +} __packed SBSSIDList, *PSBSSIDList; + +typedef struct tagSNodeItem { + // STA info + u16 wAID; + u8 abyMACAddr[6]; + u16 wTxDataRate; + u16 wInActiveCount; + u16 wEnQueueCnt; + u16 wFlags; + bool bPWBitOn; + u8 byKeyIndex; + u16 wWepKeyLength; + u8 abyWepKey[WEP_KEYMAXLEN]; + // Auto rate fallback vars + bool bIsInFallback; + u32 uTxFailures; + u32 uTxAttempts; + u16 wFailureRatio; + +} __packed SNodeItem; + +typedef struct tagSNodeList { + + u32 uItem; + SNodeItem sNodeList[0]; + +} __packed SNodeList, *PSNodeList; + +typedef struct tagSCmdLinkStatus { + + bool bLink; + u16 wBSSType; + u8 byState; + u8 abyBSSID[BSSID_LEN]; + u8 abySSID[SSID_MAXLEN + 2]; + u32 uChannel; + u32 uLinkRate; + +} __packed SCmdLinkStatus, *PSCmdLinkStatus; + +// +// 802.11 counter +// +typedef struct tagSDot11MIBCount { + u32 TransmittedFragmentCount; + u32 MulticastTransmittedFrameCount; + u32 FailedCount; + u32 RetryCount; + u32 MultipleRetryCount; + u32 RTSSuccessCount; + u32 RTSFailureCount; + u32 ACKFailureCount; + u32 FrameDuplicateCount; + u32 ReceivedFragmentCount; + u32 MulticastReceivedFrameCount; + u32 FCSErrorCount; +} __packed SDot11MIBCount, *PSDot11MIBCount; + +// +// statistic counter +// +typedef struct tagSStatMIBCount { + // + // ISR status count + // + u32 dwIsrTx0OK; + u32 dwIsrTx1OK; + u32 dwIsrBeaconTxOK; + u32 dwIsrRxOK; + u32 dwIsrTBTTInt; + u32 dwIsrSTIMERInt; + u32 dwIsrUnrecoverableError; + u32 dwIsrSoftInterrupt; + u32 dwIsrRxNoBuf; + ///////////////////////////////////// + + u32 dwIsrUnknown; /* unknown interrupt count */ + + // RSR status count + // + u32 dwRsrFrmAlgnErr; + u32 dwRsrErr; + u32 dwRsrCRCErr; + u32 dwRsrCRCOk; + u32 dwRsrBSSIDOk; + u32 dwRsrADDROk; + u32 dwRsrICVOk; + u32 dwNewRsrShortPreamble; + u32 dwRsrLong; + u32 dwRsrRunt; + + u32 dwRsrRxControl; + u32 dwRsrRxData; + u32 dwRsrRxManage; + + u32 dwRsrRxPacket; + u32 dwRsrRxOctet; + u32 dwRsrBroadcast; + u32 dwRsrMulticast; + u32 dwRsrDirected; + // 64-bit OID + u32 ullRsrOK; + + // for some optional OIDs (64 bits) and DMI support + u32 ullRxBroadcastBytes; + u32 ullRxMulticastBytes; + u32 ullRxDirectedBytes; + u32 ullRxBroadcastFrames; + u32 ullRxMulticastFrames; + u32 ullRxDirectedFrames; + + u32 dwRsrRxFragment; + u32 dwRsrRxFrmLen64; + u32 dwRsrRxFrmLen65_127; + u32 dwRsrRxFrmLen128_255; + u32 dwRsrRxFrmLen256_511; + u32 dwRsrRxFrmLen512_1023; + u32 dwRsrRxFrmLen1024_1518; + + // TSR0,1 status count + // + u32 dwTsrTotalRetry[2]; /* total collision retry count */ + u32 dwTsrOnceRetry[2]; /* this packet had one collision */ + u32 dwTsrMoreThanOnceRetry[2]; /* this packet had many collisions */ + u32 dwTsrRetry[2]; /* this packet has ever occur collision, + * that is (dwTsrOnceCollision0 plus + * dwTsrMoreThanOnceCollision0) */ + u32 dwTsrACKData[2]; + u32 dwTsrErr[2]; + u32 dwAllTsrOK[2]; + u32 dwTsrRetryTimeout[2]; + u32 dwTsrTransmitTimeout[2]; + + u32 dwTsrTxPacket[2]; + u32 dwTsrTxOctet[2]; + u32 dwTsrBroadcast[2]; + u32 dwTsrMulticast[2]; + u32 dwTsrDirected[2]; + + // RD/TD count + u32 dwCntRxFrmLength; + u32 dwCntTxBufLength; + + u8 abyCntRxPattern[16]; + u8 abyCntTxPattern[16]; + + /* Software check.... */ + u32 dwCntRxDataErr; /* rx buffer data CRC err count */ + u32 dwCntDecryptErr; /* rx buffer data CRC err count */ + u32 dwCntRxICVErr; /* rx buffer data CRC err count */ + u32 idxRxErrorDesc; /* index for rx data error RD */ + + /* 64-bit OID */ + u32 ullTsrOK[2]; + + // for some optional OIDs (64 bits) and DMI support + u32 ullTxBroadcastFrames[2]; + u32 ullTxMulticastFrames[2]; + u32 ullTxDirectedFrames[2]; + u32 ullTxBroadcastBytes[2]; + u32 ullTxMulticastBytes[2]; + u32 ullTxDirectedBytes[2]; +} __packed SStatMIBCount, *PSStatMIBCount; + +typedef struct tagSCmdValue { + + u32 dwValue; + +} __packed SCmdValue, *PSCmdValue; + +// +// hostapd & viawget ioctl related +// + +// VIAGWET_IOCTL_HOSTAPD ioctl() cmd: +enum { + VIAWGET_HOSTAPD_FLUSH = 1, + VIAWGET_HOSTAPD_ADD_STA = 2, + VIAWGET_HOSTAPD_REMOVE_STA = 3, + VIAWGET_HOSTAPD_GET_INFO_STA = 4, + VIAWGET_HOSTAPD_SET_ENCRYPTION = 5, + VIAWGET_HOSTAPD_GET_ENCRYPTION = 6, + VIAWGET_HOSTAPD_SET_FLAGS_STA = 7, + VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR = 8, + VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT = 9, + VIAWGET_HOSTAPD_MLME = 10, + VIAWGET_HOSTAPD_SCAN_REQ = 11, + VIAWGET_HOSTAPD_STA_CLEAR_STATS = 12, +}; + +#define VIAWGET_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ +((int) (&((struct viawget_hostapd_param *) 0)->u.generic_elem.data)) + +// Maximum length for algorithm names (-1 for nul termination) used in ioctl() + +struct viawget_hostapd_param { + u32 cmd; + u8 sta_addr[6]; + union { + struct { + u16 aid; + u16 capability; + u8 tx_supp_rates; + } add_sta; + struct { + u32 inactive_sec; + } get_info_sta; + struct { + u8 alg; + u32 flags; + u32 err; + u8 idx; + u8 seq[8]; + u16 key_len; + u8 key[0]; + } crypt; + struct { + u32 flags_and; + u32 flags_or; + } set_flags_sta; + struct { + u16 rid; + u16 len; + u8 data[0]; + } rid; + struct { + u8 len; + u8 data[0]; + } generic_elem; + struct { + u16 cmd; + u16 reason_code; + } mlme; + struct { + u8 ssid_len; + u8 ssid[32]; + } scan_req; + } u; +} __packed; + +#endif /* __IOCMD_H__ */ diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h new file mode 100644 index 00000000..97af32e1 --- /dev/null +++ b/drivers/staging/vt6656/iowpa.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: iowpa.h + * + * Purpose: Handles wpa supplicant ioctl interface + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + */ + +#ifndef __IOWPA_H__ +#define __IOWPA_H__ + +#define WPA_IE_LEN 64 + +//WPA related +/* +typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; +typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, + CIPHER_WEP104 } wpa_cipher; +typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, + KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt; +*/ + +enum { + VIAWGET_SET_WPA = 1, + VIAWGET_SET_KEY = 2, + VIAWGET_SET_SCAN = 3, + VIAWGET_GET_SCAN = 4, + VIAWGET_GET_SSID = 5, + VIAWGET_GET_BSSID = 6, + VIAWGET_SET_DROP_UNENCRYPT = 7, + VIAWGET_SET_DEAUTHENTICATE = 8, + VIAWGET_SET_ASSOCIATE = 9, + VIAWGET_SET_DISASSOCIATE = 10 +}; + +enum { + VIAWGET_ASSOC_MSG = 1, + VIAWGET_DISASSOC_MSG = 2, + VIAWGET_PTK_MIC_MSG = 3, + VIAWGET_GTK_MIC_MSG = 4, + VIAWGET_CCKM_ROAM_MSG = 5, + VIAWGET_DEVICECLOSE_MSG = 6 +}; + +typedef struct viawget_wpa_header { + u8 type; + u16 req_ie_len; + u16 resp_ie_len; +} __packed viawget_wpa_header; + +struct viawget_wpa_param { + u32 cmd; + u8 addr[6]; + union { + struct { + u8 len; + u8 data[0]; + } generic_elem; + struct { + u8 bssid[6]; + u8 ssid[32]; + u8 ssid_len; + u8 *wpa_ie; + u16 wpa_ie_len; + int pairwise_suite; + int group_suite; + int key_mgmt_suite; + int auth_alg; + int mode; + u8 roam_dbm; + } wpa_associate; + struct { + int alg_name; + u16 key_index; + u16 set_tx; + u8 *seq; + u16 seq_len; + u8 *key; + u16 key_len; + } wpa_key; + struct { + u8 ssid_len; + u8 ssid[32]; + } scan_req; + struct { + u16 scan_count; + u8 *buf; + } scan_results; + } u; +} __packed; + +struct viawget_scan_result { + u8 bssid[6]; + u8 ssid[32]; + u16 ssid_len; + u8 wpa_ie[WPA_IE_LEN]; + u16 wpa_ie_len; + u8 rsn_ie[WPA_IE_LEN]; + u16 rsn_ie_len; + int freq; // MHz + int caps; // e.g. privacy + int qual; // signal quality + int noise; + int level; + int maxrate; +} __packed; + +#endif /* __IOWPA_H__ */ diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c new file mode 100644 index 00000000..8872e0f8 --- /dev/null +++ b/drivers/staging/vt6656/iwctl.c @@ -0,0 +1,1837 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: iwctl.c + * + * Purpose: wireless ext & ioctl functions + * + * Author: Lyndon Chen + * + * Date: July 5, 2006 + * + * Functions: + * + * Revision History: + * + */ + +#include "device.h" +#include "iwctl.h" +#include "mac.h" +#include "card.h" +#include "hostap.h" +#include "power.h" +#include "rf.h" +#include "iowpa.h" +#include "wpactl.h" +#include "control.h" +#include "rndis.h" + +static const long frequency_list[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484, + 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980, + 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240, + 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, + 5700, 5745, 5765, 5785, 5805, 5825 +}; + +static int msglevel = MSG_LEVEL_INFO; + +struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) +{ + struct vnt_private *pDevice = netdev_priv(dev); + long ldBm; + + pDevice->wstats.status = pDevice->eOPMode; + if (pDevice->scStatistic.LinkQuality > 100) + pDevice->scStatistic.LinkQuality = 100; + pDevice->wstats.qual.qual =(u8)pDevice->scStatistic.LinkQuality; + RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm); + pDevice->wstats.qual.level = ldBm; + pDevice->wstats.qual.noise = 0; + pDevice->wstats.qual.updated = 1; + pDevice->wstats.discard.nwid = 0; + pDevice->wstats.discard.code = 0; + pDevice->wstats.discard.fragment = 0; + pDevice->wstats.discard.retries = pDevice->scStatistic.dwTsrErr; + pDevice->wstats.discard.misc = 0; + pDevice->wstats.miss.beacon = 0; + return &pDevice->wstats; +} + +/* + * Wireless Handler: get protocol name + */ +int iwctl_giwname(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + strcpy(wrqu->name, "802.11-a/b/g"); + return 0; +} + +/* + * Wireless Handler: set scan + */ +int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_point *wrq = &wrqu->data; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_scan_req *req = (struct iw_scan_req *)extra; + u8 abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + PWLAN_IE_SSID pItemSSID = NULL; + + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) + return -EINVAL; + + PRINT_K(" SIOCSIWSCAN\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if (pMgmt->eScanState == WMAC_IS_SCANNING) { + // In scanning.. + PRINT_K("SIOCSIWSCAN(overlap??)-->In scanning...\n"); + return -EAGAIN; + } + + if (pDevice->byReAssocCount > 0) { // reject scan when re-associating! + // send scan event to wpa_Supplicant + union iwreq_data wrqu; + PRINT_K("wireless_send_event--->SIOCGIWSCAN(scan done)\n"); + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL); + return 0; + } + + spin_lock_irq(&pDevice->lock); + + BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass); + + // mike add: active scan OR passive scan OR desire_ssid scan + if (wrq->length == sizeof(struct iw_scan_req)) { + if (wrq->flags & IW_SCAN_THIS_ESSID) { // desire_ssid scan + memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pItemSSID = (PWLAN_IE_SSID)abyScanSSID; + pItemSSID->byElementID = WLAN_EID_SSID; + memcpy(pItemSSID->abySSID, req->essid, (int)req->essid_len); + if (pItemSSID->abySSID[req->essid_len] == '\0') { + if (req->essid_len > 0) + pItemSSID->len = req->essid_len; + } else { + pItemSSID->len = req->essid_len; + } + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + PRINT_K("SIOCSIWSCAN:[desired_ssid=%s,len=%d]\n", ((PWLAN_IE_SSID)abyScanSSID)->abySSID, + ((PWLAN_IE_SSID)abyScanSSID)->len); + bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID); + spin_unlock_irq(&pDevice->lock); + + return 0; + } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { // passive scan + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + } + } else { // active scan + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + } + + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL); + spin_unlock_irq(&pDevice->lock); + + return 0; +} + +/* + * Wireless Handler : get scan results + */ +int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_point *wrq = &wrqu->data; + int ii; + int jj; + int kk; + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PKnownBSS pBSS; + PWLAN_IE_SSID pItemSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_SUPP_RATES pExtSuppRates; + char *current_ev = extra; + char *end_buf = extra + IW_SCAN_MAX_DATA; + char *current_val = NULL; + struct iw_event iwe; + long ldBm; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSCAN\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if (pMgmt->eScanState == WMAC_IS_SCANNING) { + // In scanning.. + return -EAGAIN; + } + pBSS = &(pMgmt->sBSSList[0]); + for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) { + if (current_ev >= end_buf) + break; + pBSS = &(pMgmt->sBSSList[jj]); + if (pBSS->bActive) { + // ADD mac address + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, pBSS->abyBSSID, WLAN_BSSID_LEN); + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + // ADD ssid + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; + iwe.u.data.length = pItemSSID->len; + iwe.u.data.flags = 1; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pItemSSID->abySSID); + // ADD mode + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) + iwe.u.mode = IW_MODE_INFRA; + else + iwe.u.mode = IW_MODE_ADHOC; + iwe.len = IW_EV_UINT_LEN; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + // ADD frequency + pSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abySuppRates; + pExtSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abyExtSuppRates; + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = pBSS->uChannel; + iwe.u.freq.e = 0; + iwe.u.freq.i = 0; + current_ev = iwe_stream_add_event(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + { + int f = (int)pBSS->uChannel - 1; + if (f < 0) + f = 0; + iwe.u.freq.m = frequency_list[f] * 100000; + iwe.u.freq.e = 1; + } + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + // ADD quality + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + RFvRSSITodBm(pDevice, (u8)(pBSS->uRSSI), &ldBm); + iwe.u.qual.level = ldBm; + iwe.u.qual.noise = 0; + + if (-ldBm < 50) + iwe.u.qual.qual = 100; + else if (-ldBm > 90) + iwe.u.qual.qual = 0; + else + iwe.u.qual.qual = (40 - (-ldBm - 50)) * 100 / 40; + iwe.u.qual.updated = 7; + + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + // ADD encryption + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + iwe.u.data.length = 0; + if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pItemSSID->abySSID); + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + current_val = current_ev + IW_EV_LCP_LEN; + + for (kk = 0; kk < 12; kk++) { + if (pSuppRates->abyRates[kk] == 0) + break; + // Bit rate given in 500 kb/s units (+ 0x80) + iwe.u.bitrate.value = ((pSuppRates->abyRates[kk] & 0x7f) * 500000); + current_val = iwe_stream_add_value(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + } + for (kk = 0; kk < 8; kk++) { + if (pExtSuppRates->abyRates[kk] == 0) + break; + // Bit rate given in 500 kb/s units (+ 0x80) + iwe.u.bitrate.value = ((pExtSuppRates->abyRates[kk] & 0x7f) * 500000); + current_val = iwe_stream_add_value(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + } + + if ((current_val - current_ev) > IW_EV_LCP_LEN) + current_ev = current_val; + + if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pBSS->wWPALen; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pBSS->byWPAIE); + } + + if ((pBSS->wRSNLen > 0) && (pBSS->wRSNLen <= MAX_WPA_IE_LEN)) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pBSS->wRSNLen; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pBSS->byRSNIE); + } + } + } // for + wrq->length = current_ev - extra; + return 0; +} + +/* + * Wireless Handler: set frequence or channel + */ +int iwctl_siwfreq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_freq *wrq = &wrqu->freq; + int rc = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFREQ\n"); + + // If setting by frequency, convert to a channel + if ((wrq->e == 1) && (wrq->m >= (int)2.412e8) && + (wrq->m <= (int)2.487e8)) { + int f = wrq->m / 100000; + int c = 0; + while ((c < 14) && (f != frequency_list[c])) + c++; + wrq->e = 0; + wrq->m = c + 1; + } + // Setting by channel number + if ((wrq->m > 14) || (wrq->e > 0)) { + rc = -EOPNOTSUPP; + } else { + int channel = wrq->m; + if ((channel < 1) || (channel > 14)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: New channel value of %d is invalid!\n", dev->name, wrq->m); + rc = -EINVAL; + } else { + // Yes ! We can set it !!! + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set to channel = %d\n", channel); + pDevice->uChannel = channel; + } + } + return rc; +} + +/* + * Wireless Handler: get frequence or channel + */ +int iwctl_giwfreq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_freq *wrq = &wrqu->freq; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFREQ\n"); + + if (pMgmt == NULL) + return -EFAULT; + +#ifdef WEXT_USECHANNELS + wrq->m = (int)pMgmt->uCurrChannel; + wrq->e = 0; +#else + { + int f = (int)pMgmt->uCurrChannel - 1; + if (f < 0) + f = 0; + wrq->m = frequency_list[f] * 100000; + wrq->e = 1; + } +#endif + return 0; +} + +/* + * Wireless Handler: set operation mode + */ +int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + __u32 *wmode = &wrqu->mode; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int rc = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMODE\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP && pDevice->bEnableHostapd) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Can't set operation mode, hostapd is running\n"); + return rc; + } + + switch (*wmode) { + case IW_MODE_ADHOC: + if (pMgmt->eConfigMode != WMAC_CONFIG_IBSS_STA) { + pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; + if (pDevice->flags & DEVICE_FLAGS_OPENED) + pDevice->bCommit = true; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc \n"); + break; + case IW_MODE_AUTO: + case IW_MODE_INFRA: + if (pMgmt->eConfigMode != WMAC_CONFIG_ESS_STA) { + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + if (pDevice->flags & DEVICE_FLAGS_OPENED) + pDevice->bCommit = true; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure \n"); + break; + case IW_MODE_MASTER: + + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + rc = -EOPNOTSUPP; + break; + + if (pMgmt->eConfigMode != WMAC_CONFIG_AP) { + pMgmt->eConfigMode = WMAC_CONFIG_AP; + if (pDevice->flags & DEVICE_FLAGS_OPENED) + pDevice->bCommit = true; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point \n"); + break; + + case IW_MODE_REPEAT: + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + rc = -EOPNOTSUPP; + break; + default: + rc = -EINVAL; + } + + if (pDevice->bCommit) { + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + netif_stop_queue(pDevice->dev); + spin_lock_irq(&pDevice->lock); + bScheduleCommand((void *) pDevice, + WLAN_CMD_RUN_AP, NULL); + spin_unlock_irq(&pDevice->lock); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Commit the settings\n"); + + spin_lock_irq(&pDevice->lock); + + if (pDevice->bLinkPass && + memcmp(pMgmt->abyCurrSSID, + pMgmt->abyDesireSSID, + WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN)) { + bScheduleCommand((void *) pDevice, + WLAN_CMD_DISASSOCIATE, NULL); + } else { + pDevice->bLinkPass = false; + pMgmt->eCurrState = WMAC_STATE_IDLE; + memset(pMgmt->abyCurrBSSID, 0, 6); + } + + ControlvMaskByte(pDevice, + MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, + LEDSTS_STS, LEDSTS_SLOW); + + netif_stop_queue(pDevice->dev); + + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + + if (!pDevice->bWPASuppWextEnabled) + bScheduleCommand((void *) pDevice, + WLAN_CMD_BSSID_SCAN, + pMgmt->abyDesireSSID); + + bScheduleCommand((void *) pDevice, + WLAN_CMD_SSID, + NULL); + + spin_unlock_irq(&pDevice->lock); + } + pDevice->bCommit = false; + } + + return rc; +} + +/* + * Wireless Handler: get operation mode + */ +int iwctl_giwmode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + __u32 *wmode = &wrqu->mode; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWMODE\n"); + + if (pMgmt == NULL) + return -EFAULT; + + // If not managed, assume it's ad-hoc + switch (pMgmt->eConfigMode) { + case WMAC_CONFIG_ESS_STA: + *wmode = IW_MODE_INFRA; + break; + case WMAC_CONFIG_IBSS_STA: + *wmode = IW_MODE_ADHOC; + break; + case WMAC_CONFIG_AUTO: + *wmode = IW_MODE_INFRA; + break; + case WMAC_CONFIG_AP: + *wmode = IW_MODE_MASTER; + break; + default: + *wmode = IW_MODE_ADHOC; + } + + return 0; +} + +/* + * Wireless Handler: get capability range + */ +int iwctl_giwrange(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_point *wrq = &wrqu->data; + struct iw_range *range = (struct iw_range *)extra; + int i; + int k; + u8 abySupportedRates[13] = { + 0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, + 0x60, 0x6C, 0x90 + }; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRANGE\n"); + if (wrq->pointer) { + wrq->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + range->min_nwid = 0x0000; + range->max_nwid = 0x0000; + range->num_channels = 14; + // Should be based on cap_rid.country to give only + // what the current card support + k = 0; + for (i = 0; i < 14; i++) { + range->freq[k].i = i + 1; // List index + range->freq[k].m = frequency_list[i] * 100000; + range->freq[k++].e = 1; // Values in table in MHz -> * 10^5 * 10 + } + range->num_frequency = k; + // Hum... Should put the right values there + range->max_qual.qual = 100; + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->sensitivity = 255; + + for (i = 0; i < 13; i++) { + range->bitrate[i] = abySupportedRates[i] * 500000; + if (range->bitrate[i] == 0) + break; + } + range->num_bitrates = i; + + // Set an indication of the max TCP throughput + // in bit/s that we can expect using this interface. + // May be use for QoS stuff... Jean II + if (i > 2) + range->throughput = 5 * 1000 * 1000; + else + range->throughput = 1.5 * 1000 * 1000; + + range->min_rts = 0; + range->max_rts = 2312; + range->min_frag = 256; + range->max_frag = 2312; + + // the encoding capabilities + range->num_encoding_sizes = 3; + // 64(40) bits WEP + range->encoding_size[0] = 5; + // 128(104) bits WEP + range->encoding_size[1] = 13; + // 256 bits for WPA-PSK + range->encoding_size[2] = 32; + // 4 keys are allowed + range->max_encoding_tokens = 4; + + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; + + range->min_pmp = 0; + range->max_pmp = 1000000; // 1 secs + range->min_pmt = 0; + range->max_pmt = 1000000; // 1 secs + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; + + // Transmit Power - values are in mW + range->txpower[0] = 100; + range->num_txpower = 1; + range->txpower_capa = IW_TXPOW_MWATT; + range->we_version_source = WIRELESS_EXT; + range->we_version_compiled = WIRELESS_EXT; + range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; + range->retry_flags = IW_RETRY_LIMIT; + range->r_time_flags = IW_RETRY_LIFETIME; + range->min_retry = 1; + range->max_retry = 65535; + range->min_r_time = 1024; + range->max_r_time = 65535 * 1024; + // Experimental measurements - boundary 11/5.5 Mb/s + // Note : with or without the (local->rssi), results + // are somewhat different. - Jean II + range->avg_qual.qual = 6; + range->avg_qual.level = 176; // -80 dBm + range->avg_qual.noise = 0; + } + + return 0; +} + +/* + * Wireless Handler : set ap mac address + */ +int iwctl_siwap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct sockaddr *wrq = &wrqu->ap_addr; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int rc = 0; + u8 ZeroBSSID[WLAN_BSSID_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + PRINT_K(" SIOCSIWAP\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if (wrq->sa_family != ARPHRD_ETHER) { + rc = -EINVAL; + } else { + memcpy(pMgmt->abyDesireBSSID, wrq->sa_data, 6); + // mike: add + if ((is_broadcast_ether_addr(pMgmt->abyDesireBSSID)) || + (memcmp(pMgmt->abyDesireBSSID, ZeroBSSID, 6) == 0)) { + PRINT_K("SIOCSIWAP:invalid desired BSSID return!\n"); + return rc; + } + // mike add: if desired AP is hidden ssid(there are + // two same BSSID in list), then ignore,because you + // don't known which one to be connect with?? + { + unsigned ii; + unsigned uSameBssidNum = 0; + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + if (pMgmt->sBSSList[ii].bActive && + !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, + pMgmt->abyDesireBSSID)) { + uSameBssidNum++; + } + } + if (uSameBssidNum >= 2) { //hit: desired AP is in hidden ssid mode!!! + PRINT_K("SIOCSIWAP:ignore for desired AP in hidden mode\n"); + return rc; + } + } + + if (pDevice->flags & DEVICE_FLAGS_OPENED) + pDevice->bCommit = true; + } + return rc; +} + +/* + * Wireless Handler: get ap mac address + */ +int iwctl_giwap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct sockaddr *wrq = &wrqu->ap_addr; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAP\n"); + + if (pMgmt == NULL) + return -EFAULT; + + memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6); + + if ((pDevice->bLinkPass == false) && (pMgmt->eCurrMode != WMAC_MODE_ESS_AP)) + memset(wrq->sa_data, 0, 6); + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) + memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6); + + wrq->sa_family = ARPHRD_ETHER; + return 0; +} + +/* + * Wireless Handler: get ap list + */ +int iwctl_giwaplist(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_point *wrq = &wrqu->data; + struct sockaddr *sock; + struct iw_quality *qual; + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PKnownBSS pBSS = &pMgmt->sBSSList[0]; + int ii; + int jj; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAPLIST\n"); + /* Only super-user can see AP list */ + + if (pBSS == NULL) + return -ENODEV; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!wrq->pointer) + return -EINVAL; + + sock = kzalloc(sizeof(struct sockaddr) * IW_MAX_AP, GFP_KERNEL); + if (sock == NULL) + return -ENOMEM; + qual = kzalloc(sizeof(struct iw_quality) * IW_MAX_AP, GFP_KERNEL); + if (qual == NULL) { + kfree(sock); + return -ENOMEM; + } + + for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) { + if (!pBSS[ii].bActive) + continue; + if (jj >= IW_MAX_AP) + break; + memcpy(sock[jj].sa_data, pBSS[ii].abyBSSID, 6); + sock[jj].sa_family = ARPHRD_ETHER; + qual[jj].level = pBSS[ii].uRSSI; + qual[jj].qual = qual[jj].noise = 0; + qual[jj].updated = 2; + jj++; + } + + wrq->flags = 1; /* Should be defined */ + wrq->length = jj; + memcpy(extra, sock, sizeof(struct sockaddr) * jj); + memcpy(extra + sizeof(struct sockaddr) * jj, qual, + sizeof(struct iw_quality) * jj); + + kfree(sock); + kfree(qual); + + return 0; +} + +/* + * Wireless Handler: set essid + */ +int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_point *wrq = &wrqu->essid; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PWLAN_IE_SSID pItemSSID; + + if (pMgmt == NULL) + return -EFAULT; + + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) + return -EINVAL; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWESSID :\n"); + + pDevice->fWPA_Authened = false; + // Check if we asked for `any' + if (wrq->flags == 0) { + // Just send an empty SSID list + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memset(pMgmt->abyDesireBSSID, 0xFF,6); + PRINT_K("set essid to 'any' \n"); + // Unknown desired AP, so here need not associate?? + return 0; + } else { + // Set the SSID + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSID->byElementID = WLAN_EID_SSID; + + memcpy(pItemSSID->abySSID, extra, wrq->length); + if (pItemSSID->abySSID[wrq->length] == '\0') { + if (wrq->length>0) + pItemSSID->len = wrq->length; + } else { + pItemSSID->len = wrq->length; + } + PRINT_K("set essid to %s \n", pItemSSID->abySSID); + + // mike: need clear desiredBSSID + if (pItemSSID->len==0) { + memset(pMgmt->abyDesireBSSID, 0xFF, 6); + return 0; + } + + // Wext wil order another command of siwap to link + // with desired AP, so here need not associate?? + if (pDevice->bWPASuppWextEnabled == true) { + /*******search if in hidden ssid mode ****/ + PKnownBSS pCurr = NULL; + u8 abyTmpDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + unsigned ii; + unsigned uSameBssidNum = 0; + + memcpy(abyTmpDesireSSID, pMgmt->abyDesireSSID, sizeof(abyTmpDesireSSID)); + pCurr = BSSpSearchBSSList(pDevice, NULL, + abyTmpDesireSSID, + pDevice->eConfigPHYMode); + + if (pCurr == NULL) { + PRINT_K("SIOCSIWESSID:hidden ssid site survey before associate.......\n"); + vResetCommandTimer((void *)pDevice); + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + bScheduleCommand((void *)pDevice, + WLAN_CMD_BSSID_SCAN, + pMgmt->abyDesireSSID); + bScheduleCommand((void *)pDevice, + WLAN_CMD_SSID, + pMgmt->abyDesireSSID); + } else { // mike: to find out if that desired SSID is a + // hidden-ssid AP, by means of judging if there + // are two same BSSID exist in list ? + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + if (pMgmt->sBSSList[ii].bActive && + !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, + pCurr->abyBSSID)) { + uSameBssidNum++; + } + } + if (uSameBssidNum >= 2) { // hit: desired AP is in hidden ssid mode!!! + PRINT_K("SIOCSIWESSID:hidden ssid directly associate.......\n"); + vResetCommandTimer((void *)pDevice); + pMgmt->eScanType = WMAC_SCAN_PASSIVE; // this scan type, you'll submit scan result! + bScheduleCommand((void *)pDevice, + WLAN_CMD_BSSID_SCAN, + pMgmt->abyDesireSSID); + bScheduleCommand((void *)pDevice, + WLAN_CMD_SSID, + pMgmt->abyDesireSSID); + } + } + return 0; + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s \n", pItemSSID->abySSID); + } + + if (pDevice->flags & DEVICE_FLAGS_OPENED) + pDevice->bCommit = true; + + return 0; +} + +/* + * Wireless Handler: get essid + */ +int iwctl_giwessid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_point *wrq = &wrqu->essid; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PWLAN_IE_SSID pItemSSID; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWESSID\n"); + + if (pMgmt == NULL) + return -EFAULT; + + // Note: if wrq->u.data.flags != 0, we should get the relevant + // SSID from the SSID list... + + // Get the current SSID + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + memcpy(extra, pItemSSID->abySSID, pItemSSID->len); + extra[pItemSSID->len] = '\0'; + + wrq->length = pItemSSID->len; + wrq->flags = 1; // active + + return 0; +} + +/* + * Wireless Handler: set data rate + */ +int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->bitrate; + int rc = 0; + u8 brate = 0; + int i; + u8 abySupportedRates[13] = { + 0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, + 0x60, 0x6C, 0x90 + }; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE \n"); + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) { + rc = -EINVAL; + return rc; + } + + // First: get a valid bit rate value + + // Which type of value + if ((wrq->value < 13) && (wrq->value >= 0)) { + // Setting by rate index + // Find value in the magic rate table + brate = wrq->value; + } else { + // Setting by frequency value + u8 normvalue = (u8)(wrq->value/500000); + + // Check if rate is valid + for (i = 0; i < 13; i++) { + if (normvalue == abySupportedRates[i]) { + brate = i; + break; + } + } + } + // -1 designed the max rate (mostly auto mode) + if (wrq->value == -1) { + // Get the highest available rate + for (i = 0; i < 13; i++) { + if (abySupportedRates[i] == 0) + break; + } + if (i != 0) + brate = i - 1; + + } + // Check that it is valid + // brate is index of abySupportedRates[] + if (brate > 13 ) { + rc = -EINVAL; + return rc; + } + + // Now, check if we want a fixed or auto value + if (wrq->fixed != 0) { + // Fixed mode + // One rate, fixed + pDevice->bFixRate = true; + if ((pDevice->byBBType == BB_TYPE_11B) && (brate > 3)) { + pDevice->uConnectionRate = 3; + } else { + pDevice->uConnectionRate = brate; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d \n", pDevice->uConnectionRate); + } + } else { + pDevice->bFixRate = false; + pDevice->uConnectionRate = 13; + } + + return rc; +} + +/* + * Wireless Handler: get data rate + */ +int iwctl_giwrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->bitrate; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRATE\n"); + + if (pMgmt == NULL) + return -EFAULT; + + { + u8 abySupportedRates[13] = { + 0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, + 0x48, 0x60, 0x6C, 0x90 + }; + int brate = 0; + + if (pDevice->uConnectionRate < 13) { + brate = abySupportedRates[pDevice->uConnectionRate]; + } else { + if (pDevice->byBBType == BB_TYPE_11B) + brate = 0x16; + if (pDevice->byBBType == BB_TYPE_11G) + brate = 0x6C; + if (pDevice->byBBType == BB_TYPE_11A) + brate = 0x6C; + } + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (pDevice->byBBType == BB_TYPE_11B) + brate = 0x16; + if (pDevice->byBBType == BB_TYPE_11G) + brate = 0x6C; + if (pDevice->byBBType == BB_TYPE_11A) + brate = 0x6C; + } + if (pDevice->uConnectionRate == 13) + brate = abySupportedRates[pDevice->wCurrentRate]; + wrq->value = brate * 500000; + // If more than one rate, set auto + if (pDevice->bFixRate == true) + wrq->fixed = true; + } + + return 0; +} + +/* + * Wireless Handler: set rts threshold + */ +int iwctl_siwrts(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->rts; + + if ((wrq->value < 0 || wrq->value > 2312) && !wrq->disabled) + return -EINVAL; + + else if (wrq->disabled) + pDevice->wRTSThreshold = 2312; + else + pDevice->wRTSThreshold = wrq->value; + + return 0; +} + +/* + * Wireless Handler: get rts + */ +int iwctl_giwrts(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->rts; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRTS\n"); + wrq->value = pDevice->wRTSThreshold; + wrq->disabled = (wrq->value >= 2312); + wrq->fixed = 1; + return 0; +} + +/* + * Wireless Handler: set fragment threshold + */ +int iwctl_siwfrag(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->frag; + int rc = 0; + int fthr = wrq->value; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFRAG\n"); + + if (wrq->disabled) + fthr = 2312; + if ((fthr < 256) || (fthr > 2312)) { + rc = -EINVAL; + } else { + fthr &= ~0x1; // Get an even value + pDevice->wFragmentationThreshold = (u16)fthr; + } + return rc; +} + +/* + * Wireless Handler: get fragment threshold + */ +int iwctl_giwfrag(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->frag; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFRAG\n"); + wrq->value = pDevice->wFragmentationThreshold; + wrq->disabled = (wrq->value >= 2312); + wrq->fixed = 1; + return 0; +} + +/* + * Wireless Handler: set retry threshold + */ +int iwctl_siwretry(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->retry; + int rc = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRETRY\n"); + + if (wrq->disabled) { + rc = -EINVAL; + return rc; + } + + if (wrq->flags & IW_RETRY_LIMIT) { + if (wrq->flags & IW_RETRY_MAX) { + pDevice->byLongRetryLimit = wrq->value; + } else if (wrq->flags & IW_RETRY_MIN) { + pDevice->byShortRetryLimit = wrq->value; + } else { + // No modifier : set both + pDevice->byShortRetryLimit = wrq->value; + pDevice->byLongRetryLimit = wrq->value; + } + } + if (wrq->flags & IW_RETRY_LIFETIME) + pDevice->wMaxTransmitMSDULifetime = wrq->value; + return rc; +} + +/* + * Wireless Handler: get retry threshold + */ +int iwctl_giwretry(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->retry; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRETRY\n"); + wrq->disabled = 0; // Can't be disabled + + // Note: by default, display the min retry number + if ((wrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + wrq->flags = IW_RETRY_LIFETIME; + wrq->value = (int)pDevice->wMaxTransmitMSDULifetime; // ms + } else if ((wrq->flags & IW_RETRY_MAX)) { + wrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + wrq->value = (int)pDevice->byLongRetryLimit; + } else { + wrq->flags = IW_RETRY_LIMIT; + wrq->value = (int)pDevice->byShortRetryLimit; + if ((int)pDevice->byShortRetryLimit != (int)pDevice->byLongRetryLimit) + wrq->flags |= IW_RETRY_MIN; + } + return 0; +} + +/* + * Wireless Handler: set encode mode + */ +int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_point *wrq = &wrqu->encoding; + u32 dwKeyIndex = (u32)(wrq->flags & IW_ENCODE_INDEX); + int ii; + int uu; + int rc = 0; + int index = (wrq->flags & IW_ENCODE_INDEX); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE\n"); + + if (pMgmt == NULL) + return -EFAULT; + + // Check the size of the key + if (wrq->length > WLAN_WEP232_KEYLEN) { + rc = -EINVAL; + return rc; + } + + if (dwKeyIndex > WLAN_WEP_NKEYS) { + rc = -EINVAL; + return rc; + } + + if (dwKeyIndex > 0) + dwKeyIndex--; + + // Send the key to the card + if (wrq->length > 0) { + if (wrq->length == WLAN_WEP232_KEYLEN) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n"); + } else if (wrq->length == WLAN_WEP104_KEYLEN) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n"); + } else if (wrq->length == WLAN_WEP40_KEYLEN) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex); + } + memset(pDevice->abyKey, 0, WLAN_WEP232_KEYLEN); + memcpy(pDevice->abyKey, extra, wrq->length); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyKey: "); + for (ii = 0; ii < wrq->length; ii++) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pDevice->abyKey[ii]); + + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + spin_lock_irq(&pDevice->lock); + KeybSetDefaultKey(pDevice, + &(pDevice->sKey), + dwKeyIndex | (1 << 31), + wrq->length, NULL, + pDevice->abyKey, + KEY_CTL_WEP); + spin_unlock_irq(&pDevice->lock); + } + pDevice->byKeyIndex = (u8)dwKeyIndex; + pDevice->uKeyLength = wrq->length; + pDevice->bTransmitKey = true; + pDevice->bEncryptionEnable = true; + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + + // Do we want to just set the transmit key index? + if (index < 4) { + pDevice->byKeyIndex = index; + } else if (!(wrq->flags & IW_ENCODE_MODE)) { + rc = -EINVAL; + return rc; + } + } + // Read the flags + if (wrq->flags & IW_ENCODE_DISABLED) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable WEP function\n"); + pMgmt->bShareKeyAlgorithm = false; + pDevice->bEncryptionEnable = false; + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + spin_lock_irq(&pDevice->lock); + for (uu = 0; uu < MAX_KEY_TABLE; uu++) + MACvDisableKeyEntry(pDevice, uu); + spin_unlock_irq(&pDevice->lock); + } + } + if (wrq->flags & IW_ENCODE_RESTRICTED) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & ShareKey System\n"); + pMgmt->bShareKeyAlgorithm = true; + } + if (wrq->flags & IW_ENCODE_OPEN) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & Open System\n"); + pMgmt->bShareKeyAlgorithm = false; + } + + memset(pMgmt->abyDesireBSSID, 0xFF, 6); + + return rc; +} + +int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_point *wrq = &wrqu->encoding; + char abyKey[WLAN_WEP232_KEYLEN]; + + unsigned index = (unsigned)(wrq->flags & IW_ENCODE_INDEX); + PSKeyItem pKey = NULL; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if (index > WLAN_WEP_NKEYS) + return -EINVAL; + if (index < 1) { // get default key + if (pDevice->byKeyIndex < WLAN_WEP_NKEYS) + index = pDevice->byKeyIndex; + else + index = 0; + } else { + index--; + } + + memset(abyKey, 0, WLAN_WEP232_KEYLEN); + // Check encryption mode + wrq->flags = IW_ENCODE_NOKEY; + // Is WEP enabled ??? + if (pDevice->bEncryptionEnable) + wrq->flags |= IW_ENCODE_ENABLED; + else + wrq->flags |= IW_ENCODE_DISABLED; + + if (pMgmt->bShareKeyAlgorithm) + wrq->flags |= IW_ENCODE_RESTRICTED; + else + wrq->flags |= IW_ENCODE_OPEN; + wrq->length = 0; + + if ((index == 0) && (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled || + pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)) { // get wpa pairwise key + if (KeybGetKey(&(pDevice->sKey), pMgmt->abyCurrBSSID, 0xffffffff, &pKey)) { + wrq->length = pKey->uKeyLength; + memcpy(abyKey, pKey->abyKey, pKey->uKeyLength); + memcpy(extra, abyKey, WLAN_WEP232_KEYLEN); + } + } else if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (u8)index, &pKey)) { + wrq->length = pKey->uKeyLength; + memcpy(abyKey, pKey->abyKey, pKey->uKeyLength); + memcpy(extra, abyKey, WLAN_WEP232_KEYLEN); + } + + wrq->flags |= index + 1; + return 0; +} + +/* + * Wireless Handler: set power mode + */ +int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_param *wrq = &wrqu->power; + int rc = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) { + rc = -EINVAL; + return rc; + } + + spin_lock_irq(&pDevice->lock); + + if (wrq->disabled) { + pDevice->ePSMode = WMAC_POWER_CAM; + PSvDisablePowerSaving(pDevice); + spin_unlock_irq(&pDevice->lock); + return rc; + } + if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + pDevice->ePSMode = WMAC_POWER_FAST; + PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval); + + } else if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { + pDevice->ePSMode = WMAC_POWER_FAST; + PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval); + } + + spin_unlock_irq(&pDevice->lock); + + switch (wrq->flags & IW_POWER_MODE) { + case IW_POWER_UNICAST_R: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n"); + rc = -EINVAL; + break; + case IW_POWER_ALL_R: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R \n"); + rc = -EINVAL; + case IW_POWER_ON: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON \n"); + break; + default: + rc = -EINVAL; + } + + return rc; +} + +/* + * Wireless Handler: get power mode + */ +int iwctl_giwpower(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_param *wrq = &wrqu->power; + int mode = pDevice->ePSMode; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPOWER\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if ((wrq->disabled = (mode == WMAC_POWER_CAM))) + return 0; + + if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + wrq->value = (int)((pMgmt->wListenInterval * + pMgmt->wCurrBeaconPeriod) / 100); + wrq->flags = IW_POWER_TIMEOUT; + } else { + wrq->value = (int)((pMgmt->wListenInterval * + pMgmt->wCurrBeaconPeriod) / 100); + wrq->flags = IW_POWER_PERIOD; + } + + wrq->flags |= IW_POWER_ALL_R; + return 0; +} + +/* + * Wireless Handler: get Sensitivity + */ +int iwctl_giwsens(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iw_param *wrq = &wrqu->sens; + long ldBm; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSENS\n"); + if (pDevice->bLinkPass == true) { + RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm); + wrq->value = ldBm; + } else { + wrq->value = 0; + } + wrq->disabled = (wrq->value == 0); + wrq->fixed = 1; + return 0; +} + +int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_param *wrq = &wrqu->param; + int ret = 0; + static int wpa_version = 0; // must be static to save the last value, einsn liu + static int pairwise = 0; + + if (pMgmt == NULL) + return -EFAULT; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH\n"); + switch (wrq->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + wpa_version = wrq->value; + if (wrq->value == IW_AUTH_WPA_VERSION_DISABLED) { + PRINT_K("iwctl_siwauth:set WPADEV to disable at 1??????\n"); + } else if (wrq->value == IW_AUTH_WPA_VERSION_WPA) { + PRINT_K("iwctl_siwauth:set WPADEV to WPA1******\n"); + } else { + PRINT_K("iwctl_siwauth:set WPADEV to WPA2******\n"); + } + break; + case IW_AUTH_CIPHER_PAIRWISE: + pairwise = wrq->value; + PRINT_K("iwctl_siwauth:set pairwise=%d\n", pairwise); + if (pairwise == IW_AUTH_CIPHER_CCMP){ + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + } else if (pairwise == IW_AUTH_CIPHER_TKIP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + } else if (pairwise == IW_AUTH_CIPHER_WEP40 || + pairwise == IW_AUTH_CIPHER_WEP104) { + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + } else if (pairwise == IW_AUTH_CIPHER_NONE) { + // do nothing, einsn liu + } else { + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + } + break; + case IW_AUTH_CIPHER_GROUP: + PRINT_K("iwctl_siwauth:set GROUP=%d\n", wrq->value); + if (wpa_version == IW_AUTH_WPA_VERSION_DISABLED) + break; + if (pairwise == IW_AUTH_CIPHER_NONE) { + if (wrq->value == IW_AUTH_CIPHER_CCMP) + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + else + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + } + break; + case IW_AUTH_KEY_MGMT: + PRINT_K("iwctl_siwauth(wpa_version=%d):set KEY_MGMT=%d\n", wpa_version,wrq->value); + if (wpa_version == IW_AUTH_WPA_VERSION_WPA2){ + if (wrq->value == IW_AUTH_KEY_MGMT_PSK) + pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; + else pMgmt->eAuthenMode = WMAC_AUTH_WPA2; + } else if (wpa_version == IW_AUTH_WPA_VERSION_WPA) { + if (wrq->value == 0){ + pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; + } else if (wrq->value == IW_AUTH_KEY_MGMT_PSK) + pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; + } else { + pMgmt->eAuthenMode = WMAC_AUTH_WPA; + } + break; + case IW_AUTH_TKIP_COUNTERMEASURES: + break; /* FIXME */ + case IW_AUTH_DROP_UNENCRYPTED: + break; + case IW_AUTH_80211_AUTH_ALG: + PRINT_K("iwctl_siwauth:set AUTH_ALG=%d\n", wrq->value); + if (wrq->value == IW_AUTH_ALG_OPEN_SYSTEM) + pMgmt->bShareKeyAlgorithm = false; + else if (wrq->value == IW_AUTH_ALG_SHARED_KEY) + pMgmt->bShareKeyAlgorithm = true; + break; + case IW_AUTH_WPA_ENABLED: + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + break; + case IW_AUTH_ROAMING_CONTROL: + ret = -EOPNOTSUPP; + break; + case IW_AUTH_PRIVACY_INVOKED: + pDevice->bEncryptionEnable = !!wrq->value; + if (pDevice->bEncryptionEnable == false) { + wpa_version = 0; + pairwise = 0; + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + pMgmt->bShareKeyAlgorithm = false; + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + PRINT_K("iwctl_siwauth:set WPADEV to disaable at 2?????\n"); + } + break; + default: + PRINT_K("iwctl_siwauth: not supported %x\n", wrq->flags); + ret = -EOPNOTSUPP; + break; + } + return ret; +} + +int iwctl_giwauth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + return -EOPNOTSUPP; +} + +int iwctl_siwgenie(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_point *wrq = &wrqu->data; + int ret = 0; + + if (pMgmt == NULL) + return -EFAULT; + + if (wrq->length){ + if ((wrq->length < 2) || (extra[1] + 2 != wrq->length)) { + ret = -EINVAL; + goto out; + } + if (wrq->length > MAX_WPA_IE_LEN){ + ret = -ENOMEM; + goto out; + } + memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN); + if (copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)){ + ret = -EFAULT; + goto out; + } + pMgmt->wWPAIELen = wrq->length; + } else { + memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN); + pMgmt->wWPAIELen = 0; + } + +out: // not completely ...not necessary in wpa_supplicant 0.5.8 + return ret; +} + +int iwctl_giwgenie(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_point *wrq = &wrqu->data; + int ret = 0; + int space = wrq->length; + + if (pMgmt == NULL) + return -EFAULT; + + wrq->length = 0; + if (pMgmt->wWPAIELen > 0) { + wrq->length = pMgmt->wWPAIELen; + if (pMgmt->wWPAIELen <= space) { + if (copy_to_user(extra, pMgmt->abyWPAIE, pMgmt->wWPAIELen)) { + ret = -EFAULT; + } + } else { + ret = -E2BIG; + } + } + return ret; +} + +int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_point *wrq = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext*)extra; + struct viawget_wpa_param *param=NULL; +// original member + wpa_alg alg_name; + u8 addr[6]; + int key_idx; + int set_tx = 0; + u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; + u8 key[64]; + size_t seq_len = 0; + size_t key_len = 0; + u8 *buf; + u8 key_array[64]; + int ret = 0; + + PRINT_K("SIOCSIWENCODEEXT......\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) + return -ENODEV; + + buf = kzalloc(sizeof(struct viawget_wpa_param), GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + param = (struct viawget_wpa_param *)buf; + +// recover alg_name + switch (ext->alg) { + case IW_ENCODE_ALG_NONE: + alg_name = WPA_ALG_NONE; + break; + case IW_ENCODE_ALG_WEP: + alg_name = WPA_ALG_WEP; + break; + case IW_ENCODE_ALG_TKIP: + alg_name = WPA_ALG_TKIP; + break; + case IW_ENCODE_ALG_CCMP: + alg_name = WPA_ALG_CCMP; + break; + default: + PRINT_K("Unknown alg = %d\n",ext->alg); + ret= -ENOMEM; + goto error; + } +// recover addr + memcpy(addr, ext->addr.sa_data, ETH_ALEN); +// recover key_idx + key_idx = (wrq->flags&IW_ENCODE_INDEX) - 1; +// recover set_tx + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + set_tx = 1; +// recover seq,seq_len + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + seq_len=IW_ENCODE_SEQ_MAX_SIZE; + memcpy(seq, ext->rx_seq, seq_len); + } +// recover key,key_len + if (ext->key_len) { + key_len = ext->key_len; + memcpy(key, &ext->key[0], key_len); + } + memset(key_array, 0, 64); + if (key_len > 0) { + memcpy(key_array, key, key_len); + if (key_len == 32) { + // notice ! the oder + memcpy(&key_array[16], &key[24], 8); + memcpy(&key_array[24], &key[16], 8); + } + } + +/**************Translate iw_encode_ext to viawget_wpa_param****************/ + memcpy(param->addr, addr, ETH_ALEN); + param->u.wpa_key.alg_name = (int)alg_name; + param->u.wpa_key.set_tx = set_tx; + param->u.wpa_key.key_index = key_idx; + param->u.wpa_key.key_len = key_len; + param->u.wpa_key.key = (u8 *)key_array; + param->u.wpa_key.seq = (u8 *)seq; + param->u.wpa_key.seq_len = seq_len; + +/****set if current action is Network Manager count?? */ +/****this method is so foolish,but there is no other way??? */ + if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { + if (param->u.wpa_key.key_index ==0) { + pDevice->bwextstep0 = true; + } + if ((pDevice->bwextstep0 == true) && (param->u.wpa_key.key_index == 1)) { + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = true; + } + if ((pDevice->bwextstep1 == true) && (param->u.wpa_key.key_index == 2)) { + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = true; + } + if ((pDevice->bwextstep2 == true) && (param->u.wpa_key.key_index == 3)) { + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = true; + } + } + if (pDevice->bwextstep3 == true) { + PRINT_K("SIOCSIWENCODEEXT:Enable WPA WEXT SUPPORT!!!!!\n"); + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = false; + pDevice->bWPASuppWextEnabled = true; + memset(pMgmt->abyDesireBSSID, 0xFF, 6); + KeyvInitTable(pDevice, &pDevice->sKey); + } +/*******/ + spin_lock_irq(&pDevice->lock); + ret = wpa_set_keys(pDevice, param); + spin_unlock_irq(&pDevice->lock); + +error: + kfree(buf); + return ret; +} + +int iwctl_giwencodeext(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + return -EOPNOTSUPP; +} + +int iwctl_siwmlme(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct iw_mlme *mlme = (struct iw_mlme *)extra; + int ret = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMLME\n"); + + if (pMgmt == NULL) + return -EFAULT; + + if (memcmp(pMgmt->abyCurrBSSID, mlme->addr.sa_data, ETH_ALEN)) { + ret = -EINVAL; + return ret; + } + switch (mlme->cmd){ + case IW_MLME_DEAUTH: + case IW_MLME_DISASSOC: + if (pDevice->bLinkPass == true) { + PRINT_K("iwctl_siwmlme--->send DISASSOCIATE\n"); + bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, + NULL); + } + break; + default: + ret = -EOPNOTSUPP; + } + return ret; +} + +static int iwctl_config_commit(struct net_device *dev, + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SIOCSIWCOMMIT\n"); + + return 0; +} + +static const iw_handler iwctl_handler[] = { + IW_HANDLER(SIOCSIWCOMMIT, iwctl_config_commit), + IW_HANDLER(SIOCGIWNAME, iwctl_giwname), + IW_HANDLER(SIOCSIWFREQ, iwctl_siwfreq), + IW_HANDLER(SIOCGIWFREQ, iwctl_giwfreq), + IW_HANDLER(SIOCSIWMODE, iwctl_siwmode), + IW_HANDLER(SIOCGIWMODE, iwctl_giwmode), + IW_HANDLER(SIOCGIWSENS, iwctl_giwsens), + IW_HANDLER(SIOCGIWRANGE, iwctl_giwrange), + IW_HANDLER(SIOCSIWAP, iwctl_siwap), + IW_HANDLER(SIOCGIWAP, iwctl_giwap), + IW_HANDLER(SIOCSIWMLME, iwctl_siwmlme), + IW_HANDLER(SIOCGIWAPLIST, iwctl_giwaplist), + IW_HANDLER(SIOCSIWSCAN, iwctl_siwscan), + IW_HANDLER(SIOCGIWSCAN, iwctl_giwscan), + IW_HANDLER(SIOCSIWESSID, iwctl_siwessid), + IW_HANDLER(SIOCGIWESSID, iwctl_giwessid), + IW_HANDLER(SIOCSIWRATE, iwctl_siwrate), + IW_HANDLER(SIOCGIWRATE, iwctl_giwrate), + IW_HANDLER(SIOCSIWRTS, iwctl_siwrts), + IW_HANDLER(SIOCGIWRTS, iwctl_giwrts), + IW_HANDLER(SIOCSIWFRAG, iwctl_siwfrag), + IW_HANDLER(SIOCGIWFRAG, iwctl_giwfrag), + IW_HANDLER(SIOCSIWRETRY, iwctl_siwretry), + IW_HANDLER(SIOCGIWRETRY, iwctl_giwretry), + IW_HANDLER(SIOCSIWENCODE, iwctl_siwencode), + IW_HANDLER(SIOCGIWENCODE, iwctl_giwencode), + IW_HANDLER(SIOCSIWPOWER, iwctl_siwpower), + IW_HANDLER(SIOCGIWPOWER, iwctl_giwpower), + IW_HANDLER(SIOCSIWGENIE, iwctl_siwgenie), + IW_HANDLER(SIOCGIWGENIE, iwctl_giwgenie), + IW_HANDLER(SIOCSIWMLME, iwctl_siwmlme), + IW_HANDLER(SIOCSIWAUTH, iwctl_siwauth), + IW_HANDLER(SIOCGIWAUTH, iwctl_giwauth), + IW_HANDLER(SIOCSIWENCODEEXT, iwctl_siwencodeext), + IW_HANDLER(SIOCGIWENCODEEXT, iwctl_giwencodeext) +}; + +static const iw_handler iwctl_private_handler[] = { + NULL, // SIOCIWFIRSTPRIV +}; + +const struct iw_handler_def iwctl_handler_def = { + .get_wireless_stats = &iwctl_get_wireless_stats, + .num_standard = ARRAY_SIZE(iwctl_handler), + .num_private = 0, + .num_private_args = 0, + .standard = iwctl_handler, + .private = NULL, + .private_args = NULL, +}; diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h new file mode 100644 index 00000000..dceda0db --- /dev/null +++ b/drivers/staging/vt6656/iwctl.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: iwctl.h + * + * Purpose: + * + * Author: Lyndon Chen + * + * Date: May 21, 2004 + * + */ + +#ifndef __IWCTL_H__ +#define __IWCTL_H__ + +#include "device.h" + +struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev); + +int iwctl_siwap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwrange(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwmode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwfreq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwfreq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwname(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwsens(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwap(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwaplist(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwessid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwrts(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwrts(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwfrag(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwfrag(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwretry(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwretry(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwpower(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwauth(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwgenie(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwgenie(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_giwencodeext(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +int iwctl_siwmlme(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern const struct iw_handler_def iwctl_handler_def; +extern const struct iw_priv_args iwctl_priv_args; + +#endif /* __IWCTL_H__ */ diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c new file mode 100644 index 00000000..205590b0 --- /dev/null +++ b/drivers/staging/vt6656/key.c @@ -0,0 +1,737 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: key.c + * + * Purpose: Implement functions for 802.11i Key management + * + * Author: Jerry Chen + * + * Date: May 29, 2003 + * + * Functions: + * KeyvInitTable - Init Key management table + * KeybGetKey - Get Key from table + * KeybSetKey - Set Key to table + * KeybRemoveKey - Remove Key from table + * KeybGetTransmitKey - Get Transmit Key from table + * + * Revision History: + * + */ + +#include "mac.h" +#include "tmacro.h" +#include "key.h" +#include "rndis.h" +#include "control.h" + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +static void s_vCheckKeyTableValid(struct vnt_private *pDevice, + PSKeyManagement pTable) +{ + int i; + u16 wLength = 0; + u8 pbyData[MAX_KEY_TABLE]; + + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == true) && + (pTable->KeyTable[i].PairwiseKey.bKeyValid == false) && + (pTable->KeyTable[i].GroupKey[0].bKeyValid == false) && + (pTable->KeyTable[i].GroupKey[1].bKeyValid == false) && + (pTable->KeyTable[i].GroupKey[2].bKeyValid == false) && + (pTable->KeyTable[i].GroupKey[3].bKeyValid == false) + ) { + + pTable->KeyTable[i].bInUse = false; + pTable->KeyTable[i].wKeyCtl = 0; + pTable->KeyTable[i].bSoftWEP = false; + pbyData[wLength++] = (u8) i; + //MACvDisableKeyEntry(pDevice, i); + } + } + if ( wLength != 0 ) { + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_CLRKEYENTRY, + 0, + 0, + wLength, + pbyData + ); + } + +} + +/* + * Description: Init Key management table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * Out: + * none + * + * Return Value: none + * + */ +void KeyvInitTable(struct vnt_private *pDevice, PSKeyManagement pTable) +{ + int i, jj; + u8 pbyData[MAX_KEY_TABLE+1]; + + spin_lock_irq(&pDevice->lock); + for (i=0;i<MAX_KEY_TABLE;i++) { + pTable->KeyTable[i].bInUse = false; + pTable->KeyTable[i].PairwiseKey.bKeyValid = false; + pTable->KeyTable[i].PairwiseKey.pvKeyTable = + (void *)&pTable->KeyTable[i]; + for (jj=0; jj < MAX_GROUP_KEY; jj++) { + pTable->KeyTable[i].GroupKey[jj].bKeyValid = false; + pTable->KeyTable[i].GroupKey[jj].pvKeyTable = + (void *) &(pTable->KeyTable[i]); + } + pTable->KeyTable[i].wKeyCtl = 0; + pTable->KeyTable[i].dwGTKeyIndex = 0; + pTable->KeyTable[i].bSoftWEP = false; + pbyData[i] = (u8) i; + } + pbyData[i] = (u8) i; + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_CLRKEYENTRY, + 0, + 0, + 11, + pbyData + ); + + spin_unlock_irq(&pDevice->lock); + + return; +} + +/* + * Description: Get Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * dwKeyIndex - Key Index (0xFFFFFFFF means pairwise key) + * Out: + * pKey - Key return + * + * Return Value: true if found otherwise false + * + */ +int KeybGetKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyIndex, + PSKeyItem *pKey) +{ + int i; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetKey()\n"); + + *pKey = NULL; + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == true) && + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { + if (dwKeyIndex == 0xFFFFFFFF) { + if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) { + *pKey = &(pTable->KeyTable[i].PairwiseKey); + return (true); + } + else { + return (false); + } + } else if (dwKeyIndex < MAX_GROUP_KEY) { + if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid == true) { + *pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]); + return (true); + } + else { + return (false); + } + } + else { + return (false); + } + } + } + return (false); +} + +/* + * Description: Set Key to table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * dwKeyIndex - Key index (reference to NDIS DDK) + * uKeyLength - Key length + * KeyRSC - Key RSC + * pbyKey - Pointer to key + * Out: + * none + * + * Return Value: true if success otherwise false + * + */ +int KeybSetKey(struct vnt_private *pDevice, PSKeyManagement pTable, + u8 *pbyBSSID, u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, + u8 byKeyDecMode) +{ + PSKeyItem pKey; + int i, j, ii; + u32 uKeyIdx; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Enter KeybSetKey: %X\n", dwKeyIndex); + + j = (MAX_KEY_TABLE-1); + for (i=0;i<(MAX_KEY_TABLE-1);i++) { + if ((pTable->KeyTable[i].bInUse == false) && + (j == (MAX_KEY_TABLE-1))) { + // found empty table + j = i; + } + if ((pTable->KeyTable[i].bInUse == true) && + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { + // found table already exist + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { + // Pairwise key + pKey = &(pTable->KeyTable[i].PairwiseKey); + pTable->KeyTable[i].wKeyCtl &= 0xFFF0; // clear pairwise key control filed + pTable->KeyTable[i].wKeyCtl |= byKeyDecMode; + uKeyIdx = 4; // use HW key entry 4 for pairwise key + } else { + // Group key + if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) + return (false); + pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]); + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[i].dwGTKeyIndex, i); + } + pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); + pTable->KeyTable[i].wKeyCtl |= 0x0040; // use group key for group address + uKeyIdx = (dwKeyIndex & 0x000000FF); + } + pTable->KeyTable[i].wKeyCtl |= 0x8000; // enable on-fly + + pKey->bKeyValid = true; + pKey->uKeyLength = uKeyLength; + pKey->dwKeyIndex = dwKeyIndex; + pKey->byCipherSuite = byKeyDecMode; + memcpy(pKey->abyKey, pbyKey, uKeyLength); + if (byKeyDecMode == KEY_CTL_WEP) { + if (uKeyLength == WLAN_WEP40_KEYLEN) + pKey->abyKey[15] &= 0x7F; + if (uKeyLength == WLAN_WEP104_KEYLEN) + pKey->abyKey[15] |= 0x80; + } + MACvSetKeyEntry(pDevice, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (u32 *)pKey->abyKey); + + if ((dwKeyIndex & USE_KEYRSC) == 0) + pKey->KeyRSC = 0; /* RSC set by NIC */ + else + pKey->KeyRSC = *KeyRSC; + + pKey->dwTSC47_16 = 0; + pKey->wTSC15_0 = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", pKey->uKeyLength); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); + for (ii = 0; ii < pKey->uKeyLength; ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", + pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", + pKey->wTSC15_0); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", + pKey->dwKeyIndex); + + return (true); + } + } + if (j < (MAX_KEY_TABLE-1)) { + memcpy(pTable->KeyTable[j].abyBSSID, pbyBSSID, ETH_ALEN); + pTable->KeyTable[j].bInUse = true; + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { + // Pairwise key + pKey = &(pTable->KeyTable[j].PairwiseKey); + pTable->KeyTable[j].wKeyCtl &= 0xFFF0; // clear pairwise key control filed + pTable->KeyTable[j].wKeyCtl |= byKeyDecMode; + uKeyIdx = 4; // use HW key entry 4 for pairwise key + } else { + // Group key + if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) + return (false); + pKey = &(pTable->KeyTable[j].GroupKey[dwKeyIndex & 0x000000FF]); + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(N)[%X]: %d\n", + pTable->KeyTable[j].dwGTKeyIndex, j); + } + pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4); + pTable->KeyTable[j].wKeyCtl |= 0x0040; // use group key for group address + uKeyIdx = (dwKeyIndex & 0x000000FF); + } + pTable->KeyTable[j].wKeyCtl |= 0x8000; // enable on-fly + + pKey->bKeyValid = true; + pKey->uKeyLength = uKeyLength; + pKey->dwKeyIndex = dwKeyIndex; + pKey->byCipherSuite = byKeyDecMode; + memcpy(pKey->abyKey, pbyKey, uKeyLength); + if (byKeyDecMode == KEY_CTL_WEP) { + if (uKeyLength == WLAN_WEP40_KEYLEN) + pKey->abyKey[15] &= 0x7F; + if (uKeyLength == WLAN_WEP104_KEYLEN) + pKey->abyKey[15] |= 0x80; + } + MACvSetKeyEntry(pDevice, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (u32 *)pKey->abyKey); + + if ((dwKeyIndex & USE_KEYRSC) == 0) + pKey->KeyRSC = 0; /* RSC set by NIC */ + else + pKey->KeyRSC = *KeyRSC; + + pKey->dwTSC47_16 = 0; + pKey->wTSC15_0 = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(N): \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); + for (ii = 0; ii < pKey->uKeyLength; ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", + pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", + pKey->dwKeyIndex); + + return (true); + } + return (false); +} + +/* + * Description: Remove Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * dwKeyIndex - Key Index (reference to NDIS DDK) + * Out: + * none + * + * Return Value: true if success otherwise false + * + */ + +int KeybRemoveKey(struct vnt_private *pDevice, PSKeyManagement pTable, + u8 *pbyBSSID, u32 dwKeyIndex) +{ + int i; + int bReturnValue = false; + + if (is_broadcast_ether_addr(pbyBSSID)) { + // delete all keys + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { + for (i=0;i<MAX_KEY_TABLE;i++) { + pTable->KeyTable[i].PairwiseKey.bKeyValid = false; + } + bReturnValue = true; + } + else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) { + for (i=0;i<MAX_KEY_TABLE;i++) { + pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false; + if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) { + // remove Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = 0; + } + } + bReturnValue = true; + } + else { + bReturnValue = false; + } + + } else { + for (i=0;i<MAX_KEY_TABLE;i++) { + if ( (pTable->KeyTable[i].bInUse == true) && + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { + + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { + pTable->KeyTable[i].PairwiseKey.bKeyValid = false; + bReturnValue = true; + break; + } + else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) { + pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = false; + if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) { + // remove Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = 0; + } + bReturnValue = true; + break; + } + else { + bReturnValue = false; + break; + } + } //pTable->KeyTable[i].bInUse == true + } //for + bReturnValue = true; + } + + s_vCheckKeyTableValid(pDevice,pTable); + return bReturnValue; + +} + +/* + * Description: Remove Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * Out: + * none + * + * Return Value: true if success otherwise false + * + */ +int KeybRemoveAllKey(struct vnt_private *pDevice, PSKeyManagement pTable, + u8 *pbyBSSID) +{ + int i, u; + + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == true) && + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { + pTable->KeyTable[i].PairwiseKey.bKeyValid = false; + for (u = 0; u < MAX_GROUP_KEY; u++) + pTable->KeyTable[i].GroupKey[u].bKeyValid = false; + + pTable->KeyTable[i].dwGTKeyIndex = 0; + s_vCheckKeyTableValid(pDevice, pTable); + return (true); + } + } + return (false); +} + +/* + * Description: Get Transmit Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * Out: + * pKey - Key return + * + * Return Value: true if found otherwise false + * + */ +int KeybGetTransmitKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyType, + PSKeyItem *pKey) +{ + int i, ii; + + *pKey = NULL; + + for (i = 0; i < MAX_KEY_TABLE; i++) { + if ((pTable->KeyTable[i].bInUse == true) && + !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) { + + if (dwKeyType == PAIRWISE_KEY) { + + if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) { + *pKey = &(pTable->KeyTable[i].PairwiseKey); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetTransmitKey:"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PAIRWISE_KEY: KeyTable.abyBSSID: "); + for (ii = 0; ii < 6; ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + return (true); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PairwiseKey.bKeyValid == false\n"); + return (false); + } + } // End of Type == PAIRWISE + else { + if (pTable->KeyTable[i].dwGTKeyIndex == 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ERROR: dwGTKeyIndex == 0 !!!\n"); + return false; + } + if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid == true) { + *pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetTransmitKey:"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GROUP_KEY: KeyTable.abyBSSID\n"); + for (ii = 0; ii < 6; ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %X\n", + pTable->KeyTable[i].dwGTKeyIndex); + + return (true); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GroupKey.bKeyValid == false\n"); + return (false); + } + } // End of Type = GROUP + } // BSSID match + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ERROR: NO Match BSSID !!! "); + for (ii = 0; ii < 6; ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *(pbyBSSID+ii)); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + return (false); +} + +/* + * Description: Set Key to table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * dwKeyIndex - Key index (reference to NDIS DDK) + * uKeyLength - Key length + * KeyRSC - Key RSC + * pbyKey - Pointer to key + * Out: + * none + * + * Return Value: true if success otherwise false + * + */ + +int KeybSetDefaultKey(struct vnt_private *pDevice, PSKeyManagement pTable, + u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, + u8 byKeyDecMode) +{ + int ii; + PSKeyItem pKey; + u32 uKeyIdx; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enter KeybSetDefaultKey: %1x, %d\n", + (int) dwKeyIndex, (int) uKeyLength); + + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key + return (false); + } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) { + return (false); + } + + if (uKeyLength > MAX_KEY_LEN) + return false; + + pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = true; + for (ii = 0; ii < ETH_ALEN; ii++) + pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF; + + // Group key + pKey = &(pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF]); + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, + MAX_KEY_TABLE-1); + + } + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4); + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode); + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044; // use group key for all address + uKeyIdx = (dwKeyIndex & 0x000000FF); + + if ((uKeyLength == WLAN_WEP232_KEYLEN) && + (byKeyDecMode == KEY_CTL_WEP)) { + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000; // disable on-fly disable address match + pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = true; + } else { + if (pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP == false) + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000; // enable on-fly disable address match + } + + pKey->bKeyValid = true; + pKey->uKeyLength = uKeyLength; + pKey->dwKeyIndex = dwKeyIndex; + pKey->byCipherSuite = byKeyDecMode; + memcpy(pKey->abyKey, pbyKey, uKeyLength); + if (byKeyDecMode == KEY_CTL_WEP) { + if (uKeyLength == WLAN_WEP40_KEYLEN) + pKey->abyKey[15] &= 0x7F; + if (uKeyLength == WLAN_WEP104_KEYLEN) + pKey->abyKey[15] |= 0x80; + } + + MACvSetKeyEntry(pDevice, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (u32 *) pKey->abyKey); + + if ((dwKeyIndex & USE_KEYRSC) == 0) + pKey->KeyRSC = 0; /* RSC set by NIC */ + else + pKey->KeyRSC = *KeyRSC; + + pKey->dwTSC47_16 = 0; + pKey->wTSC15_0 = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n", pKey->bKeyValid); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n", (int)pKey->uKeyLength); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: \n"); + for (ii = 0; ii < pKey->uKeyLength; ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x", pKey->abyKey[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n", + pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n", + pKey->dwKeyIndex); + + return (true); +} + +/* + * Description: Set Key to table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * dwKeyIndex - Key index (reference to NDIS DDK) + * uKeyLength - Key length + * KeyRSC - Key RSC + * pbyKey - Pointer to key + * Out: + * none + * + * Return Value: true if success otherwise false + * + */ + +int KeybSetAllGroupKey(struct vnt_private *pDevice, PSKeyManagement pTable, + u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, + u8 byKeyDecMode) +{ + int i, ii; + PSKeyItem pKey; + u32 uKeyIdx; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n", + dwKeyIndex); + + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key + return (false); + } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) { + return (false); + } + + for (i=0; i < MAX_KEY_TABLE-1; i++) { + if (pTable->KeyTable[i].bInUse == true) { + // found table already exist + // Group key + pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]); + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[i].dwGTKeyIndex, i); + + } + pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); + pTable->KeyTable[i].wKeyCtl |= 0x0040; // use group key for group address + uKeyIdx = (dwKeyIndex & 0x000000FF); + + pTable->KeyTable[i].wKeyCtl |= 0x8000; // enable on-fly + + pKey->bKeyValid = true; + pKey->uKeyLength = uKeyLength; + pKey->dwKeyIndex = dwKeyIndex; + pKey->byCipherSuite = byKeyDecMode; + memcpy(pKey->abyKey, pbyKey, uKeyLength); + if (byKeyDecMode == KEY_CTL_WEP) { + if (uKeyLength == WLAN_WEP40_KEYLEN) + pKey->abyKey[15] &= 0x7F; + if (uKeyLength == WLAN_WEP104_KEYLEN) + pKey->abyKey[15] |= 0x80; + } + + MACvSetKeyEntry(pDevice, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (u32 *) pKey->abyKey); + + if ((dwKeyIndex & USE_KEYRSC) == 0) + pKey->KeyRSC = 0; /* RSC set by NIC */ + else + pKey->KeyRSC = *KeyRSC; + + pKey->dwTSC47_16 = 0; + pKey->wTSC15_0 = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); + for (ii = 0; ii < pKey->uKeyLength; ii++) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", pKey->abyKey[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + //DBG_PRN_GRP12(("pKey->dwTSC47_16: %lX\n ", pKey->dwTSC47_16)); + //DBG_PRN_GRP12(("pKey->wTSC15_0: %X\n ", pKey->wTSC15_0)); + //DBG_PRN_GRP12(("pKey->dwKeyIndex: %lX\n ", pKey->dwKeyIndex)); + + } // (pTable->KeyTable[i].bInUse == true) + } + return (true); +} diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h new file mode 100644 index 00000000..23e188d1 --- /dev/null +++ b/drivers/staging/vt6656/key.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: key.h + * + * Purpose: Implement functions for 802.11i Key management + * + * Author: Jerry Chen + * + * Date: May 29, 2003 + * + */ + +#ifndef __KEY_H__ +#define __KEY_H__ + +#include "tether.h" +#include "80211mgr.h" + +#define MAX_GROUP_KEY 4 +#define MAX_KEY_TABLE 11 +#define MAX_KEY_LEN 32 +#define AES_KEY_LEN 16 + +#define AUTHENTICATOR_KEY 0x10000000 +#define USE_KEYRSC 0x20000000 +#define PAIRWISE_KEY 0x40000000 +#define TRANSMIT_KEY 0x80000000 + +#define GROUP_KEY 0x00000000 + +#define KEY_CTL_WEP 0x00 +#define KEY_CTL_NONE 0x01 +#define KEY_CTL_TKIP 0x02 +#define KEY_CTL_CCMP 0x03 +#define KEY_CTL_INVALID 0xFF + +typedef struct tagSKeyItem +{ + bool bKeyValid; + u32 uKeyLength; + u8 abyKey[MAX_KEY_LEN]; + u64 KeyRSC; + u32 dwTSC47_16; + u16 wTSC15_0; + u8 byCipherSuite; + u8 byReserved0; + u32 dwKeyIndex; + void *pvKeyTable; +} SKeyItem, *PSKeyItem; //64 + +typedef struct tagSKeyTable +{ + u8 abyBSSID[ETH_ALEN]; /* 6 */ + u8 byReserved0[2]; //8 + SKeyItem PairwiseKey; + SKeyItem GroupKey[MAX_GROUP_KEY]; //64*5 = 320, 320+8=328 + u32 dwGTKeyIndex; // GroupTransmitKey Index + bool bInUse; + u16 wKeyCtl; + bool bSoftWEP; + u8 byReserved1[6]; +} SKeyTable, *PSKeyTable; //352 + +typedef struct tagSKeyManagement +{ + SKeyTable KeyTable[MAX_KEY_TABLE]; +} SKeyManagement, *PSKeyManagement; + +void KeyvInitTable(struct vnt_private *, PSKeyManagement pTable); + +int KeybGetKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyIndex, + PSKeyItem *pKey); + +int KeybSetKey(struct vnt_private *, PSKeyManagement pTable, u8 *pbyBSSID, + u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, + u8 byKeyDecMode); + +int KeybRemoveKey(struct vnt_private *, PSKeyManagement pTable, + u8 *pbyBSSID, u32 dwKeyIndex); + +int KeybRemoveAllKey(struct vnt_private *, PSKeyManagement pTable, + u8 *pbyBSSID); + +int KeybGetTransmitKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyType, + PSKeyItem *pKey); + +int KeybSetDefaultKey(struct vnt_private *, PSKeyManagement pTable, + u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, + u8 byKeyDecMode); + +int KeybSetAllGroupKey(struct vnt_private *, PSKeyManagement pTable, + u32 dwKeyIndex, u32 uKeyLength, u64 *KeyRSC, u8 *pbyKey, + u8 byKeyDecMode); + +#endif /* __KEY_H__ */ diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c new file mode 100644 index 00000000..343db192 --- /dev/null +++ b/drivers/staging/vt6656/mac.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: mac.c + * + * Purpose: MAC routines + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * + * Revision History: + */ + +#include "tmacro.h" +#include "tether.h" +#include "desc.h" +#include "mac.h" +#include "80211hdr.h" +#include "rndis.h" +#include "control.h" + +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +/* + * Description: + * Write MAC Multicast Address Mask + * + * Parameters: + * In: + * uByteidx - Index of Mask + * byData - Mask Value to write + * Out: + * none + * + * Return Value: none + * + */ +void MACvWriteMultiAddr(struct vnt_private *pDevice, u32 uByteIdx, u8 byData) +{ + u8 byData1; + + byData1 = byData; + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + (u16) (MAC_REG_MAR0 + uByteIdx), + MESSAGE_REQUEST_MACREG, + 1, + &byData1); +} + +/* + * Description: + * Shut Down MAC + * + * Parameters: + * In: + * Out: + * none + * + * + */ +void MACbShutdown(struct vnt_private *pDevice) +{ + CONTROLnsRequestOutAsyn(pDevice, + MESSAGE_TYPE_MACSHUTDOWN, + 0, + 0, + 0, + NULL + ); +} + +void MACvSetBBType(struct vnt_private *pDevice, u8 byType) +{ + u8 pbyData[2]; + + pbyData[0] = byType; + pbyData[1] = EnCFG_BBType_MASK; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE_MASK, + MAC_REG_ENCFG0, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); +} + +/* + * Description: + * Disable the Key Entry by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ +void MACvDisableKeyEntry(struct vnt_private *pDevice, u32 uEntryIdx) +{ + u16 wOffset; + u8 byData; + + byData = (u8) uEntryIdx; + + wOffset = MISCFIFO_KEYETRY0; + wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); + + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, 0); + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + + //issue write misc fifo command to device + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_CLRKEYENTRY, + 0, + 0, + 1, + &byData + ); +} + +/* + * Description: + * Set the Key by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetKeyEntry(struct vnt_private *pDevice, u16 wKeyCtl, u32 uEntryIdx, + u32 uKeyIdx, u8 *pbyAddr, u32 *pdwKey) +{ + u8 *pbyKey; + u16 wOffset; + u32 dwData1, dwData2; + int ii; + u8 pbyData[24]; + + if (pDevice->byLocalID <= MAC_REVISION_A1) + if (pDevice->vnt_mgmt.byCSSPK == KEY_CTL_CCMP) + return; + + wOffset = MISCFIFO_KEYETRY0; + wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); + + dwData1 = 0; + dwData1 |= wKeyCtl; + dwData1 <<= 16; + dwData1 |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5)); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %X,"\ + " KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); + + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + + //wOffset++; + + dwData2 = 0; + dwData2 |= *(pbyAddr+3); + dwData2 <<= 8; + dwData2 |= *(pbyAddr+2); + dwData2 <<= 8; + dwData2 |= *(pbyAddr+1); + dwData2 <<= 8; + dwData2 |= *(pbyAddr+0); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %X\n", + wOffset, dwData2); + + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + + //wOffset++; + + //wOffset += (uKeyIdx * 4); +/* for (ii=0;ii<4;ii++) { + // alway push 128 bits + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"3.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + } +*/ + pbyKey = (u8 *)pdwKey; + + pbyData[0] = (u8)dwData1; + pbyData[1] = (u8)(dwData1>>8); + pbyData[2] = (u8)(dwData1>>16); + pbyData[3] = (u8)(dwData1>>24); + pbyData[4] = (u8)dwData2; + pbyData[5] = (u8)(dwData2>>8); + pbyData[6] = (u8)(dwData2>>16); + pbyData[7] = (u8)(dwData2>>24); + for (ii = 8; ii < 24; ii++) + pbyData[ii] = *pbyKey++; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_SETKEY, + wOffset, + (u16)uKeyIdx, + 24, + pbyData + ); + +} + +void MACvRegBitsOff(struct vnt_private *pDevice, u8 byRegOfs, u8 byBits) +{ + u8 pbyData[2]; + + pbyData[0] = 0; + pbyData[1] = byBits; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE_MASK, + byRegOfs, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); +} + +void MACvRegBitsOn(struct vnt_private *pDevice, u8 byRegOfs, u8 byBits) +{ + u8 pbyData[2]; + + pbyData[0] = byBits; + pbyData[1] = byBits; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE_MASK, + byRegOfs, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); +} + +void MACvWriteWord(struct vnt_private *pDevice, u8 byRegOfs, u16 wData) +{ + u8 pbyData[2]; + + pbyData[0] = (u8)(wData & 0xff); + pbyData[1] = (u8)(wData >> 8); + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + byRegOfs, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); + +} + +void MACvWriteBSSIDAddress(struct vnt_private *pDevice, u8 *pbyEtherAddr) +{ + u8 pbyData[6]; + + pbyData[0] = *((u8 *)pbyEtherAddr); + pbyData[1] = *((u8 *)pbyEtherAddr+1); + pbyData[2] = *((u8 *)pbyEtherAddr+2); + pbyData[3] = *((u8 *)pbyEtherAddr+3); + pbyData[4] = *((u8 *)pbyEtherAddr+4); + pbyData[5] = *((u8 *)pbyEtherAddr+5); + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + MAC_REG_BSSID0, + MESSAGE_REQUEST_MACREG, + 6, + pbyData + ); +} + +void MACvEnableProtectMD(struct vnt_private *pDevice) +{ + u8 pbyData[2]; + + pbyData[0] = EnCFG_ProtectMd; + pbyData[1] = EnCFG_ProtectMd; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE_MASK, + MAC_REG_ENCFG0, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); +} + +void MACvDisableProtectMD(struct vnt_private *pDevice) +{ + u8 pbyData[2]; + + pbyData[0] = 0; + pbyData[1] = EnCFG_ProtectMd; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE_MASK, + MAC_REG_ENCFG0, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); +} + +void MACvEnableBarkerPreambleMd(struct vnt_private *pDevice) +{ + u8 pbyData[2]; + + pbyData[0] = EnCFG_BarkerPream; + pbyData[1] = EnCFG_BarkerPream; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE_MASK, + MAC_REG_ENCFG2, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); +} + +void MACvDisableBarkerPreambleMd(struct vnt_private *pDevice) +{ + u8 pbyData[2]; + + pbyData[0] = 0; + pbyData[1] = EnCFG_BarkerPream; + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE_MASK, + MAC_REG_ENCFG2, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); +} + +void MACvWriteBeaconInterval(struct vnt_private *pDevice, u16 wInterval) +{ + u8 pbyData[2]; + + pbyData[0] = (u8)(wInterval & 0xff); + pbyData[1] = (u8)(wInterval >> 8); + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + MAC_REG_BI, + MESSAGE_REQUEST_MACREG, + 2, + pbyData + ); +} diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h new file mode 100644 index 00000000..0db1be5b --- /dev/null +++ b/drivers/staging/vt6656/mac.h @@ -0,0 +1,421 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: mac.h + * + * Purpose: MAC routines + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Revision History: + * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53. + * 09-03-2003 Bryan YC Fan: Add MACvDisableProtectMD & MACvEnableProtectMD + */ + +#ifndef __MAC_H__ +#define __MAC_H__ + +#include "device.h" +#include "tmacro.h" + +#define REV_ID_VT3253_A0 0x00 +#define REV_ID_VT3253_A1 0x01 +#define REV_ID_VT3253_B0 0x08 +#define REV_ID_VT3253_B1 0x09 + +// +// Registers in the MAC +// +#define MAC_REG_BISTCMD 0x04 +#define MAC_REG_BISTSR0 0x05 +#define MAC_REG_BISTSR1 0x06 +#define MAC_REG_BISTSR2 0x07 +#define MAC_REG_I2MCSR 0x08 +#define MAC_REG_I2MTGID 0x09 +#define MAC_REG_I2MTGAD 0x0A +#define MAC_REG_I2MCFG 0x0B +#define MAC_REG_I2MDIPT 0x0C +#define MAC_REG_I2MDOPT 0x0E +#define MAC_REG_USBSUS 0x0F + +#define MAC_REG_LOCALID 0x14 +#define MAC_REG_TESTCFG 0x15 +#define MAC_REG_JUMPER0 0x16 +#define MAC_REG_JUMPER1 0x17 +#define MAC_REG_TMCTL 0x18 +#define MAC_REG_TMDATA0 0x1C +#define MAC_REG_TMDATA1 0x1D +#define MAC_REG_TMDATA2 0x1E +#define MAC_REG_TMDATA3 0x1F + +// MAC Parameter related +#define MAC_REG_LRT 0x20 // +#define MAC_REG_SRT 0x21 // +#define MAC_REG_SIFS 0x22 // +#define MAC_REG_DIFS 0x23 // +#define MAC_REG_EIFS 0x24 // +#define MAC_REG_SLOT 0x25 // +#define MAC_REG_BI 0x26 // +#define MAC_REG_CWMAXMIN0 0x28 // +#define MAC_REG_LINKOFFTOTM 0x2A +#define MAC_REG_SWTMOT 0x2B +#define MAC_REG_RTSOKCNT 0x2C +#define MAC_REG_RTSFAILCNT 0x2D +#define MAC_REG_ACKFAILCNT 0x2E +#define MAC_REG_FCSERRCNT 0x2F +// TSF Related +#define MAC_REG_TSFCNTR 0x30 // +#define MAC_REG_NEXTTBTT 0x38 // +#define MAC_REG_TSFOFST 0x40 // +#define MAC_REG_TFTCTL 0x48 // +// WMAC Control/Status Related +#define MAC_REG_ENCFG0 0x4C // +#define MAC_REG_ENCFG1 0x4D // +#define MAC_REG_ENCFG2 0x4E // + +#define MAC_REG_CFG 0x50 // +#define MAC_REG_TEST 0x52 // +#define MAC_REG_HOSTCR 0x54 // +#define MAC_REG_MACCR 0x55 // +#define MAC_REG_RCR 0x56 // +#define MAC_REG_TCR 0x57 // +#define MAC_REG_IMR 0x58 // +#define MAC_REG_ISR 0x5C +#define MAC_REG_ISR1 0x5D +// Power Saving Related +#define MAC_REG_PSCFG 0x60 // +#define MAC_REG_PSCTL 0x61 // +#define MAC_REG_PSPWRSIG 0x62 // +#define MAC_REG_BBCR13 0x63 +#define MAC_REG_AIDATIM 0x64 +#define MAC_REG_PWBT 0x66 +#define MAC_REG_WAKEOKTMR 0x68 +#define MAC_REG_CALTMR 0x69 +#define MAC_REG_SYNSPACCNT 0x6A +#define MAC_REG_WAKSYNOPT 0x6B +// Baseband/IF Control Group +#define MAC_REG_BBREGCTL 0x6C // +#define MAC_REG_CHANNEL 0x6D +#define MAC_REG_BBREGADR 0x6E +#define MAC_REG_BBREGDATA 0x6F +#define MAC_REG_IFREGCTL 0x70 // +#define MAC_REG_IFDATA 0x71 // +#define MAC_REG_ITRTMSET 0x74 // +#define MAC_REG_PAPEDELAY 0x77 +#define MAC_REG_SOFTPWRCTL 0x78 // +#define MAC_REG_SOFTPWRCTL2 0x79 // +#define MAC_REG_GPIOCTL0 0x7A // +#define MAC_REG_GPIOCTL1 0x7B // + +// MiscFF PIO related +#define MAC_REG_MISCFFNDEX 0xBC +#define MAC_REG_MISCFFCTL 0xBE +#define MAC_REG_MISCFFDATA 0xC0 + +// MAC Configuration Group +#define MAC_REG_PAR0 0xC4 +#define MAC_REG_PAR4 0xC8 +#define MAC_REG_BSSID0 0xCC +#define MAC_REG_BSSID4 0xD0 +#define MAC_REG_MAR0 0xD4 +#define MAC_REG_MAR4 0xD8 +// MAC RSPPKT INFO Group +#define MAC_REG_RSPINF_B_1 0xDC +#define MAC_REG_RSPINF_B_2 0xE0 +#define MAC_REG_RSPINF_B_5 0xE4 +#define MAC_REG_RSPINF_B_11 0xE8 +#define MAC_REG_RSPINF_A_6 0xEC +#define MAC_REG_RSPINF_A_9 0xEE +#define MAC_REG_RSPINF_A_12 0xF0 +#define MAC_REG_RSPINF_A_18 0xF2 +#define MAC_REG_RSPINF_A_24 0xF4 +#define MAC_REG_RSPINF_A_36 0xF6 +#define MAC_REG_RSPINF_A_48 0xF8 +#define MAC_REG_RSPINF_A_54 0xFA +#define MAC_REG_RSPINF_A_72 0xFC + +// +// Bits in the I2MCFG EEPROM register +// +#define I2MCFG_BOUNDCTL 0x80 +#define I2MCFG_WAITCTL 0x20 +#define I2MCFG_SCLOECTL 0x10 +#define I2MCFG_WBUSYCTL 0x08 +#define I2MCFG_NORETRY 0x04 +#define I2MCFG_I2MLDSEQ 0x02 +#define I2MCFG_I2CMFAST 0x01 + +// +// Bits in the I2MCSR EEPROM register +// +#define I2MCSR_EEMW 0x80 +#define I2MCSR_EEMR 0x40 +#define I2MCSR_AUTOLD 0x08 +#define I2MCSR_NACK 0x02 +#define I2MCSR_DONE 0x01 + +// +// Bits in the TMCTL register +// +#define TMCTL_TSUSP 0x04 +#define TMCTL_TMD 0x02 +#define TMCTL_TE 0x01 + +// +// Bits in the TFTCTL register +// +#define TFTCTL_HWUTSF 0x80 // +#define TFTCTL_TBTTSYNC 0x40 +#define TFTCTL_HWUTSFEN 0x20 +#define TFTCTL_TSFCNTRRD 0x10 // +#define TFTCTL_TBTTSYNCEN 0x08 // +#define TFTCTL_TSFSYNCEN 0x04 // +#define TFTCTL_TSFCNTRST 0x02 // +#define TFTCTL_TSFCNTREN 0x01 // + +// +// Bits in the EnhanceCFG_0 register +// +#define EnCFG_BBType_a 0x00 +#define EnCFG_BBType_b 0x01 +#define EnCFG_BBType_g 0x02 +#define EnCFG_BBType_MASK 0x03 +#define EnCFG_ProtectMd 0x20 + +// +// Bits in the EnhanceCFG_1 register +// +#define EnCFG_BcnSusInd 0x01 +#define EnCFG_BcnSusClr 0x02 + +// +// Bits in the EnhanceCFG_2 register +// +#define EnCFG_NXTBTTCFPSTR 0x01 +#define EnCFG_BarkerPream 0x02 +#define EnCFG_PktBurstMode 0x04 + +// +// Bits in the CFG register +// +#define CFG_TKIPOPT 0x80 +#define CFG_RXDMAOPT 0x40 +#define CFG_TMOT_SW 0x20 +#define CFG_TMOT_HWLONG 0x10 +#define CFG_TMOT_HW 0x00 +#define CFG_CFPENDOPT 0x08 +#define CFG_BCNSUSEN 0x04 +#define CFG_NOTXTIMEOUT 0x02 +#define CFG_NOBUFOPT 0x01 + +// +// Bits in the TEST register +// +#define TEST_LBEXT 0x80 // +#define TEST_LBINT 0x40 // +#define TEST_LBNONE 0x00 // +#define TEST_SOFTINT 0x20 // +#define TEST_CONTTX 0x10 // +#define TEST_TXPE 0x08 // +#define TEST_NAVDIS 0x04 // +#define TEST_NOCTS 0x02 // +#define TEST_NOACK 0x01 // + +// +// Bits in the HOSTCR register +// +#define HOSTCR_TXONST 0x80 // +#define HOSTCR_RXONST 0x40 // +#define HOSTCR_ADHOC 0x20 // Network Type 1 = Ad-hoc +#define HOSTCR_AP 0x10 // Port Type 1 = AP +#define HOSTCR_TXON 0x08 //0000 1000 +#define HOSTCR_RXON 0x04 //0000 0100 +#define HOSTCR_MACEN 0x02 //0000 0010 +#define HOSTCR_SOFTRST 0x01 //0000 0001 + +// +// Bits in the MACCR register +// +#define MACCR_SYNCFLUSHOK 0x04 // +#define MACCR_SYNCFLUSH 0x02 // +#define MACCR_CLRNAV 0x01 // + +// +// Bits in the RCR register +// +#define RCR_SSID 0x80 +#define RCR_RXALLTYPE 0x40 // +#define RCR_UNICAST 0x20 // +#define RCR_BROADCAST 0x10 // +#define RCR_MULTICAST 0x08 // +#define RCR_WPAERR 0x04 // +#define RCR_ERRCRC 0x02 // +#define RCR_BSSID 0x01 // + +// +// Bits in the TCR register +// +#define TCR_SYNCDCFOPT 0x02 // +#define TCR_AUTOBCNTX 0x01 // Beacon automatically transmit enable + +//ISR1 +#define ISR_GPIO3 0x40 +#define ISR_RXNOBUF 0x08 +#define ISR_MIBNEARFULL 0x04 +#define ISR_SOFTINT 0x02 +#define ISR_FETALERR 0x01 + +#define LEDSTS_STS 0x06 +#define LEDSTS_TMLEN 0x78 +#define LEDSTS_OFF 0x00 +#define LEDSTS_ON 0x02 +#define LEDSTS_SLOW 0x04 +#define LEDSTS_INTER 0x06 + +//ISR0 +#define ISR_WATCHDOG 0x80 +#define ISR_SOFTTIMER 0x40 +#define ISR_GPIO0 0x20 +#define ISR_TBTT 0x10 +#define ISR_RXDMA0 0x08 +#define ISR_BNTX 0x04 +#define ISR_ACTX 0x01 + +// +// Bits in the PSCFG register +// +#define PSCFG_PHILIPMD 0x40 // +#define PSCFG_WAKECALEN 0x20 // +#define PSCFG_WAKETMREN 0x10 // +#define PSCFG_BBPSPROG 0x08 // +#define PSCFG_WAKESYN 0x04 // +#define PSCFG_SLEEPSYN 0x02 // +#define PSCFG_AUTOSLEEP 0x01 // + +// +// Bits in the PSCTL register +// +#define PSCTL_WAKEDONE 0x20 // +#define PSCTL_PS 0x10 // +#define PSCTL_GO2DOZE 0x08 // +#define PSCTL_LNBCN 0x04 // +#define PSCTL_ALBCN 0x02 // +#define PSCTL_PSEN 0x01 // + +// +// Bits in the PSPWSIG register +// +#define PSSIG_WPE3 0x80 // +#define PSSIG_WPE2 0x40 // +#define PSSIG_WPE1 0x20 // +#define PSSIG_WRADIOPE 0x10 // +#define PSSIG_SPE3 0x08 // +#define PSSIG_SPE2 0x04 // +#define PSSIG_SPE1 0x02 // +#define PSSIG_SRADIOPE 0x01 // + +// +// Bits in the BBREGCTL register +// +#define BBREGCTL_DONE 0x04 // +#define BBREGCTL_REGR 0x02 // +#define BBREGCTL_REGW 0x01 // + +// +// Bits in the IFREGCTL register +// +#define IFREGCTL_DONE 0x04 // +#define IFREGCTL_IFRF 0x02 // +#define IFREGCTL_REGW 0x01 // + +// +// Bits in the SOFTPWRCTL register +// +#define SOFTPWRCTL_RFLEOPT 0x08 // +#define SOFTPWRCTL_TXPEINV 0x02 // +#define SOFTPWRCTL_SWPECTI 0x01 // +#define SOFTPWRCTL_SWPAPE 0x20 // +#define SOFTPWRCTL_SWCALEN 0x10 // +#define SOFTPWRCTL_SWRADIO_PE 0x08 // +#define SOFTPWRCTL_SWPE2 0x04 // +#define SOFTPWRCTL_SWPE1 0x02 // +#define SOFTPWRCTL_SWPE3 0x01 // + +// +// Bits in the GPIOCTL1 register +// +#define GPIO3_MD 0x20 // +#define GPIO3_DATA 0x40 // +#define GPIO3_INTMD 0x80 // + +// +// Bits in the MISCFFCTL register +// +#define MISCFFCTL_WRITE 0x0001 // + +// Loopback mode +#define MAC_LB_EXT 0x02 // +#define MAC_LB_INTERNAL 0x01 // +#define MAC_LB_NONE 0x00 // + +// Ethernet address filter type +#define PKT_TYPE_NONE 0x00 // turn off receiver +#define PKT_TYPE_ALL_MULTICAST 0x80 +#define PKT_TYPE_PROMISCUOUS 0x40 +#define PKT_TYPE_DIRECTED 0x20 // obselete, directed address is always accepted +#define PKT_TYPE_BROADCAST 0x10 +#define PKT_TYPE_MULTICAST 0x08 +#define PKT_TYPE_ERROR_WPA 0x04 +#define PKT_TYPE_ERROR_CRC 0x02 +#define PKT_TYPE_BSSID 0x01 + +#define Default_BI 0x200 + +// MiscFIFO Offset +#define MISCFIFO_KEYETRY0 32 +#define MISCFIFO_KEYENTRYSIZE 22 + +// max time out delay time +#define W_MAX_TIMEOUT 0xFFF0U // + +// wait time within loop +#define CB_DELAY_LOOP_WAIT 10 // 10ms + +#define MAC_REVISION_A0 0x00 +#define MAC_REVISION_A1 0x01 + +void MACvWriteMultiAddr(struct vnt_private *, u32, u8); +void MACbShutdown(struct vnt_private *); +void MACvSetBBType(struct vnt_private *, u8); +void MACvDisableKeyEntry(struct vnt_private *, u32); +void MACvSetKeyEntry(struct vnt_private *, u16, u32, u32, u8 *, u32 *); +void MACvRegBitsOff(struct vnt_private *, u8, u8); +void MACvRegBitsOn(struct vnt_private *, u8, u8); +void MACvWriteWord(struct vnt_private *, u8, u16); +void MACvWriteBSSIDAddress(struct vnt_private *, u8 *); +void MACvEnableProtectMD(struct vnt_private *); +void MACvDisableProtectMD(struct vnt_private *); +void MACvEnableBarkerPreambleMd(struct vnt_private *); +void MACvDisableBarkerPreambleMd(struct vnt_private *); +void MACvWriteBeaconInterval(struct vnt_private *, u16); + +#endif /* __MAC_H__ */ diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c new file mode 100644 index 00000000..06b966cf --- /dev/null +++ b/drivers/staging/vt6656/main_usb.c @@ -0,0 +1,1490 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: main_usb.c + * + * Purpose: driver entry for initial, open, close, tx and rx. + * + * Author: Lyndon Chen + * + * Date: Dec 8, 2005 + * + * Functions: + * + * vt6656_probe - module initial (insmod) driver entry + * device_remove1 - module remove entry + * device_open - allocate dma/descripter resource & initial mac/bbp function + * device_xmit - asynchronous data tx function + * device_set_multi - set mac filter + * device_ioctl - ioctl entry + * device_close - shutdown mac/bbp & free dma/descriptor resource + * device_alloc_frag_buf - rx fragement pre-allocated function + * device_free_tx_bufs - free tx buffer function + * device_dma0_tx_80211- tx 802.11 frame via dma0 + * device_dma0_xmit- tx PS buffered frame via dma0 + * device_init_registers- initial MAC & BBP & RF internal registers. + * device_init_rings- initial tx/rx ring buffer + * device_init_defrag_cb- initial & allocate de-fragement buffer. + * device_tx_srv- tx interrupt service function + * + * Revision History: + */ +#undef __NO_VERSION__ + +#include <linux/file.h> +#include "device.h" +#include "card.h" +#include "baseband.h" +#include "mac.h" +#include "tether.h" +#include "wmgr.h" +#include "wctl.h" +#include "power.h" +#include "wcmd.h" +#include "iocmd.h" +#include "tcrc.h" +#include "rxtx.h" +#include "bssdb.h" +#include "hostap.h" +#include "wpactl.h" +#include "iwctl.h" +#include "dpc.h" +#include "datarate.h" +#include "rf.h" +#include "firmware.h" +#include "rndis.h" +#include "control.h" +#include "channel.h" +#include "int.h" +#include "iowpa.h" + +/* static int msglevel = MSG_LEVEL_DEBUG; */ +static int msglevel =MSG_LEVEL_INFO; + +/* + * define module options + */ + +/* version information */ +#define DRIVER_AUTHOR \ + "VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>" +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DEVICE_FULL_DRV_NAM); + +#define DEVICE_PARAM(N,D) \ + static int N[MAX_UINTS]=OPTION_DEFAULT;\ + module_param_array(N, int, NULL, 0);\ + MODULE_PARM_DESC(N, D); + +#define RX_DESC_DEF0 64 +DEVICE_PARAM(RxDescriptors0,"Number of receive usb desc buffer"); + +#define TX_DESC_DEF0 64 +DEVICE_PARAM(TxDescriptors0,"Number of transmit usb desc buffer"); + +#define CHANNEL_DEF 6 +DEVICE_PARAM(Channel, "Channel number"); + +/* PreambleType[] is the preamble length used for transmit. + 0: indicate allows long preamble type + 1: indicate allows short preamble type +*/ + +#define PREAMBLE_TYPE_DEF 1 + +DEVICE_PARAM(PreambleType, "Preamble Type"); + +#define RTS_THRESH_DEF 2347 +DEVICE_PARAM(RTSThreshold, "RTS threshold"); + +#define FRAG_THRESH_DEF 2346 +DEVICE_PARAM(FragThreshold, "Fragmentation threshold"); + +#define DATA_RATE_DEF 13 +/* datarate[] index + 0: indicate 1 Mbps 0x02 + 1: indicate 2 Mbps 0x04 + 2: indicate 5.5 Mbps 0x0B + 3: indicate 11 Mbps 0x16 + 4: indicate 6 Mbps 0x0c + 5: indicate 9 Mbps 0x12 + 6: indicate 12 Mbps 0x18 + 7: indicate 18 Mbps 0x24 + 8: indicate 24 Mbps 0x30 + 9: indicate 36 Mbps 0x48 + 10: indicate 48 Mbps 0x60 + 11: indicate 54 Mbps 0x6c + 12: indicate 72 Mbps 0x90 + 13: indicate auto rate +*/ + +DEVICE_PARAM(ConnectionRate, "Connection data rate"); + +#define OP_MODE_DEF 0 +DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode "); + +/* OpMode[] is used for transmit. + 0: indicate infrastruct mode used + 1: indicate adhoc mode used + 2: indicate AP mode used +*/ + +/* PSMode[] + 0: indicate disable power saving mode + 1: indicate enable power saving mode +*/ + +#define PS_MODE_DEF 0 +DEVICE_PARAM(PSMode, "Power saving mode"); + +#define SHORT_RETRY_DEF 8 +DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); + +#define LONG_RETRY_DEF 4 +DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); + +/* BasebandType[] baseband type selected + 0: indicate 802.11a type + 1: indicate 802.11b type + 2: indicate 802.11g type +*/ + +#define BBP_TYPE_DEF 2 +DEVICE_PARAM(BasebandType, "baseband type"); + +/* 80211hEnable[] + 0: indicate disable 802.11h + 1: indicate enable 802.11h +*/ + +#define X80211h_MODE_DEF 0 + +DEVICE_PARAM(b80211hEnable, "802.11h mode"); + +/* + * Static vars definitions + */ + +static struct usb_device_id vt6656_table[] = { + {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)}, + {} +}; + +/* frequency list (map channels to frequencies) */ +/* +static const long frequency_list[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484, + 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980, + 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240, + 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, + 5700, 5745, 5765, 5785, 5805, 5825 + }; + +static const struct iw_handler_def iwctl_handler_def; +*/ + +static int vt6656_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void vt6656_disconnect(struct usb_interface *intf); + +#ifdef CONFIG_PM /* Minimal support for suspend and resume */ +static int vt6656_suspend(struct usb_interface *intf, pm_message_t message); +static int vt6656_resume(struct usb_interface *intf); +#endif /* CONFIG_PM */ + +static struct net_device_stats *device_get_stats(struct net_device *dev); +static int device_open(struct net_device *dev); +static int device_xmit(struct sk_buff *skb, struct net_device *dev); +static void device_set_multi(struct net_device *dev); +static int device_close(struct net_device *dev); +static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); + +static int device_init_registers(struct vnt_private *pDevice, + DEVICE_INIT_TYPE InitType); +static bool device_init_defrag_cb(struct vnt_private *pDevice); +static void device_init_diversity_timer(struct vnt_private *pDevice); +static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev); + +static int ethtool_ioctl(struct net_device *dev, void *useraddr); +static void device_free_tx_bufs(struct vnt_private *pDevice); +static void device_free_rx_bufs(struct vnt_private *pDevice); +static void device_free_int_bufs(struct vnt_private *pDevice); +static void device_free_frag_bufs(struct vnt_private *pDevice); +static bool device_alloc_bufs(struct vnt_private *pDevice); + +static int Read_config_file(struct vnt_private *pDevice); +static unsigned char *Config_FileOperation(struct vnt_private *pDevice); +static int Config_FileGetParameter(unsigned char *string, + unsigned char *dest, + unsigned char *source); + +static void usb_device_reset(struct vnt_private *pDevice); + +static void +device_set_options(struct vnt_private *pDevice) { + + u8 abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; + u8 abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8}; + + memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN); + memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN); + memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN); + + pDevice->cbTD = TX_DESC_DEF0; + pDevice->cbRD = RX_DESC_DEF0; + pDevice->uChannel = CHANNEL_DEF; + pDevice->wRTSThreshold = RTS_THRESH_DEF; + pDevice->wFragmentationThreshold = FRAG_THRESH_DEF; + pDevice->byShortRetryLimit = SHORT_RETRY_DEF; + pDevice->byLongRetryLimit = LONG_RETRY_DEF; + pDevice->wMaxTransmitMSDULifetime = DEFAULT_MSDU_LIFETIME; + pDevice->byShortPreamble = PREAMBLE_TYPE_DEF; + pDevice->ePSMode = PS_MODE_DEF; + pDevice->b11hEnable = X80211h_MODE_DEF; + pDevice->eOPMode = OP_MODE_DEF; + pDevice->uConnectionRate = DATA_RATE_DEF; + if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = true; + pDevice->byBBType = BBP_TYPE_DEF; + pDevice->byPacketType = pDevice->byBBType; + pDevice->byAutoFBCtrl = AUTO_FB_0; + pDevice->bUpdateBBVGA = true; + pDevice->byFOETuning = 0; + pDevice->byAutoPwrTunning = 0; + pDevice->wCTSDuration = 0; + pDevice->byPreambleType = 0; + pDevice->bExistSWNetAddr = false; + /* pDevice->bDiversityRegCtlON = true; */ + pDevice->bDiversityRegCtlON = false; +} + +static void device_init_diversity_timer(struct vnt_private *pDevice) +{ + init_timer(&pDevice->TimerSQ3Tmax1); + pDevice->TimerSQ3Tmax1.data = (unsigned long)pDevice; + pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack; + pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ); + + init_timer(&pDevice->TimerSQ3Tmax2); + pDevice->TimerSQ3Tmax2.data = (unsigned long)pDevice; + pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack; + pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ); + + init_timer(&pDevice->TimerSQ3Tmax3); + pDevice->TimerSQ3Tmax3.data = (unsigned long)pDevice; + pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerSQ3Tmax3CallBack; + pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ); + + return; +} + +/* + * initialization of MAC & BBP registers + */ + +static int device_init_registers(struct vnt_private *pDevice, + DEVICE_INIT_TYPE InitType) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u8 abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 abySNAP_RFC1042[ETH_ALEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; + u8 abySNAP_Bridgetunnel[ETH_ALEN] + = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; + u8 byAntenna; + int ii; + CMD_CARD_INIT sInitCmd; + int ntStatus = STATUS_SUCCESS; + RSP_CARD_INIT sInitRsp; + u8 byTmp; + u8 byCalibTXIQ = 0, byCalibTXDC = 0, byCalibRXIQ = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---->INIbInitAdapter. [%d][%d]\n", InitType, pDevice->byPacketType); + spin_lock_irq(&pDevice->lock); + if (InitType == DEVICE_INIT_COLD) { + memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN); + memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN); + memcpy(pDevice->abySNAP_Bridgetunnel, + abySNAP_Bridgetunnel, + ETH_ALEN); + + if ( !FIRMWAREbCheckVersion(pDevice) ) { + if (FIRMWAREbDownload(pDevice) == true) { + if (FIRMWAREbBrach2Sram(pDevice) == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" FIRMWAREbBrach2Sram fail \n"); + spin_unlock_irq(&pDevice->lock); + return false; + } + } else { + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" FIRMWAREbDownload fail \n"); + spin_unlock_irq(&pDevice->lock); + return false; + } + } + + if ( !BBbVT3184Init(pDevice) ) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" BBbVT3184Init fail \n"); + spin_unlock_irq(&pDevice->lock); + return false; + } + } + + sInitCmd.byInitClass = (u8)InitType; + sInitCmd.bExistSWNetAddr = (u8) pDevice->bExistSWNetAddr; + for (ii = 0; ii < 6; ii++) + sInitCmd.bySWNetAddr[ii] = pDevice->abyCurrentNetAddr[ii]; + sInitCmd.byShortRetryLimit = pDevice->byShortRetryLimit; + sInitCmd.byLongRetryLimit = pDevice->byLongRetryLimit; + + /* issue card_init command to device */ + ntStatus = CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_CARDINIT, + 0, + 0, + sizeof(CMD_CARD_INIT), + (u8 *) &(sInitCmd)); + + if ( ntStatus != STATUS_SUCCESS ) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Issue Card init fail \n"); + spin_unlock_irq(&pDevice->lock); + return false; + } + if (InitType == DEVICE_INIT_COLD) { + + ntStatus = CONTROLnsRequestIn(pDevice,MESSAGE_TYPE_INIT_RSP,0,0,sizeof(RSP_CARD_INIT), (u8 *) &(sInitRsp)); + + if (ntStatus != STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Cardinit request in status fail!\n"); + spin_unlock_irq(&pDevice->lock); + return false; + } + + /* local ID for AES functions */ + ntStatus = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + MAC_REG_LOCALID, + MESSAGE_REQUEST_MACREG, + 1, + &pDevice->byLocalID); + + if ( ntStatus != STATUS_SUCCESS ) { + spin_unlock_irq(&pDevice->lock); + return false; + } + + /* do MACbSoftwareReset in MACvInitialize */ + + /* force CCK */ + pDevice->bCCK = true; + pDevice->bProtectMode = false; + /* only used in 11g type, sync with ERP IE */ + pDevice->bNonERPPresent = false; + pDevice->bBarkerPreambleMd = false; + if ( pDevice->bFixRate ) { + pDevice->wCurrentRate = (u16) pDevice->uConnectionRate; + } else { + if ( pDevice->byBBType == BB_TYPE_11B ) + pDevice->wCurrentRate = RATE_11M; + else + pDevice->wCurrentRate = RATE_54M; + } + + CHvInitChannelTable(pDevice); + + pDevice->byTopOFDMBasicRate = RATE_24M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byRevId = 0; + /* target to IF pin while programming to RF chip */ + pDevice->byCurPwr = 0xFF; + + pDevice->byCCKPwr = pDevice->abyEEPROM[EEP_OFS_PWR_CCK]; + pDevice->byOFDMPwrG = pDevice->abyEEPROM[EEP_OFS_PWR_OFDMG]; + /* load power table */ + for (ii = 0; ii < 14; ii++) { + pDevice->abyCCKPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_CCK_PWR_TBL]; + if (pDevice->abyCCKPwrTbl[ii] == 0) + pDevice->abyCCKPwrTbl[ii] = pDevice->byCCKPwr; + pDevice->abyOFDMPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_OFDM_PWR_TBL]; + if (pDevice->abyOFDMPwrTbl[ii] == 0) + pDevice->abyOFDMPwrTbl[ii] = pDevice->byOFDMPwrG; + } + + /* + * original zonetype is USA, but custom zonetype is Europe, + * then need to recover 12, 13, 14 channels with 11 channel + */ + if(((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) || + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe))&& + (pDevice->byOriginalZonetype == ZoneType_USA)) { + for (ii = 11; ii < 14; ii++) { + pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10]; + pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10]; + } + } + + pDevice->byOFDMPwrA = 0x34; /* same as RFbMA2829SelectChannel */ + + /* load OFDM A power table */ + for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { + pDevice->abyOFDMAPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_OFDMA_PWR_TBL]; + if (pDevice->abyOFDMAPwrTbl[ii] == 0) + pDevice->abyOFDMAPwrTbl[ii] = pDevice->byOFDMPwrA; + } + + byAntenna = pDevice->abyEEPROM[EEP_OFS_ANTENNA]; + if (byAntenna & EEP_ANTINV) + pDevice->bTxRxAntInv = true; + else + pDevice->bTxRxAntInv = false; + + byAntenna &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + + if (byAntenna == 0) /* if not set default is both */ + byAntenna = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + + if (byAntenna == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { + pDevice->byAntennaCount = 2; + pDevice->byTxAntennaMode = ANT_B; + pDevice->dwTxAntennaSel = 1; + pDevice->dwRxAntennaSel = 1; + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_A; + else + pDevice->byRxAntennaMode = ANT_B; + + if (pDevice->bDiversityRegCtlON) + pDevice->bDiversityEnable = true; + else + pDevice->bDiversityEnable = false; + } else { + pDevice->bDiversityEnable = false; + pDevice->byAntennaCount = 1; + pDevice->dwTxAntennaSel = 0; + pDevice->dwRxAntennaSel = 0; + if (byAntenna & EEP_ANTENNA_AUX) { + pDevice->byTxAntennaMode = ANT_A; + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_B; + else + pDevice->byRxAntennaMode = ANT_A; + } else { + pDevice->byTxAntennaMode = ANT_B; + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_A; + else + pDevice->byRxAntennaMode = ANT_B; + } + } + pDevice->ulDiversityNValue = 100*255; + pDevice->ulDiversityMValue = 100*16; + pDevice->byTMax = 1; + pDevice->byTMax2 = 4; + pDevice->ulSQ3TH = 0; + pDevice->byTMax3 = 64; + + /* get Auto Fall Back type */ + pDevice->byAutoFBCtrl = AUTO_FB_0; + + /* set SCAN Time */ + pDevice->uScanTime = WLAN_SCAN_MINITIME; + + /* default Auto Mode */ + /* pDevice->NetworkType = Ndis802_11Automode; */ + pDevice->eConfigPHYMode = PHY_TYPE_AUTO; + pDevice->byBBType = BB_TYPE_11G; + + /* initialize BBP registers */ + pDevice->ulTxPower = 25; + + /* get channel range */ + pDevice->byMinChannel = 1; + pDevice->byMaxChannel = CB_MAX_CHANNEL; + + /* get RFType */ + pDevice->byRFType = sInitRsp.byRFType; + + if ((pDevice->byRFType & RF_EMU) != 0) { + /* force change RevID for VT3253 emu */ + pDevice->byRevId = 0x80; + } + + /* load vt3266 calibration parameters in EEPROM */ + if (pDevice->byRFType == RF_VT3226D0) { + if((pDevice->abyEEPROM[EEP_OFS_MAJOR_VER] == 0x1) && + (pDevice->abyEEPROM[EEP_OFS_MINOR_VER] >= 0x4)) { + byCalibTXIQ = pDevice->abyEEPROM[EEP_OFS_CALIB_TX_IQ]; + byCalibTXDC = pDevice->abyEEPROM[EEP_OFS_CALIB_TX_DC]; + byCalibRXIQ = pDevice->abyEEPROM[EEP_OFS_CALIB_RX_IQ]; + if( (byCalibTXIQ || byCalibTXDC || byCalibRXIQ) ) { + /* CR255, enable TX/RX IQ and DC compensation mode */ + ControlvWriteByte(pDevice, + MESSAGE_REQUEST_BBREG, + 0xFF, + 0x03); + /* CR251, TX I/Q Imbalance Calibration */ + ControlvWriteByte(pDevice, + MESSAGE_REQUEST_BBREG, + 0xFB, + byCalibTXIQ); + /* CR252, TX DC-Offset Calibration */ + ControlvWriteByte(pDevice, + MESSAGE_REQUEST_BBREG, + 0xFC, + byCalibTXDC); + /* CR253, RX I/Q Imbalance Calibration */ + ControlvWriteByte(pDevice, + MESSAGE_REQUEST_BBREG, + 0xFD, + byCalibRXIQ); + } else { + /* CR255, turn off BB Calibration compensation */ + ControlvWriteByte(pDevice, + MESSAGE_REQUEST_BBREG, + 0xFF, + 0x0); + } + } + } + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + pMgmt->uCurrChannel = pDevice->uChannel; + pMgmt->uIBSSChannel = pDevice->uChannel; + CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); + + /* get permanent network address */ + memcpy(pDevice->abyPermanentNetAddr,&(sInitRsp.byNetAddr[0]),6); + memcpy(pDevice->abyCurrentNetAddr, + pDevice->abyPermanentNetAddr, + ETH_ALEN); + + /* if exist SW network address, use it */ + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n", + pDevice->abyCurrentNetAddr); + } + + /* + * set BB and packet type at the same time + * set Short Slot Time, xIFS, and RSPINF + */ + if (pDevice->byBBType == BB_TYPE_11A) { + CARDbAddBasicRate(pDevice, RATE_6M); + pDevice->bShortSlotTime = true; + } else { + CARDbAddBasicRate(pDevice, RATE_1M); + pDevice->bShortSlotTime = false; + } + BBvSetShortSlotTime(pDevice); + CARDvSetBSSMode(pDevice); + + if (pDevice->bUpdateBBVGA) { + pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; + pDevice->byBBVGANew = pDevice->byBBVGACurrent; + BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); + } + + pDevice->byRadioCtl = pDevice->abyEEPROM[EEP_OFS_RADIOCTL]; + pDevice->bHWRadioOff = false; + if ( (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) != 0 ) { + ntStatus = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + MAC_REG_GPIOCTL1, + MESSAGE_REQUEST_MACREG, + 1, + &byTmp); + + if ( ntStatus != STATUS_SUCCESS ) { + spin_unlock_irq(&pDevice->lock); + return false; + } + if ( (byTmp & GPIO3_DATA) == 0 ) { + pDevice->bHWRadioOff = true; + MACvRegBitsOn(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD); + } else { + MACvRegBitsOff(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD); + pDevice->bHWRadioOff = false; + } + + } + + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_TMLEN,0x38); + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + MACvRegBitsOn(pDevice,MAC_REG_GPIOCTL0,0x01); + + if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) { + CARDbRadioPowerOff(pDevice); + } else { + CARDbRadioPowerOn(pDevice); + } + + spin_unlock_irq(&pDevice->lock); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----INIbInitAdapter Exit\n"); + return true; +} + +#ifdef CONFIG_PM /* Minimal support for suspend and resume */ + +static int vt6656_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct vnt_private *device = usb_get_intfdata(intf); + + if (!device || !device->dev) + return -ENODEV; + + if (device->flags & DEVICE_FLAGS_OPENED) + device_close(device->dev); + + return 0; +} + +static int vt6656_resume(struct usb_interface *intf) +{ + struct vnt_private *device = usb_get_intfdata(intf); + + if (!device || !device->dev) + return -ENODEV; + + if (!(device->flags & DEVICE_FLAGS_OPENED)) + device_open(device->dev); + + return 0; +} + +#endif /* CONFIG_PM */ + +static const struct net_device_ops device_netdev_ops = { + .ndo_open = device_open, + .ndo_stop = device_close, + .ndo_do_ioctl = device_ioctl, + .ndo_get_stats = device_get_stats, + .ndo_start_xmit = device_xmit, + .ndo_set_rx_mode = device_set_multi, +}; + +static int +vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + u8 fake_mac[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + struct usb_device *udev = interface_to_usbdev(intf); + int rc = 0; + struct net_device *netdev = NULL; + struct vnt_private *pDevice; + + printk(KERN_NOTICE "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION); + printk(KERN_NOTICE "Copyright (c) 2004 VIA Networking Technologies, Inc.\n"); + + udev = usb_get_dev(udev); + netdev = alloc_etherdev(sizeof(struct vnt_private)); + if (!netdev) { + printk(KERN_ERR DEVICE_NAME ": allocate net device failed\n"); + rc = -ENOMEM; + goto err_nomem; + } + + pDevice = netdev_priv(netdev); + memset(pDevice, 0, sizeof(struct vnt_private)); + + pDevice->dev = netdev; + pDevice->usb = udev; + + device_set_options(pDevice); + spin_lock_init(&pDevice->lock); + + pDevice->tx_80211 = device_dma0_tx_80211; + pDevice->vnt_mgmt.pAdapter = (void *) pDevice; + + netdev->netdev_ops = &device_netdev_ops; + netdev->wireless_handlers = + (struct iw_handler_def *) &iwctl_handler_def; + + usb_set_intfdata(intf, pDevice); + SET_NETDEV_DEV(netdev, &intf->dev); + memcpy(pDevice->dev->dev_addr, fake_mac, ETH_ALEN); + rc = register_netdev(netdev); + if (rc) { + printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n"); + goto err_netdev; + } + + usb_device_reset(pDevice); + + return 0; + +err_netdev: + free_netdev(netdev); +err_nomem: + usb_put_dev(udev); + + return rc; +} + +static void device_free_tx_bufs(struct vnt_private *pDevice) +{ + PUSB_SEND_CONTEXT pTxContext; + int ii; + + for (ii = 0; ii < pDevice->cbTD; ii++) { + + pTxContext = pDevice->apTD[ii]; + /* deallocate URBs */ + if (pTxContext->pUrb) { + usb_kill_urb(pTxContext->pUrb); + usb_free_urb(pTxContext->pUrb); + } + kfree(pTxContext); + } + return; +} + +static void device_free_rx_bufs(struct vnt_private *pDevice) +{ + PRCB pRCB; + int ii; + + for (ii = 0; ii < pDevice->cbRD; ii++) { + + pRCB = pDevice->apRCB[ii]; + /* deallocate URBs */ + if (pRCB->pUrb) { + usb_kill_urb(pRCB->pUrb); + usb_free_urb(pRCB->pUrb); + } + /* deallocate skb */ + if (pRCB->skb) + dev_kfree_skb(pRCB->skb); + } + kfree(pDevice->pRCBMem); + + return; +} + +static void usb_device_reset(struct vnt_private *pDevice) +{ + int status; + status = usb_reset_device(pDevice->usb); + if (status) + printk("usb_device_reset fail status=%d\n",status); + return ; +} + +static void device_free_int_bufs(struct vnt_private *pDevice) +{ + kfree(pDevice->intBuf.pDataBuf); + return; +} + +static bool device_alloc_bufs(struct vnt_private *pDevice) +{ + + PUSB_SEND_CONTEXT pTxContext; + PRCB pRCB; + int ii; + + for (ii = 0; ii < pDevice->cbTD; ii++) { + + pTxContext = kmalloc(sizeof(USB_SEND_CONTEXT), GFP_KERNEL); + if (pTxContext == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : allocate tx usb context failed\n", pDevice->dev->name); + goto free_tx; + } + pDevice->apTD[ii] = pTxContext; + pTxContext->pDevice = (void *) pDevice; + /* allocate URBs */ + pTxContext->pUrb = usb_alloc_urb(0, GFP_ATOMIC); + if (pTxContext->pUrb == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "alloc tx urb failed\n"); + goto free_tx; + } + pTxContext->bBoolInUse = false; + } + + /* allocate RCB mem */ + pDevice->pRCBMem = kzalloc((sizeof(RCB) * pDevice->cbRD), GFP_KERNEL); + if (pDevice->pRCBMem == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : alloc rx usb context failed\n", pDevice->dev->name); + goto free_tx; + } + + pDevice->FirstRecvFreeList = NULL; + pDevice->LastRecvFreeList = NULL; + pDevice->FirstRecvMngList = NULL; + pDevice->LastRecvMngList = NULL; + pDevice->NumRecvFreeList = 0; + pRCB = (PRCB) pDevice->pRCBMem; + + for (ii = 0; ii < pDevice->cbRD; ii++) { + + pDevice->apRCB[ii] = pRCB; + pRCB->pDevice = (void *) pDevice; + /* allocate URBs */ + pRCB->pUrb = usb_alloc_urb(0, GFP_ATOMIC); + + if (pRCB->pUrb == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx urb\n"); + goto free_rx_tx; + } + pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + if (pRCB->skb == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx skb\n"); + goto free_rx_tx; + } + pRCB->skb->dev = pDevice->dev; + pRCB->bBoolInUse = false; + EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB); + pDevice->NumRecvFreeList++; + pRCB++; + } + + pDevice->pControlURB = usb_alloc_urb(0, GFP_ATOMIC); + if (pDevice->pControlURB == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc control urb\n"); + goto free_rx_tx; + } + + pDevice->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC); + if (pDevice->pInterruptURB == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int urb\n"); + usb_free_urb(pDevice->pControlURB); + goto free_rx_tx; + } + + pDevice->intBuf.pDataBuf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL); + if (pDevice->intBuf.pDataBuf == NULL) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int buf\n"); + usb_free_urb(pDevice->pControlURB); + usb_free_urb(pDevice->pInterruptURB); + goto free_rx_tx; + } + + return true; + +free_rx_tx: + device_free_rx_bufs(pDevice); + +free_tx: + device_free_tx_bufs(pDevice); + + return false; +} + +static bool device_init_defrag_cb(struct vnt_private *pDevice) +{ + int i; + PSDeFragControlBlock pDeF; + + /* Init the fragment ctl entries */ + for (i = 0; i < CB_MAX_RX_FRAG; i++) { + pDeF = &(pDevice->sRxDFCB[i]); + if (!device_alloc_frag_buf(pDevice, pDeF)) { + DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc frag bufs\n", + pDevice->dev->name); + goto free_frag; + } + } + pDevice->cbDFCB = CB_MAX_RX_FRAG; + pDevice->cbFreeDFCB = pDevice->cbDFCB; + return true; + +free_frag: + device_free_frag_bufs(pDevice); + return false; +} + +static void device_free_frag_bufs(struct vnt_private *pDevice) +{ + PSDeFragControlBlock pDeF; + int i; + + for (i = 0; i < CB_MAX_RX_FRAG; i++) { + + pDeF = &(pDevice->sRxDFCB[i]); + + if (pDeF->skb) + dev_kfree_skb(pDeF->skb); + } +} + +int device_alloc_frag_buf(struct vnt_private *pDevice, + PSDeFragControlBlock pDeF) +{ + + pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + if (pDeF->skb == NULL) + return false; + ASSERT(pDeF->skb); + pDeF->skb->dev = pDevice->dev; + + return true; +} + +static int device_open(struct net_device *dev) +{ + struct vnt_private *pDevice = netdev_priv(dev); + + pDevice->fWPA_Authened = false; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_open...\n"); + + pDevice->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS; + + if (device_alloc_bufs(pDevice) == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_alloc_bufs fail... \n"); + return -ENOMEM; + } + + if (device_init_defrag_cb(pDevice)== false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Initial defragment cb fail \n"); + goto free_rx_tx; + } + + MP_CLEAR_FLAG(pDevice, fMP_DISCONNECTED); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); + MP_SET_FLAG(pDevice, fMP_POST_READS); + MP_SET_FLAG(pDevice, fMP_POST_WRITES); + + /* read config file */ + Read_config_file(pDevice); + + if (device_init_registers(pDevice, DEVICE_INIT_COLD) == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " init register fail\n"); + goto free_all; + } + + device_set_multi(pDevice->dev); + + /* init for key management */ + KeyvInitTable(pDevice,&pDevice->sKey); + memcpy(pDevice->vnt_mgmt.abyMACAddr, + pDevice->abyCurrentNetAddr, ETH_ALEN); + memcpy(pDevice->dev->dev_addr, pDevice->abyCurrentNetAddr, ETH_ALEN); + pDevice->bStopTx0Pkt = false; + pDevice->bStopDataPkt = false; + pDevice->bRoaming = false; + pDevice->bIsRoaming = false; + pDevice->bEnableRoaming = false; + if (pDevice->bDiversityRegCtlON) { + device_init_diversity_timer(pDevice); + } + + vMgrObjectInit(pDevice); + tasklet_init(&pDevice->RxMngWorkItem, (void *)RXvMngWorkItem, (unsigned long)pDevice); + tasklet_init(&pDevice->ReadWorkItem, (void *)RXvWorkItem, (unsigned long)pDevice); + tasklet_init(&pDevice->EventWorkItem, (void *)INTvWorkItem, (unsigned long)pDevice); + add_timer(&pDevice->vnt_mgmt.sTimerSecondCallback); + pDevice->int_interval = 100; /* max 100 microframes */ + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + + pDevice->bIsRxWorkItemQueued = true; + pDevice->fKillEventPollingThread = false; + pDevice->bEventAvailable = false; + + pDevice->bWPADEVUp = false; + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = false; + pDevice->bWPASuppWextEnabled = false; + pDevice->byReAssocCount = 0; + + RXvWorkItem(pDevice); + INTvWorkItem(pDevice); + + /* if WEP key already set by iwconfig but device not yet open */ + if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) { + spin_lock_irq(&pDevice->lock); + KeybSetDefaultKey( pDevice, + &(pDevice->sKey), + pDevice->byKeyIndex | (1 << 31), + pDevice->uKeyLength, + NULL, + pDevice->abyKey, + KEY_CTL_WEP + ); + spin_unlock_irq(&pDevice->lock); + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + } + + if (pDevice->vnt_mgmt.eConfigMode == WMAC_CONFIG_AP) + bScheduleCommand((void *) pDevice, WLAN_CMD_RUN_AP, NULL); + else + bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL); + + netif_stop_queue(pDevice->dev); + pDevice->flags |= DEVICE_FLAGS_OPENED; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success..\n"); + return 0; + +free_all: + device_free_frag_bufs(pDevice); +free_rx_tx: + device_free_rx_bufs(pDevice); + device_free_tx_bufs(pDevice); + device_free_int_bufs(pDevice); + usb_kill_urb(pDevice->pControlURB); + usb_kill_urb(pDevice->pInterruptURB); + usb_free_urb(pDevice->pControlURB); + usb_free_urb(pDevice->pInterruptURB); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open fail.. \n"); + return -ENOMEM; +} + +static int device_close(struct net_device *dev) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int uu; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close1\n"); + if (pDevice == NULL) + return -ENODEV; + + if (pDevice->bLinkPass) { + bScheduleCommand((void *) pDevice, WLAN_CMD_DISASSOCIATE, NULL); + mdelay(30); + } + + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pMgmt->bShareKeyAlgorithm = false; + pDevice->bEncryptionEnable = false; + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + spin_lock_irq(&pDevice->lock); + for (uu = 0; uu < MAX_KEY_TABLE; uu++) + MACvDisableKeyEntry(pDevice,uu); + spin_unlock_irq(&pDevice->lock); + + if ((pDevice->flags & DEVICE_FLAGS_UNPLUG) == false) { + MACbShutdown(pDevice); + } + netif_stop_queue(pDevice->dev); + MP_SET_FLAG(pDevice, fMP_DISCONNECTED); + MP_CLEAR_FLAG(pDevice, fMP_POST_WRITES); + MP_CLEAR_FLAG(pDevice, fMP_POST_READS); + pDevice->fKillEventPollingThread = true; + del_timer(&pDevice->sTimerCommand); + del_timer(&pMgmt->sTimerSecondCallback); + + del_timer(&pDevice->sTimerTxData); + + if (pDevice->bDiversityRegCtlON) { + del_timer(&pDevice->TimerSQ3Tmax1); + del_timer(&pDevice->TimerSQ3Tmax2); + del_timer(&pDevice->TimerSQ3Tmax3); + } + tasklet_kill(&pDevice->RxMngWorkItem); + tasklet_kill(&pDevice->ReadWorkItem); + tasklet_kill(&pDevice->EventWorkItem); + + pDevice->bRoaming = false; + pDevice->bIsRoaming = false; + pDevice->bEnableRoaming = false; + pDevice->bCmdRunning = false; + pDevice->bLinkPass = false; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + + pDevice->flags &= ~DEVICE_FLAGS_OPENED; + + device_free_tx_bufs(pDevice); + device_free_rx_bufs(pDevice); + device_free_int_bufs(pDevice); + device_free_frag_bufs(pDevice); + + usb_kill_urb(pDevice->pControlURB); + usb_kill_urb(pDevice->pInterruptURB); + usb_free_urb(pDevice->pControlURB); + usb_free_urb(pDevice->pInterruptURB); + + BSSvClearNodeDBTable(pDevice, 0); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close2 \n"); + + return 0; +} + +static void vt6656_disconnect(struct usb_interface *intf) +{ + struct vnt_private *device = usb_get_intfdata(intf); + + if (!device) + return; + + usb_set_intfdata(intf, NULL); + usb_put_dev(interface_to_usbdev(intf)); + + device->flags |= DEVICE_FLAGS_UNPLUG; + + if (device->dev) { + unregister_netdev(device->dev); + free_netdev(device->dev); + } + +} + +static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) +{ + struct vnt_private *pDevice = netdev_priv(dev); + + spin_lock_irq(&pDevice->lock); + + if (unlikely(pDevice->bStopTx0Pkt)) + dev_kfree_skb_irq(skb); + else + vDMA0_tx_80211(pDevice, skb); + + spin_unlock_irq(&pDevice->lock); + + return NETDEV_TX_OK; +} + +static int device_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct net_device_stats *stats = &pDevice->stats; + + spin_lock_irq(&pDevice->lock); + + netif_stop_queue(dev); + + if (!pDevice->bLinkPass) { + dev_kfree_skb_irq(skb); + goto out; + } + + if (pDevice->bStopDataPkt) { + dev_kfree_skb_irq(skb); + stats->tx_dropped++; + goto out; + } + + if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb)) { + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); + } + +out: + spin_unlock_irq(&pDevice->lock); + + return NETDEV_TX_OK; +} + +static unsigned const ethernet_polynomial = 0x04c11db7U; +static inline u32 ether_crc(int length, unsigned char *data) +{ + int crc = -1; + + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) { + crc = (crc << 1) ^ + ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); + } + } + return crc; +} + +/* find out the start position of str2 from str1 */ +static unsigned char *kstrstr(const unsigned char *str1, + const unsigned char *str2) { + int str1_len = strlen(str1); + int str2_len = strlen(str2); + + while (str1_len >= str2_len) { + str1_len--; + if(memcmp(str1,str2,str2_len)==0) + return (unsigned char *) str1; + str1++; + } + return NULL; +} + +static int Config_FileGetParameter(unsigned char *string, + unsigned char *dest, + unsigned char *source) +{ + unsigned char buf1[100]; + unsigned char buf2[100]; + unsigned char *start_p = NULL, *end_p = NULL, *tmp_p = NULL; + int ii; + + memset(buf1,0,100); + strcat(buf1, string); + strcat(buf1, "="); + source+=strlen(buf1); + + /* find target string start point */ + start_p = kstrstr(source,buf1); + if (start_p == NULL) + return false; + + /* check if current config line is marked by "#" */ + for (ii = 1; ; ii++) { + if (memcmp(start_p - ii, "\n", 1) == 0) + break; + if (memcmp(start_p - ii, "#", 1) == 0) + return false; + } + + /* find target string end point */ + end_p = kstrstr(start_p,"\n"); + if (end_p == NULL) { /* can't find "\n", but don't care */ + end_p = start_p + strlen(start_p); /* no include "\n" */ + } + + memset(buf2,0,100); + memcpy(buf2, start_p, end_p-start_p); /* get the target line */ + buf2[end_p-start_p]='\0'; + + /* find value */ + start_p = kstrstr(buf2,"="); + if (start_p == NULL) + return false; + memset(buf1,0,100); + strcpy(buf1,start_p+1); + + /* except space */ + tmp_p = buf1; + while(*tmp_p != 0x00) { + if(*tmp_p==' ') + tmp_p++; + else + break; + } + + memcpy(dest,tmp_p,strlen(tmp_p)); + return true; +} + +/* if read fails, return NULL, or return data pointer */ +static unsigned char *Config_FileOperation(struct vnt_private *pDevice) +{ + unsigned char *buffer = kmalloc(1024, GFP_KERNEL); + struct file *file; + + if (!buffer) { + printk("allocate mem for file fail?\n"); + return NULL; + } + + file = filp_open(CONFIG_PATH, O_RDONLY, 0); + if (IS_ERR(file)) { + kfree(buffer); + printk("Config_FileOperation file Not exist\n"); + return NULL; + } + + if (kernel_read(file, 0, buffer, 1024) < 0) { + printk("read file error?\n"); + kfree(buffer); + buffer = NULL; + } + + fput(file); + return buffer; +} + +/* return --->-1:fail; >=0:successful */ +static int Read_config_file(struct vnt_private *pDevice) +{ + int result = 0; + unsigned char tmpbuffer[100]; + unsigned char *buffer = NULL; + + /* init config setting */ + pDevice->config_file.ZoneType = -1; + pDevice->config_file.eAuthenMode = -1; + pDevice->config_file.eEncryptionStatus = -1; + + buffer = Config_FileOperation(pDevice); + if (buffer == NULL) { + result =-1; + return result; + } + +/* get zonetype */ +{ + memset(tmpbuffer,0,sizeof(tmpbuffer)); + if(Config_FileGetParameter("ZONETYPE",tmpbuffer,buffer) ==true) { + if(memcmp(tmpbuffer,"USA",3)==0) { + pDevice->config_file.ZoneType=ZoneType_USA; + } + else if(memcmp(tmpbuffer,"JAPAN",5)==0) { + pDevice->config_file.ZoneType=ZoneType_Japan; + } + else if(memcmp(tmpbuffer,"EUROPE",6)==0) { + pDevice->config_file.ZoneType=ZoneType_Europe; + } + else { + printk("Unknown Zonetype[%s]?\n",tmpbuffer); + } + } +} + +/* get other parameter */ + { + memset(tmpbuffer,0,sizeof(tmpbuffer)); + if(Config_FileGetParameter("AUTHENMODE",tmpbuffer,buffer)==true) { + pDevice->config_file.eAuthenMode = (int) simple_strtol(tmpbuffer, NULL, 10); + } + + memset(tmpbuffer,0,sizeof(tmpbuffer)); + if(Config_FileGetParameter("ENCRYPTIONMODE",tmpbuffer,buffer)==true) { + pDevice->config_file.eEncryptionStatus= (int) simple_strtol(tmpbuffer, NULL, 10); + } + } + + kfree(buffer); + return result; +} + +static void device_set_multi(struct net_device *dev) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct netdev_hw_addr *ha; + u32 mc_filter[2]; + int ii; + u8 pbyData[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 byTmpMode = 0; + int rc; + + spin_lock_irq(&pDevice->lock); + rc = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + MAC_REG_RCR, + MESSAGE_REQUEST_MACREG, + 1, + &byTmpMode + ); + if (rc == 0) pDevice->byRxMode = byTmpMode; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode in= %x\n", pDevice->byRxMode); + + if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ + DBG_PRT(MSG_LEVEL_ERR,KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); + /* unconditionally log net taps */ + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST); + } + else if ((netdev_mc_count(dev) > pDevice->multicast_limit) || + (dev->flags & IFF_ALLMULTI)) { + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + MAC_REG_MAR0, + MESSAGE_REQUEST_MACREG, + 8, + pbyData + ); + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + } + else { + memset(mc_filter, 0, sizeof(mc_filter)); + netdev_for_each_mc_addr(ha, dev) { + int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; + mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); + } + for (ii = 0; ii < 4; ii++) { + MACvWriteMultiAddr(pDevice, ii, *((u8 *)&mc_filter[0] + ii)); + MACvWriteMultiAddr(pDevice, ii+ 4, *((u8 *)&mc_filter[1] + ii)); + } + pDevice->byRxMode &= ~(RCR_UNICAST); + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + } + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + /* + * If AP mode, don't enable RCR_UNICAST since HW only compares + * addr1 with local MAC + */ + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + pDevice->byRxMode &= ~(RCR_UNICAST); + } + ControlvWriteByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_RCR, pDevice->byRxMode); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode out= %x\n", pDevice->byRxMode); + spin_unlock_irq(&pDevice->lock); + +} + +static struct net_device_stats *device_get_stats(struct net_device *dev) +{ + struct vnt_private *pDevice = netdev_priv(dev); + + return &pDevice->stats; +} + +static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct vnt_private *pDevice = netdev_priv(dev); + struct iwreq *wrq = (struct iwreq *) rq; + int rc = 0; + + switch (cmd) { + + case IOCTL_CMD_HOSTAPD: + + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) + rc = -EFAULT; + + rc = vt6656_hostap_ioctl(pDevice, &wrq->u.data); + break; + + case SIOCETHTOOL: + return ethtool_ioctl(dev, (void *) rq->ifr_data); + + } + + return rc; +} + +static int ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strncpy(info.driver, DEVICE_NAME, sizeof(info.driver)-1); + strncpy(info.version, DEVICE_VERSION, sizeof(info.version)-1); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + } + + return -EOPNOTSUPP; +} + +MODULE_DEVICE_TABLE(usb, vt6656_table); + +static struct usb_driver vt6656_driver = { + .name = DEVICE_NAME, + .probe = vt6656_probe, + .disconnect = vt6656_disconnect, + .id_table = vt6656_table, +#ifdef CONFIG_PM + .suspend = vt6656_suspend, + .resume = vt6656_resume, +#endif /* CONFIG_PM */ +}; + +module_usb_driver(vt6656_driver); diff --git a/drivers/staging/vt6656/mib.c b/drivers/staging/vt6656/mib.c new file mode 100644 index 00000000..12333cdc --- /dev/null +++ b/drivers/staging/vt6656/mib.c @@ -0,0 +1,489 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: mib.c + * + * Purpose: Implement MIB Data Structure + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * STAvUpdateIstStatCounter - Update ISR statistic counter + * STAvUpdateRDStatCounter - Update Rx statistic counter + * STAvUpdateTDStatCounter - Update Tx statistic counter + * STAvUpdateTDStatCounterEx - Update Tx statistic counter and copy tx data + * STAvUpdate802_11Counter - Update 802.11 mib counter + * + * Revision History: + * + */ + +#include "mac.h" +#include "tether.h" +#include "mib.h" +#include "wctl.h" +#include "baseband.h" + +static int msglevel =MSG_LEVEL_INFO; + +/* + * Description: Update Isr Statistic Counter + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * wisr - Interrupt status + * Out: + * none + * + * Return Value: none + * + */ +void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, u8 byIsr0, u8 byIsr1) +{ + /**********************/ + /* ABNORMAL interrupt */ + /**********************/ + // not any IMR bit invoke irq + if (byIsr0 == 0) { + pStatistic->ISRStat.dwIsrUnknown++; + return; + } + + if (byIsr0 & ISR_ACTX) // ISR, bit0 + pStatistic->ISRStat.dwIsrTx0OK++; // TXDMA0 successful + + if (byIsr0 & ISR_BNTX) // ISR, bit2 + pStatistic->ISRStat.dwIsrBeaconTxOK++; // BeaconTx successful + + if (byIsr0 & ISR_RXDMA0) // ISR, bit3 + pStatistic->ISRStat.dwIsrRx0OK++; // Rx0 successful + + if (byIsr0 & ISR_TBTT) // ISR, bit4 + pStatistic->ISRStat.dwIsrTBTTInt++; // TBTT successful + + if (byIsr0 & ISR_SOFTTIMER) // ISR, bit6 + pStatistic->ISRStat.dwIsrSTIMERInt++; + + if (byIsr0 & ISR_WATCHDOG) // ISR, bit7 + pStatistic->ISRStat.dwIsrWatchDog++; + + if (byIsr1 & ISR_FETALERR) // ISR, bit8 + pStatistic->ISRStat.dwIsrUnrecoverableError++; + + if (byIsr1 & ISR_SOFTINT) // ISR, bit9 + pStatistic->ISRStat.dwIsrSoftInterrupt++; // software interrupt + + if (byIsr1 & ISR_MIBNEARFULL) // ISR, bit10 + pStatistic->ISRStat.dwIsrMIBNearfull++; + + if (byIsr1 & ISR_RXNOBUF) // ISR, bit11 + pStatistic->ISRStat.dwIsrRxNoBuf++; // Rx No Buff + +} + +/* + * Description: Update Rx Statistic Counter + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * byRSR - Rx Status + * byNewRSR - Rx Status + * pbyBuffer - Rx Buffer + * cbFrameLength - Rx Length + * Out: + * none + * + * Return Value: none + * + */ +void STAvUpdateRDStatCounter(PSStatCounter pStatistic, + u8 byRSR, u8 byNewRSR, + u8 byRxSts, u8 byRxRate, + u8 * pbyBuffer, unsigned int cbFrameLength) +{ + /* need change */ + struct ieee80211_hdr *pHeader = (struct ieee80211_hdr *)pbyBuffer; + + if (byRSR & RSR_ADDROK) + pStatistic->dwRsrADDROk++; + if (byRSR & RSR_CRCOK) { + pStatistic->dwRsrCRCOk++; + pStatistic->ullRsrOK++; + + if (cbFrameLength >= ETH_ALEN) { + /* update counters in case of successful transmission */ + if (byRSR & RSR_ADDRBROAD) { + pStatistic->ullRxBroadcastFrames++; + pStatistic->ullRxBroadcastBytes += + (unsigned long long) cbFrameLength; + } + else if (byRSR & RSR_ADDRMULTI) { + pStatistic->ullRxMulticastFrames++; + pStatistic->ullRxMulticastBytes += + (unsigned long long) cbFrameLength; + } + else { + pStatistic->ullRxDirectedFrames++; + pStatistic->ullRxDirectedBytes += + (unsigned long long) cbFrameLength; + } + } + } + + if(byRxRate==22) { + pStatistic->CustomStat.ullRsr11M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr11MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "11M: ALL[%d], OK[%d]:[%02x]\n", + (signed int) pStatistic->CustomStat.ullRsr11M, + (signed int) pStatistic->CustomStat.ullRsr11MCRCOk, byRSR); + } + else if(byRxRate==11) { + pStatistic->CustomStat.ullRsr5M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr5MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 5M: ALL[%d], OK[%d]:[%02x]\n", + (signed int) pStatistic->CustomStat.ullRsr5M, + (signed int) pStatistic->CustomStat.ullRsr5MCRCOk, byRSR); + } + else if(byRxRate==4) { + pStatistic->CustomStat.ullRsr2M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr2MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 2M: ALL[%d], OK[%d]:[%02x]\n", + (signed int) pStatistic->CustomStat.ullRsr2M, + (signed int) pStatistic->CustomStat.ullRsr2MCRCOk, byRSR); + } + else if(byRxRate==2){ + pStatistic->CustomStat.ullRsr1M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr1MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 1M: ALL[%d], OK[%d]:[%02x]\n", + (signed int) pStatistic->CustomStat.ullRsr1M, + (signed int) pStatistic->CustomStat.ullRsr1MCRCOk, byRSR); + } + else if(byRxRate==12){ + pStatistic->CustomStat.ullRsr6M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr6MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 6M: ALL[%d], OK[%d]\n", + (signed int) pStatistic->CustomStat.ullRsr6M, + (signed int) pStatistic->CustomStat.ullRsr6MCRCOk); + } + else if(byRxRate==18){ + pStatistic->CustomStat.ullRsr9M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr9MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " 9M: ALL[%d], OK[%d]\n", + (signed int) pStatistic->CustomStat.ullRsr9M, + (signed int) pStatistic->CustomStat.ullRsr9MCRCOk); + } + else if(byRxRate==24){ + pStatistic->CustomStat.ullRsr12M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr12MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "12M: ALL[%d], OK[%d]\n", + (signed int) pStatistic->CustomStat.ullRsr12M, + (signed int) pStatistic->CustomStat.ullRsr12MCRCOk); + } + else if(byRxRate==36){ + pStatistic->CustomStat.ullRsr18M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr18MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "18M: ALL[%d], OK[%d]\n", + (signed int) pStatistic->CustomStat.ullRsr18M, + (signed int) pStatistic->CustomStat.ullRsr18MCRCOk); + } + else if(byRxRate==48){ + pStatistic->CustomStat.ullRsr24M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr24MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "24M: ALL[%d], OK[%d]\n", + (signed int) pStatistic->CustomStat.ullRsr24M, + (signed int) pStatistic->CustomStat.ullRsr24MCRCOk); + } + else if(byRxRate==72){ + pStatistic->CustomStat.ullRsr36M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr36MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "36M: ALL[%d], OK[%d]\n", + (signed int) pStatistic->CustomStat.ullRsr36M, + (signed int) pStatistic->CustomStat.ullRsr36MCRCOk); + } + else if(byRxRate==96){ + pStatistic->CustomStat.ullRsr48M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr48MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "48M: ALL[%d], OK[%d]\n", + (signed int) pStatistic->CustomStat.ullRsr48M, + (signed int) pStatistic->CustomStat.ullRsr48MCRCOk); + } + else if(byRxRate==108){ + pStatistic->CustomStat.ullRsr54M++; + if(byRSR & RSR_CRCOK) { + pStatistic->CustomStat.ullRsr54MCRCOk++; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "54M: ALL[%d], OK[%d]\n", + (signed int) pStatistic->CustomStat.ullRsr54M, + (signed int) pStatistic->CustomStat.ullRsr54MCRCOk); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "Unknown: Total[%d], CRCOK[%d]\n", + (signed int) pStatistic->dwRsrRxPacket+1, + (signed int)pStatistic->dwRsrCRCOk); + } + + if (byRSR & RSR_BSSIDOK) + pStatistic->dwRsrBSSIDOk++; + + if (byRSR & RSR_BCNSSIDOK) + pStatistic->dwRsrBCNSSIDOk++; + if (byRSR & RSR_IVLDLEN) //invalid len (> 2312 byte) + pStatistic->dwRsrLENErr++; + if (byRSR & RSR_IVLDTYP) //invalid packet type + pStatistic->dwRsrTYPErr++; + if ((byRSR & (RSR_IVLDTYP | RSR_IVLDLEN)) || !(byRSR & RSR_CRCOK)) + pStatistic->dwRsrErr++; + + if (byNewRSR & NEWRSR_DECRYPTOK) + pStatistic->dwNewRsrDECRYPTOK++; + if (byNewRSR & NEWRSR_CFPIND) + pStatistic->dwNewRsrCFP++; + if (byNewRSR & NEWRSR_HWUTSF) + pStatistic->dwNewRsrUTSF++; + if (byNewRSR & NEWRSR_BCNHITAID) + pStatistic->dwNewRsrHITAID++; + if (byNewRSR & NEWRSR_BCNHITAID0) + pStatistic->dwNewRsrHITAID0++; + + // increase rx packet count + pStatistic->dwRsrRxPacket++; + pStatistic->dwRsrRxOctet += cbFrameLength; + + if (IS_TYPE_DATA(pbyBuffer)) { + pStatistic->dwRsrRxData++; + } else if (IS_TYPE_MGMT(pbyBuffer)){ + pStatistic->dwRsrRxManage++; + } else if (IS_TYPE_CONTROL(pbyBuffer)){ + pStatistic->dwRsrRxControl++; + } + + if (byRSR & RSR_ADDRBROAD) + pStatistic->dwRsrBroadcast++; + else if (byRSR & RSR_ADDRMULTI) + pStatistic->dwRsrMulticast++; + else + pStatistic->dwRsrDirected++; + + if (WLAN_GET_FC_MOREFRAG(pHeader->frame_control)) + pStatistic->dwRsrRxFragment++; + + if (cbFrameLength < ETH_ZLEN + 4) { + pStatistic->dwRsrRunt++; + } else if (cbFrameLength == ETH_ZLEN + 4) { + pStatistic->dwRsrRxFrmLen64++; + } + else if ((65 <= cbFrameLength) && (cbFrameLength <= 127)) { + pStatistic->dwRsrRxFrmLen65_127++; + } + else if ((128 <= cbFrameLength) && (cbFrameLength <= 255)) { + pStatistic->dwRsrRxFrmLen128_255++; + } + else if ((256 <= cbFrameLength) && (cbFrameLength <= 511)) { + pStatistic->dwRsrRxFrmLen256_511++; + } + else if ((512 <= cbFrameLength) && (cbFrameLength <= 1023)) { + pStatistic->dwRsrRxFrmLen512_1023++; + } else if ((1024 <= cbFrameLength) && + (cbFrameLength <= ETH_FRAME_LEN + 4)) { + pStatistic->dwRsrRxFrmLen1024_1518++; + } else if (cbFrameLength > ETH_FRAME_LEN + 4) { + pStatistic->dwRsrLong++; + } +} + +/* + * Description: Update Tx Statistic Counter + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * byTSR0 - Tx Status + * byTSR1 - Tx Status + * pbyBuffer - Tx Buffer + * cbFrameLength - Tx Length + * uIdx - Index of Tx DMA + * Out: + * none + * + * Return Value: none + * + */ +void +STAvUpdateTDStatCounter ( + PSStatCounter pStatistic, + u8 byPktNum, + u8 byRate, + u8 byTSR + ) +{ + u8 byRetyCnt; + // increase tx packet count + pStatistic->dwTsrTxPacket++; + + byRetyCnt = (byTSR & 0xF0) >> 4; + if (byRetyCnt != 0) { + pStatistic->dwTsrRetry++; + pStatistic->dwTsrTotalRetry += byRetyCnt; + pStatistic->dwTxFail[byRate]+= byRetyCnt; + pStatistic->dwTxFail[MAX_RATE] += byRetyCnt; + + if ( byRetyCnt == 0x1) + pStatistic->dwTsrOnceRetry++; + else + pStatistic->dwTsrMoreThanOnceRetry++; + + if (byRetyCnt <= 8) + pStatistic->dwTxRetryCount[byRetyCnt-1]++; + + } + if ( !(byTSR & (TSR_TMO | TSR_RETRYTMO))) { + + if (byRetyCnt < 2) + pStatistic->TxNoRetryOkCount ++; + else + pStatistic->TxRetryOkCount ++; + + pStatistic->ullTsrOK++; + pStatistic->CustomStat.ullTsrAllOK++; + // update counters in case that successful transmit + pStatistic->dwTxOk[byRate]++; + pStatistic->dwTxOk[MAX_RATE]++; + + if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_BROAD ) { + pStatistic->ullTxBroadcastFrames++; + pStatistic->ullTxBroadcastBytes += pStatistic->abyTxPktInfo[byPktNum].wLength; + } else if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_MULTI ) { + pStatistic->ullTxMulticastFrames++; + pStatistic->ullTxMulticastBytes += pStatistic->abyTxPktInfo[byPktNum].wLength; + } else if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_UNI ) { + pStatistic->ullTxDirectedFrames++; + pStatistic->ullTxDirectedBytes += pStatistic->abyTxPktInfo[byPktNum].wLength; + } + } + else { + + pStatistic->TxFailCount ++; + + pStatistic->dwTsrErr++; + if (byTSR & TSR_RETRYTMO) + pStatistic->dwTsrRetryTimeout++; + if (byTSR & TSR_TMO) + pStatistic->dwTsrTransmitTimeout++; + } + + if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_BROAD ) { + pStatistic->dwTsrBroadcast++; + } else if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_MULTI ) { + pStatistic->dwTsrMulticast++; + } else if ( pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni == TX_PKT_UNI ) { + pStatistic->dwTsrDirected++; + } +} + +/* + * Description: Update 802.11 mib counter + * + * Parameters: + * In: + * p802_11Counter - Pointer to 802.11 mib counter + * pStatistic - Pointer to Statistic Counter Data Structure + * dwCounter - hardware counter for 802.11 mib + * Out: + * none + * + * Return Value: none + * + */ +void +STAvUpdate802_11Counter( + PSDot11Counters p802_11Counter, + PSStatCounter pStatistic, + u8 byRTSSuccess, + u8 byRTSFail, + u8 byACKFail, + u8 byFCSErr + ) +{ + //p802_11Counter->TransmittedFragmentCount + p802_11Counter->MulticastTransmittedFrameCount = + (unsigned long long) (pStatistic->dwTsrBroadcast + + pStatistic->dwTsrMulticast); + p802_11Counter->FailedCount = (unsigned long long) (pStatistic->dwTsrErr); + p802_11Counter->RetryCount = (unsigned long long) (pStatistic->dwTsrRetry); + p802_11Counter->MultipleRetryCount = + (unsigned long long) (pStatistic->dwTsrMoreThanOnceRetry); + //p802_11Counter->FrameDuplicateCount + p802_11Counter->RTSSuccessCount += (unsigned long long) byRTSSuccess; + p802_11Counter->RTSFailureCount += (unsigned long long) byRTSFail; + p802_11Counter->ACKFailureCount += (unsigned long long) byACKFail; + p802_11Counter->FCSErrorCount += (unsigned long long) byFCSErr; + //p802_11Counter->ReceivedFragmentCount + p802_11Counter->MulticastReceivedFrameCount = + (unsigned long long) (pStatistic->dwRsrBroadcast + + pStatistic->dwRsrMulticast); +} + +/* + * Description: Clear 802.11 mib counter + * + * Parameters: + * In: + * pUsbCounter - Pointer to USB mib counter + * ntStatus - URB status + * Out: + * none + * + * Return Value: none + * + */ + +void STAvUpdateUSBCounter(PSUSBCounter pUsbCounter, int ntStatus) +{ + +// if ( ntStatus == USBD_STATUS_CRC ) { + pUsbCounter->dwCrc++; +// } + +} diff --git a/drivers/staging/vt6656/mib.h b/drivers/staging/vt6656/mib.h new file mode 100644 index 00000000..35375325 --- /dev/null +++ b/drivers/staging/vt6656/mib.h @@ -0,0 +1,378 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: mib.h + * + * Purpose: Implement MIB Data Structure + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + +#ifndef __MIB_H__ +#define __MIB_H__ + +#include "tether.h" +#include "desc.h" + +// +// USB counter +// +typedef struct tagSUSBCounter { + u32 dwCrc; + +} SUSBCounter, *PSUSBCounter; + +// +// 802.11 counter +// + +typedef struct tagSDot11Counters { + /* unsigned long Length; // Length of structure */ + unsigned long long TransmittedFragmentCount; + unsigned long long MulticastTransmittedFrameCount; + unsigned long long FailedCount; + unsigned long long RetryCount; + unsigned long long MultipleRetryCount; + unsigned long long RTSSuccessCount; + unsigned long long RTSFailureCount; + unsigned long long ACKFailureCount; + unsigned long long FrameDuplicateCount; + unsigned long long ReceivedFragmentCount; + unsigned long long MulticastReceivedFrameCount; + unsigned long long FCSErrorCount; + unsigned long long TKIPLocalMICFailures; + unsigned long long TKIPRemoteMICFailures; + unsigned long long TKIPICVErrors; + unsigned long long TKIPReplays; + unsigned long long CCMPFormatErrors; + unsigned long long CCMPReplays; + unsigned long long CCMPDecryptErrors; + unsigned long long FourWayHandshakeFailures; + /* + * unsigned long long WEPUndecryptableCount; + * unsigned long long WEPICVErrorCount; + * unsigned long long DecryptSuccessCount; + * unsigned long long DecryptFailureCount; + */ +} SDot11Counters, *PSDot11Counters; + +// +// MIB2 counter +// +typedef struct tagSMib2Counter { + signed long ifIndex; + char ifDescr[256]; // max size 255 plus zero ending + // e.g. "interface 1" + signed long ifType; + signed long ifMtu; + u32 ifSpeed; + u8 ifPhysAddress[ETH_ALEN]; + signed long ifAdminStatus; + signed long ifOperStatus; + u32 ifLastChange; + u32 ifInOctets; + u32 ifInUcastPkts; + u32 ifInNUcastPkts; + u32 ifInDiscards; + u32 ifInErrors; + u32 ifInUnknownProtos; + u32 ifOutOctets; + u32 ifOutUcastPkts; + u32 ifOutNUcastPkts; + u32 ifOutDiscards; + u32 ifOutErrors; + u32 ifOutQLen; + u32 ifSpecific; +} SMib2Counter, *PSMib2Counter; + +// Value in the ifType entry +#define WIRELESSLANIEEE80211b 6 // + +// Value in the ifAdminStatus/ifOperStatus entry +#define UP 1 // +#define DOWN 2 // +#define TESTING 3 // + +// +// RMON counter +// +typedef struct tagSRmonCounter { + signed long etherStatsIndex; + u32 etherStatsDataSource; + u32 etherStatsDropEvents; + u32 etherStatsOctets; + u32 etherStatsPkts; + u32 etherStatsBroadcastPkts; + u32 etherStatsMulticastPkts; + u32 etherStatsCRCAlignErrors; + u32 etherStatsUndersizePkts; + u32 etherStatsOversizePkts; + u32 etherStatsFragments; + u32 etherStatsJabbers; + u32 etherStatsCollisions; + u32 etherStatsPkt64Octets; + u32 etherStatsPkt65to127Octets; + u32 etherStatsPkt128to255Octets; + u32 etherStatsPkt256to511Octets; + u32 etherStatsPkt512to1023Octets; + u32 etherStatsPkt1024to1518Octets; + u32 etherStatsOwners; + u32 etherStatsStatus; +} SRmonCounter, *PSRmonCounter; + +// +// Custom counter +// +typedef struct tagSCustomCounters { + unsigned long Length; + + unsigned long long ullTsrAllOK; + + unsigned long long ullRsr11M; + unsigned long long ullRsr5M; + unsigned long long ullRsr2M; + unsigned long long ullRsr1M; + + unsigned long long ullRsr11MCRCOk; + unsigned long long ullRsr5MCRCOk; + unsigned long long ullRsr2MCRCOk; + unsigned long long ullRsr1MCRCOk; + + unsigned long long ullRsr54M; + unsigned long long ullRsr48M; + unsigned long long ullRsr36M; + unsigned long long ullRsr24M; + unsigned long long ullRsr18M; + unsigned long long ullRsr12M; + unsigned long long ullRsr9M; + unsigned long long ullRsr6M; + + unsigned long long ullRsr54MCRCOk; + unsigned long long ullRsr48MCRCOk; + unsigned long long ullRsr36MCRCOk; + unsigned long long ullRsr24MCRCOk; + unsigned long long ullRsr18MCRCOk; + unsigned long long ullRsr12MCRCOk; + unsigned long long ullRsr9MCRCOk; + unsigned long long ullRsr6MCRCOk; + +} SCustomCounters, *PSCustomCounters; + +// +// Custom counter +// +typedef struct tagSISRCounters { + unsigned long Length; + + u32 dwIsrTx0OK; + u32 dwIsrAC0TxOK; + u32 dwIsrBeaconTxOK; + u32 dwIsrRx0OK; + u32 dwIsrTBTTInt; + u32 dwIsrSTIMERInt; + u32 dwIsrWatchDog; + u32 dwIsrUnrecoverableError; + u32 dwIsrSoftInterrupt; + u32 dwIsrMIBNearfull; + u32 dwIsrRxNoBuf; + + u32 dwIsrUnknown; // unknown interrupt count + + u32 dwIsrRx1OK; + u32 dwIsrATIMTxOK; + u32 dwIsrSYNCTxOK; + u32 dwIsrCFPEnd; + u32 dwIsrATIMEnd; + u32 dwIsrSYNCFlushOK; + u32 dwIsrSTIMER1Int; + ///////////////////////////////////// +} SISRCounters, *PSISRCounters; + +// Value in the etherStatsStatus entry +#define VALID 1 // +#define CREATE_REQUEST 2 // +#define UNDER_CREATION 3 // +#define INVALID 4 // + +// +// Tx packet information +// +typedef struct tagSTxPktInfo { + u8 byBroadMultiUni; + u16 wLength; + u16 wFIFOCtl; + u8 abyDestAddr[ETH_ALEN]; +} STxPktInfo, *PSTxPktInfo; + +#define MAX_RATE 12 +// +// statistic counter +// +typedef struct tagSStatCounter { + // + // ISR status count + // + + SISRCounters ISRStat; + + // RSR status count + // + u32 dwRsrFrmAlgnErr; + u32 dwRsrErr; + u32 dwRsrCRCErr; + u32 dwRsrCRCOk; + u32 dwRsrBSSIDOk; + u32 dwRsrADDROk; + u32 dwRsrBCNSSIDOk; + u32 dwRsrLENErr; + u32 dwRsrTYPErr; + + u32 dwNewRsrDECRYPTOK; + u32 dwNewRsrCFP; + u32 dwNewRsrUTSF; + u32 dwNewRsrHITAID; + u32 dwNewRsrHITAID0; + + u32 dwRsrLong; + u32 dwRsrRunt; + + u32 dwRsrRxControl; + u32 dwRsrRxData; + u32 dwRsrRxManage; + + u32 dwRsrRxPacket; + u32 dwRsrRxOctet; + u32 dwRsrBroadcast; + u32 dwRsrMulticast; + u32 dwRsrDirected; + // 64-bit OID + unsigned long long ullRsrOK; + + // for some optional OIDs (64 bits) and DMI support + unsigned long long ullRxBroadcastBytes; + unsigned long long ullRxMulticastBytes; + unsigned long long ullRxDirectedBytes; + unsigned long long ullRxBroadcastFrames; + unsigned long long ullRxMulticastFrames; + unsigned long long ullRxDirectedFrames; + + u32 dwRsrRxFragment; + u32 dwRsrRxFrmLen64; + u32 dwRsrRxFrmLen65_127; + u32 dwRsrRxFrmLen128_255; + u32 dwRsrRxFrmLen256_511; + u32 dwRsrRxFrmLen512_1023; + u32 dwRsrRxFrmLen1024_1518; + + // TSR status count + // + u32 dwTsrTotalRetry; // total collision retry count + u32 dwTsrOnceRetry; // this packet only occur one collision + u32 dwTsrMoreThanOnceRetry; // this packet occur more than one collision + u32 dwTsrRetry; // this packet has ever occur collision, + // that is (dwTsrOnceCollision0 + dwTsrMoreThanOnceCollision0) + u32 dwTsrACKData; + u32 dwTsrErr; + u32 dwAllTsrOK; + u32 dwTsrRetryTimeout; + u32 dwTsrTransmitTimeout; + + u32 dwTsrTxPacket; + u32 dwTsrTxOctet; + u32 dwTsrBroadcast; + u32 dwTsrMulticast; + u32 dwTsrDirected; + + // RD/TD count + u32 dwCntRxFrmLength; + u32 dwCntTxBufLength; + + u8 abyCntRxPattern[16]; + u8 abyCntTxPattern[16]; + + // Software check.... + u32 dwCntRxDataErr; // rx buffer data software compare CRC err count + u32 dwCntDecryptErr; // rx buffer data software compare CRC err count + u32 dwCntRxICVErr; // rx buffer data software compare CRC err count + + // 64-bit OID + unsigned long long ullTsrOK; + + // for some optional OIDs (64 bits) and DMI support + unsigned long long ullTxBroadcastFrames; + unsigned long long ullTxMulticastFrames; + unsigned long long ullTxDirectedFrames; + unsigned long long ullTxBroadcastBytes; + unsigned long long ullTxMulticastBytes; + unsigned long long ullTxDirectedBytes; + + // for autorate + u32 dwTxOk[MAX_RATE+1]; + u32 dwTxFail[MAX_RATE+1]; + u32 dwTxRetryCount[8]; + + STxPktInfo abyTxPktInfo[16]; + + SUSBCounter USB_EP0Stat; + SUSBCounter USB_BulkInStat; + SUSBCounter USB_BulkOutStat; + SUSBCounter USB_InterruptStat; + + SCustomCounters CustomStat; + + //Tx count: + unsigned long TxNoRetryOkCount; /* success tx no retry ! */ + unsigned long TxRetryOkCount; /* success tx but retry ! */ + unsigned long TxFailCount; /* fail tx ? */ + //Rx count: + unsigned long RxOkCnt; /* success rx ! */ + unsigned long RxFcsErrCnt; /* fail rx ? */ + //statistic + unsigned long SignalStren; + unsigned long LinkQuality; + +} SStatCounter, *PSStatCounter; + +void STAvUpdateIsrStatCounter(PSStatCounter pStatistic, + u8 byIsr0, + u8 byIsr1); + +void STAvUpdateRDStatCounter(PSStatCounter pStatistic, + u8 byRSR, u8 byNewRSR, u8 byRxSts, + u8 byRxRate, u8 * pbyBuffer, + unsigned int cbFrameLength); + +void STAvUpdateTDStatCounter(PSStatCounter pStatistic, u8 byPktNum, + u8 byRate, u8 byTSR); + +void +STAvUpdate802_11Counter( + PSDot11Counters p802_11Counter, + PSStatCounter pStatistic, + u8 byRTSSuccess, + u8 byRTSFail, + u8 byACKFail, + u8 byFCSErr + ); + +void STAvUpdateUSBCounter(PSUSBCounter pUsbCounter, int ntStatus); + +#endif /* __MIB_H__ */ diff --git a/drivers/staging/vt6656/michael.c b/drivers/staging/vt6656/michael.c new file mode 100644 index 00000000..9a5a0b67 --- /dev/null +++ b/drivers/staging/vt6656/michael.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: michael.cpp + * + * Purpose: The implementation of LIST data structure. + * + * Author: Kyle Hsu + * + * Date: Sep 4, 2002 + * + * Functions: + * s_dwGetUINT32 - Convert from u8[] to u32 in a portable way + * s_vPutUINT32 - Convert from u32 to u8[] in a portable way + * s_vClear - Reset the state to the empty message. + * s_vSetKey - Set the key. + * MIC_vInit - Set the key. + * s_vAppendByte - Append the byte to our word-sized buffer. + * MIC_vAppend - call s_vAppendByte. + * MIC_vGetMIC - Append the minimum padding and call s_vAppendByte. + * + * Revision History: + * + */ + +#include "tmacro.h" +#include "michael.h" + +/* + * static u32 s_dwGetUINT32(u8 * p); Get u32 from + * 4 bytes LSByte first + * static void s_vPutUINT32(u8* p, u32 val); Put u32 into + * 4 bytes LSByte first + */ +static void s_vClear(void); /* Clear the internal message, + * resets the object to the + * state just after construction. */ +static void s_vSetKey(u32 dwK0, u32 dwK1); +static void s_vAppendByte(u8 b); /* Add a single byte to the internal + * message */ + +static u32 L, R; /* Current state */ +static u32 K0, K1; /* Key */ +static u32 M; /* Message accumulator (single word) */ +static unsigned int nBytesInM; /* # bytes in M */ + +/* +static u32 s_dwGetUINT32 (u8 * p) +// Convert from u8[] to u32 in a portable way +{ + u32 res = 0; + unsigned int i; + for (i = 0; i < 4; i++) + res |= (*p++) << (8*i); + return res; +} + +static void s_vPutUINT32(u8 *p, u32 val) +// Convert from u32 to u8[] in a portable way +{ + unsigned int i; + for (i = 0; i < 4; i++) { + *p++ = (u8) (val & 0xff); + val >>= 8; + } +} +*/ + +static void s_vClear(void) +{ + /* Reset the state to the empty message. */ + L = K0; + R = K1; + nBytesInM = 0; + M = 0; +} + +static void s_vSetKey(u32 dwK0, u32 dwK1) +{ + /* Set the key */ + K0 = dwK0; + K1 = dwK1; + /* and reset the message */ + s_vClear(); +} + +static void s_vAppendByte(u8 b) +{ + /* Append the byte to our word-sized buffer */ + M |= b << (8*nBytesInM); + nBytesInM++; + /* Process the word if it is full. */ + if (nBytesInM >= 4) { + L ^= M; + R ^= ROL32(L, 17); + L += R; + R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8); + L += R; + R ^= ROL32(L, 3); + L += R; + R ^= ROR32(L, 2); + L += R; + /* Clear the buffer */ + M = 0; + nBytesInM = 0; + } +} + +void MIC_vInit(u32 dwK0, u32 dwK1) +{ + /* Set the key */ + s_vSetKey(dwK0, dwK1); +} + +void MIC_vUnInit(void) +{ + /* Wipe the key material */ + K0 = 0; + K1 = 0; + + /* And the other fields as well. */ + /* Note that this sets (L,R) to (K0,K1) which is just fine. */ + s_vClear(); +} + +void MIC_vAppend(u8 * src, unsigned int nBytes) +{ + /* This is simple */ + while (nBytes > 0) { + s_vAppendByte(*src++); + nBytes--; + } +} + +void MIC_vGetMIC(u32 * pdwL, u32 * pdwR) +{ + /* Append the minimum padding */ + s_vAppendByte(0x5a); + s_vAppendByte(0); + s_vAppendByte(0); + s_vAppendByte(0); + s_vAppendByte(0); + /* and then zeroes until the length is a multiple of 4 */ + while (nBytesInM != 0) + s_vAppendByte(0); + /* The s_vAppendByte function has already computed the result. */ + *pdwL = L; + *pdwR = R; + /* Reset to the empty message. */ + s_vClear(); +} diff --git a/drivers/staging/vt6656/michael.h b/drivers/staging/vt6656/michael.h new file mode 100644 index 00000000..9c69a426 --- /dev/null +++ b/drivers/staging/vt6656/michael.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: Michael.h + * + * Purpose: Reference implementation for Michael + * written by Niels Ferguson + * + * Author: Kyle Hsu + * + * Date: Jan 2, 2003 + * + */ + +#ifndef __MICHAEL_H__ +#define __MICHAEL_H__ + +#include <linux/types.h> + +void MIC_vInit(u32 dwK0, u32 dwK1); + +void MIC_vUnInit(void); + +// Append bytes to the message to be MICed +void MIC_vAppend(u8 * src, unsigned int nBytes); + +// Get the MIC result. Destination should accept 8 bytes of result. +// This also resets the message to empty. +void MIC_vGetMIC(u32 * pdwL, u32 * pdwR); + +// Rotation functions on 32 bit values +#define ROL32(A, n) \ + (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) +#define ROR32(A, n) ROL32((A), 32-(n)) + +#endif /* __MICHAEL_H__ */ diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c new file mode 100644 index 00000000..edc8975b --- /dev/null +++ b/drivers/staging/vt6656/power.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: power.c + * + * Purpose: Handles 802.11 power management functions + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + * Functions: + * PSvEnablePowerSaving - Enable Power Saving Mode + * PSvDiasblePowerSaving - Disable Power Saving Mode + * PSbConsiderPowerDown - Decide if we can Power Down + * PSvSendPSPOLL - Send PS-POLL packet + * PSbSendNullPacket - Send Null packet + * PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon + * + * Revision History: + * + */ + +#include "mac.h" +#include "device.h" +#include "wmgr.h" +#include "power.h" +#include "wcmd.h" +#include "rxtx.h" +#include "card.h" +#include "control.h" +#include "rndis.h" + +static int msglevel = MSG_LEVEL_INFO; + +/* + * + * Routine Description: + * Enable hw power saving functions + * + * Return Value: + * None. + * + */ + +void PSvEnablePowerSaving(struct vnt_private *pDevice, u16 wListenInterval) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u16 wAID = pMgmt->wCurrAID | BIT14 | BIT15; + + /* set period of power up before TBTT */ + MACvWriteWord(pDevice, MAC_REG_PWBT, C_PWBT); + + if (pDevice->eOPMode != OP_MODE_ADHOC) { + /* set AID */ + MACvWriteWord(pDevice, MAC_REG_AIDATIM, wAID); + } else { + /* set ATIM Window */ + /* MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); */ + } + + /* Warren:06-18-2004,the sequence must follow PSEN->AUTOSLEEP->GO2DOZE */ + /* enable power saving hw function */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_PSEN); + + /* Set AutoSleep */ + MACvRegBitsOn(pDevice, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + + /* Warren:MUST turn on this once before turn on AUTOSLEEP ,or the AUTOSLEEP doesn't work */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_GO2DOZE); + + if (wListenInterval >= 2) { + + /* clear always listen beacon */ + MACvRegBitsOff(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN); + + /* first time set listen next beacon */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN); + + pMgmt->wCountToWakeUp = wListenInterval; + + } else { + + /* always listen beacon */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN); + + pMgmt->wCountToWakeUp = 0; + } + + pDevice->bEnablePSMode = true; + + /* We don't send null pkt in ad hoc mode since beacon will handle this. */ + if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) + PSbSendNullPacket(pDevice); + + pDevice->bPWBitOn = true; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS:Power Saving Mode Enable...\n"); +} + +/* + * + * Routine Description: + * Disable hw power saving functions + * + * Return Value: + * None. + * + */ + +void PSvDisablePowerSaving(struct vnt_private *pDevice) +{ + + /* disable power saving hw function */ + CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_DISABLE_PS, 0, + 0, 0, NULL); + + /* clear AutoSleep */ + MACvRegBitsOff(pDevice, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + + /* set always listen beacon */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN); + pDevice->bEnablePSMode = false; + + if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) + PSbSendNullPacket(pDevice); + + pDevice->bPWBitOn = false; +} + +/* + * + * Routine Description: + * Consider to power down when no more packets to tx or rx. + * + * Return Value: + * true, if power down success + * false, if fail + */ + +int PSbConsiderPowerDown(struct vnt_private *pDevice, int bCheckRxDMA, + int bCheckCountToWakeUp) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u8 byData; + + /* check if already in Doze mode */ + ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG, + MAC_REG_PSCTL, &byData); + + if ((byData & PSCTL_PS) != 0) + return true; + + if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) { + /* check if in TIM wake period */ + if (pMgmt->bInTIMWake) + return false; + } + + /* check scan state */ + if (pDevice->bCmdRunning) + return false; + + /* Tx Burst */ + if (pDevice->bPSModeTxBurst) + return false; + + /* Froce PSEN on */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_PSEN); + + if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) { + if (bCheckCountToWakeUp && (pMgmt->wCountToWakeUp == 0 + || pMgmt->wCountToWakeUp == 1)) { + return false; + } + } + + pDevice->bPSRxBeacon = true; + + /* no Tx, no Rx isr, now go to Doze */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_GO2DOZE); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Go to Doze ZZZZZZZZZZZZZZZ\n"); + return true; +} + +/* + * + * Routine Description: + * Send PS-POLL packet + * + * Return Value: + * None. + * + */ + +void PSvSendPSPOLL(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct vnt_tx_mgmt *pTxPacket = NULL; + + memset(pMgmt->pbyPSPacketPool, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_HDR_ADDR2_LEN); + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyPSPacketPool; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + + pTxPacket->p80211Header->sA2.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_CTL) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PSPOLL) | + WLAN_SET_FC_PWRMGT(0) + )); + + pTxPacket->p80211Header->sA2.wDurationID = pMgmt->wCurrAID | BIT14 | BIT15; + memcpy(pTxPacket->p80211Header->sA2.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + memcpy(pTxPacket->p80211Header->sA2.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + pTxPacket->cbMPDULen = WLAN_HDR_ADDR2_LEN; + pTxPacket->cbPayloadLen = 0; + + /* log failure if sending failed */ + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet failed..\n"); + } +} + +/* + * + * Routine Description: + * Send NULL packet to AP for notification power state of STA + * + * Return Value: + * None. + * + */ + +int PSbSendNullPacket(struct vnt_private *pDevice) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u16 flags = 0; + + if (pDevice->bLinkPass == false) + return false; + + if ((pDevice->bEnablePSMode == false) && + (pDevice->fTxDataInSleep == false)) { + return false; + } + + memset(pMgmt->pbyPSPacketPool, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_NULLDATA_FR_MAXLEN); + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyPSPacketPool; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + + flags = WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL); + + if (pDevice->bEnablePSMode) + flags |= WLAN_SET_FC_PWRMGT(1); + else + flags |= WLAN_SET_FC_PWRMGT(0); + + pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16(flags); + + if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) + pTxPacket->p80211Header->sA3.wFrameCtl |= cpu_to_le16((u16)WLAN_SET_FC_TODS(1)); + + memcpy(pTxPacket->p80211Header->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + memcpy(pTxPacket->p80211Header->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy(pTxPacket->p80211Header->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + pTxPacket->cbMPDULen = WLAN_HDR_ADDR3_LEN; + pTxPacket->cbPayloadLen = 0; + /* log error if sending failed */ + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Null Packet failed !\n"); + return false; + } + return true; +} + +/* + * + * Routine Description: + * Check if Next TBTT must wake up + * + * Return Value: + * None. + * + */ + +int PSbIsNextTBTTWakeUp(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int bWakeUp = false; + + if (pMgmt->wListenInterval >= 2) { + if (pMgmt->wCountToWakeUp == 0) + pMgmt->wCountToWakeUp = pMgmt->wListenInterval; + + pMgmt->wCountToWakeUp--; + + if (pMgmt->wCountToWakeUp == 1) { + /* Turn on wake up to listen next beacon */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN); + pDevice->bPSRxBeacon = false; + bWakeUp = true; + } else if (!pDevice->bPSRxBeacon) { + /* Listen until RxBeacon */ + MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN); + } + } + return bWakeUp; +} + diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h new file mode 100644 index 00000000..77835823 --- /dev/null +++ b/drivers/staging/vt6656/power.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: power.h + * + * Purpose: Handles 802.11 power management functions + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + */ + +#ifndef __POWER_H__ +#define __POWER_H__ + +#define C_PWBT 1000 // micro sec. power up before TBTT +#define PS_FAST_INTERVAL 1 // Fast power saving listen interval +#define PS_MAX_INTERVAL 4 // MAX power saving listen interval + +/* PSDevice pDevice */ +/* PSDevice hDeviceContext */ + +int PSbConsiderPowerDown(struct vnt_private *, int bCheckRxDMA, + int bCheckCountToWakeUp); +void PSvDisablePowerSaving(struct vnt_private *); +void PSvEnablePowerSaving(struct vnt_private *, u16 wListenInterval); +void PSvSendPSPOLL(struct vnt_private *); +int PSbSendNullPacket(struct vnt_private *); +int PSbIsNextTBTTWakeUp(struct vnt_private *); + +#endif /* __POWER_H__ */ diff --git a/drivers/staging/vt6656/rc4.c b/drivers/staging/vt6656/rc4.c new file mode 100644 index 00000000..2fd836f0 --- /dev/null +++ b/drivers/staging/vt6656/rc4.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: rc4.c + * + * Purpose: + * + * Functions: + * + * Revision History: + * + * Author: Kyle Hsu + * + * Date: Sep 4, 2002 + * + */ + +#include "rc4.h" + +void rc4_init(PRC4Ext pRC4, u8 * pbyKey, unsigned int cbKey_len) +{ + unsigned int ust1, ust2; + unsigned int keyindex; + unsigned int stateindex; + u8 * pbyst; + unsigned int idx; + + pbyst = pRC4->abystate; + pRC4->ux = 0; + pRC4->uy = 0; + for (idx = 0; idx < 256; idx++) + pbyst[idx] = (u8)idx; + keyindex = 0; + stateindex = 0; + for (idx = 0; idx < 256; idx++) { + ust1 = pbyst[idx]; + stateindex = (stateindex + pbyKey[keyindex] + ust1) & 0xff; + ust2 = pbyst[stateindex]; + pbyst[stateindex] = (u8)ust1; + pbyst[idx] = (u8)ust2; + if (++keyindex >= cbKey_len) + keyindex = 0; + } +} + +unsigned int rc4_byte(PRC4Ext pRC4) +{ + unsigned int ux; + unsigned int uy; + unsigned int ustx, usty; + u8 * pbyst; + + pbyst = pRC4->abystate; + ux = (pRC4->ux + 1) & 0xff; + ustx = pbyst[ux]; + uy = (ustx + pRC4->uy) & 0xff; + usty = pbyst[uy]; + pRC4->ux = ux; + pRC4->uy = uy; + pbyst[uy] = (u8)ustx; + pbyst[ux] = (u8)usty; + + return pbyst[(ustx + usty) & 0xff]; +} + +void rc4_encrypt(PRC4Ext pRC4, u8 * pbyDest, + u8 * pbySrc, unsigned int cbData_len) +{ + unsigned int ii; + for (ii = 0; ii < cbData_len; ii++) + pbyDest[ii] = (u8)(pbySrc[ii] ^ rc4_byte(pRC4)); +} diff --git a/drivers/staging/vt6656/rc4.h b/drivers/staging/vt6656/rc4.h new file mode 100644 index 00000000..d376e1ad --- /dev/null +++ b/drivers/staging/vt6656/rc4.h @@ -0,0 +1,46 @@ +/* + * File: rc4.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Purpose: + * + * Functions: + * + * Revision History: + * + * Author: Kyle Hsu + * + * Date: Sep 4, 2002 + * + */ + +#ifndef __RC4_H__ +#define __RC4_H__ + +#include <linux/types.h> + +typedef struct { + unsigned int ux; + unsigned int uy; + u8 abystate[256]; +} RC4Ext, *PRC4Ext; + +void rc4_init(PRC4Ext pRC4, u8 * pbyKey, unsigned int cbKey_len); +unsigned int rc4_byte(PRC4Ext pRC4); +void rc4_encrypt(PRC4Ext pRC4, u8 * pbyDest, u8 * pbySrc, + unsigned int cbData_len); + +#endif /* __RC4_H__ */ diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c new file mode 100644 index 00000000..44cfe0b1 --- /dev/null +++ b/drivers/staging/vt6656/rf.c @@ -0,0 +1,1099 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: rf.c + * + * Purpose: rf function code + * + * Author: Jerry Chen + * + * Date: Feb. 19, 2004 + * + * Functions: + * IFRFbWriteEmbedded - Embedded write RF register via MAC + * + * Revision History: + * + */ + +#include "mac.h" +#include "rf.h" +#include "baseband.h" +#include "control.h" +#include "rndis.h" +#include "datarate.h" + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; +#define BY_AL2230_REG_LEN 23 //24bit +#define CB_AL2230_INIT_SEQ 15 +#define AL2230_PWR_IDX_LEN 64 + +#define BY_AL7230_REG_LEN 23 //24bit +#define CB_AL7230_INIT_SEQ 16 +#define AL7230_PWR_IDX_LEN 64 + +//{{RobertYu:20051111 +#define BY_VT3226_REG_LEN 23 +#define CB_VT3226_INIT_SEQ 11 +#define VT3226_PWR_IDX_LEN 64 +//}} + +//{{RobertYu:20060609 +#define BY_VT3342_REG_LEN 23 +#define CB_VT3342_INIT_SEQ 13 +#define VT3342_PWR_IDX_LEN 64 +//}} + +u8 abyAL2230InitTable[CB_AL2230_INIT_SEQ][3] = { + {0x03, 0xF7, 0x90}, + {0x03, 0x33, 0x31}, + {0x01, 0xB8, 0x02}, + {0x00, 0xFF, 0xF3}, + {0x00, 0x05, 0xA4}, + {0x0F, 0x4D, 0xC5}, //RobertYu:20060814 + {0x08, 0x05, 0xB6}, + {0x01, 0x47, 0xC7}, + {0x00, 0x06, 0x88}, + {0x04, 0x03, 0xB9}, + {0x00, 0xDB, 0xBA}, + {0x00, 0x09, 0x9B}, + {0x0B, 0xDF, 0xFC}, + {0x00, 0x00, 0x0D}, + {0x00, 0x58, 0x0F} + }; + +u8 abyAL2230ChannelTable0[CB_MAX_CHANNEL_24G][3] = { + {0x03, 0xF7, 0x90}, // channel = 1, Tf = 2412MHz + {0x03, 0xF7, 0x90}, // channel = 2, Tf = 2417MHz + {0x03, 0xE7, 0x90}, // channel = 3, Tf = 2422MHz + {0x03, 0xE7, 0x90}, // channel = 4, Tf = 2427MHz + {0x03, 0xF7, 0xA0}, // channel = 5, Tf = 2432MHz + {0x03, 0xF7, 0xA0}, // channel = 6, Tf = 2437MHz + {0x03, 0xE7, 0xA0}, // channel = 7, Tf = 2442MHz + {0x03, 0xE7, 0xA0}, // channel = 8, Tf = 2447MHz + {0x03, 0xF7, 0xB0}, // channel = 9, Tf = 2452MHz + {0x03, 0xF7, 0xB0}, // channel = 10, Tf = 2457MHz + {0x03, 0xE7, 0xB0}, // channel = 11, Tf = 2462MHz + {0x03, 0xE7, 0xB0}, // channel = 12, Tf = 2467MHz + {0x03, 0xF7, 0xC0}, // channel = 13, Tf = 2472MHz + {0x03, 0xE7, 0xC0} // channel = 14, Tf = 2412M + }; + +u8 abyAL2230ChannelTable1[CB_MAX_CHANNEL_24G][3] = { + {0x03, 0x33, 0x31}, // channel = 1, Tf = 2412MHz + {0x0B, 0x33, 0x31}, // channel = 2, Tf = 2417MHz + {0x03, 0x33, 0x31}, // channel = 3, Tf = 2422MHz + {0x0B, 0x33, 0x31}, // channel = 4, Tf = 2427MHz + {0x03, 0x33, 0x31}, // channel = 5, Tf = 2432MHz + {0x0B, 0x33, 0x31}, // channel = 6, Tf = 2437MHz + {0x03, 0x33, 0x31}, // channel = 7, Tf = 2442MHz + {0x0B, 0x33, 0x31}, // channel = 8, Tf = 2447MHz + {0x03, 0x33, 0x31}, // channel = 9, Tf = 2452MHz + {0x0B, 0x33, 0x31}, // channel = 10, Tf = 2457MHz + {0x03, 0x33, 0x31}, // channel = 11, Tf = 2462MHz + {0x0B, 0x33, 0x31}, // channel = 12, Tf = 2467MHz + {0x03, 0x33, 0x31}, // channel = 13, Tf = 2472MHz + {0x06, 0x66, 0x61} // channel = 14, Tf = 2412M + }; + +// 40MHz reference frequency +// Need to Pull PLLON(PE3) low when writing channel registers through 3-wire. +u8 abyAL7230InitTable[CB_AL7230_INIT_SEQ][3] = { + {0x20, 0x37, 0x90}, // Channel1 // Need modify for 11a + {0x13, 0x33, 0x31}, // Channel1 // Need modify for 11a + {0x84, 0x1F, 0xF2}, // Need modify for 11a: 451FE2 + {0x3F, 0xDF, 0xA3}, // Need modify for 11a: 5FDFA3 + {0x7F, 0xD7, 0x84}, // 11b/g // Need modify for 11a + //0x802B4500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B45 + // RoberYu:20050113, Rev0.47 Regsiter Setting Guide + {0x80, 0x2B, 0x55}, // Need modify for 11a: 8D1B55 + {0x56, 0xAF, 0x36}, + {0xCE, 0x02, 0x07}, // Need modify for 11a: 860207 + {0x6E, 0xBC, 0x98}, + {0x22, 0x1B, 0xB9}, + {0xE0, 0x00, 0x0A}, // Need modify for 11a: E0600A + {0x08, 0x03, 0x1B}, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) + //0x00093C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C + // RoberYu:20050113, Rev0.47 Regsiter Setting Guide + {0x00, 0x0A, 0x3C}, // Need modify for 11a: 00143C + {0xFF, 0xFF, 0xFD}, + {0x00, 0x00, 0x0E}, + {0x1A, 0xBA, 0x8F} // Need modify for 11a: 12BACF + }; + +u8 abyAL7230InitTableAMode[CB_AL7230_INIT_SEQ][3] = { + {0x2F, 0xF5, 0x20}, // Channel184 // Need modify for 11b/g + {0x00, 0x00, 0x01}, // Channel184 // Need modify for 11b/g + {0x45, 0x1F, 0xE2}, // Need modify for 11b/g + {0x5F, 0xDF, 0xA3}, // Need modify for 11b/g + {0x6F, 0xD7, 0x84}, // 11a // Need modify for 11b/g + {0x85, 0x3F, 0x55}, // Need modify for 11b/g, RoberYu:20050113 + {0x56, 0xAF, 0x36}, + {0xCE, 0x02, 0x07}, // Need modify for 11b/g + {0x6E, 0xBC, 0x98}, + {0x22, 0x1B, 0xB9}, + {0xE0, 0x60, 0x0A}, // Need modify for 11b/g + {0x08, 0x03, 0x1B}, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) + {0x00, 0x14, 0x7C}, // Need modify for 11b/g + {0xFF, 0xFF, 0xFD}, + {0x00, 0x00, 0x0E}, + {0x12, 0xBA, 0xCF} // Need modify for 11b/g + }; + +u8 abyAL7230ChannelTable0[CB_MAX_CHANNEL][3] = { + {0x20, 0x37, 0x90}, // channel = 1, Tf = 2412MHz + {0x20, 0x37, 0x90}, // channel = 2, Tf = 2417MHz + {0x20, 0x37, 0x90}, // channel = 3, Tf = 2422MHz + {0x20, 0x37, 0x90}, // channel = 4, Tf = 2427MHz + {0x20, 0x37, 0xA0}, // channel = 5, Tf = 2432MHz + {0x20, 0x37, 0xA0}, // channel = 6, Tf = 2437MHz + {0x20, 0x37, 0xA0}, // channel = 7, Tf = 2442MHz + {0x20, 0x37, 0xA0}, // channel = 8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49 + {0x20, 0x37, 0xB0}, // channel = 9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49 + {0x20, 0x37, 0xB0}, // channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49 + {0x20, 0x37, 0xB0}, // channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49 + {0x20, 0x37, 0xB0}, // channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49 + {0x20, 0x37, 0xC0}, // channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49 + {0x20, 0x37, 0xC0}, // channel = 14, Tf = 2484MHz + + // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + {0x0F, 0xF5, 0x20}, // channel = 183, Tf = 4915MHz (15) + {0x2F, 0xF5, 0x20}, // channel = 184, Tf = 4920MHz (16) + {0x0F, 0xF5, 0x20}, // channel = 185, Tf = 4925MHz (17) + {0x0F, 0xF5, 0x20}, // channel = 187, Tf = 4935MHz (18) + {0x2F, 0xF5, 0x20}, // channel = 188, Tf = 4940MHz (19) + {0x0F, 0xF5, 0x20}, // channel = 189, Tf = 4945MHz (20) + {0x2F, 0xF5, 0x30}, // channel = 192, Tf = 4960MHz (21) + {0x2F, 0xF5, 0x30}, // channel = 196, Tf = 4980MHz (22) + + // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, + // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + + {0x0F, 0xF5, 0x40}, // channel = 7, Tf = 5035MHz (23) + {0x2F, 0xF5, 0x40}, // channel = 8, Tf = 5040MHz (24) + {0x0F, 0xF5, 0x40}, // channel = 9, Tf = 5045MHz (25) + {0x0F, 0xF5, 0x40}, // channel = 11, Tf = 5055MHz (26) + {0x2F, 0xF5, 0x40}, // channel = 12, Tf = 5060MHz (27) + {0x2F, 0xF5, 0x50}, // channel = 16, Tf = 5080MHz (28) + {0x2F, 0xF5, 0x60}, // channel = 34, Tf = 5170MHz (29) + {0x2F, 0xF5, 0x60}, // channel = 36, Tf = 5180MHz (30) + {0x2F, 0xF5, 0x70}, // channel = 38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49 + {0x2F, 0xF5, 0x70}, // channel = 40, Tf = 5200MHz (32) + {0x2F, 0xF5, 0x70}, // channel = 42, Tf = 5210MHz (33) + {0x2F, 0xF5, 0x70}, // channel = 44, Tf = 5220MHz (34) + {0x2F, 0xF5, 0x70}, // channel = 46, Tf = 5230MHz (35) + {0x2F, 0xF5, 0x70}, // channel = 48, Tf = 5240MHz (36) + {0x2F, 0xF5, 0x80}, // channel = 52, Tf = 5260MHz (37) + {0x2F, 0xF5, 0x80}, // channel = 56, Tf = 5280MHz (38) + {0x2F, 0xF5, 0x80}, // channel = 60, Tf = 5300MHz (39) + {0x2F, 0xF5, 0x90}, // channel = 64, Tf = 5320MHz (40) + + {0x2F, 0xF5, 0xC0}, // channel = 100, Tf = 5500MHz (41) + {0x2F, 0xF5, 0xC0}, // channel = 104, Tf = 5520MHz (42) + {0x2F, 0xF5, 0xC0}, // channel = 108, Tf = 5540MHz (43) + {0x2F, 0xF5, 0xD0}, // channel = 112, Tf = 5560MHz (44) + {0x2F, 0xF5, 0xD0}, // channel = 116, Tf = 5580MHz (45) + {0x2F, 0xF5, 0xD0}, // channel = 120, Tf = 5600MHz (46) + {0x2F, 0xF5, 0xE0}, // channel = 124, Tf = 5620MHz (47) + {0x2F, 0xF5, 0xE0}, // channel = 128, Tf = 5640MHz (48) + {0x2F, 0xF5, 0xE0}, // channel = 132, Tf = 5660MHz (49) + {0x2F, 0xF5, 0xF0}, // channel = 136, Tf = 5680MHz (50) + {0x2F, 0xF5, 0xF0}, // channel = 140, Tf = 5700MHz (51) + {0x2F, 0xF6, 0x00}, // channel = 149, Tf = 5745MHz (52) + {0x2F, 0xF6, 0x00}, // channel = 153, Tf = 5765MHz (53) + {0x2F, 0xF6, 0x00}, // channel = 157, Tf = 5785MHz (54) + {0x2F, 0xF6, 0x10}, // channel = 161, Tf = 5805MHz (55) + {0x2F, 0xF6, 0x10} // channel = 165, Tf = 5825MHz (56) + }; + +u8 abyAL7230ChannelTable1[CB_MAX_CHANNEL][3] = { + {0x13, 0x33, 0x31}, // channel = 1, Tf = 2412MHz + {0x1B, 0x33, 0x31}, // channel = 2, Tf = 2417MHz + {0x03, 0x33, 0x31}, // channel = 3, Tf = 2422MHz + {0x0B, 0x33, 0x31}, // channel = 4, Tf = 2427MHz + {0x13, 0x33, 0x31}, // channel = 5, Tf = 2432MHz + {0x1B, 0x33, 0x31}, // channel = 6, Tf = 2437MHz + {0x03, 0x33, 0x31}, // channel = 7, Tf = 2442MHz + {0x0B, 0x33, 0x31}, // channel = 8, Tf = 2447MHz + {0x13, 0x33, 0x31}, // channel = 9, Tf = 2452MHz + {0x1B, 0x33, 0x31}, // channel = 10, Tf = 2457MHz + {0x03, 0x33, 0x31}, // channel = 11, Tf = 2462MHz + {0x0B, 0x33, 0x31}, // channel = 12, Tf = 2467MHz + {0x13, 0x33, 0x31}, // channel = 13, Tf = 2472MHz + {0x06, 0x66, 0x61}, // channel = 14, Tf = 2484MHz + + // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + {0x1D, 0x55, 0x51}, // channel = 183, Tf = 4915MHz (15) + {0x00, 0x00, 0x01}, // channel = 184, Tf = 4920MHz (16) + {0x02, 0xAA, 0xA1}, // channel = 185, Tf = 4925MHz (17) + {0x08, 0x00, 0x01}, // channel = 187, Tf = 4935MHz (18) + {0x0A, 0xAA, 0xA1}, // channel = 188, Tf = 4940MHz (19) + {0x0D, 0x55, 0x51}, // channel = 189, Tf = 4945MHz (20) + {0x15, 0x55, 0x51}, // channel = 192, Tf = 4960MHz (21) + {0x00, 0x00, 0x01}, // channel = 196, Tf = 4980MHz (22) + + // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, + // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + {0x1D, 0x55, 0x51}, // channel = 7, Tf = 5035MHz (23) + {0x00, 0x00, 0x01}, // channel = 8, Tf = 5040MHz (24) + {0x02, 0xAA, 0xA1}, // channel = 9, Tf = 5045MHz (25) + {0x08, 0x00, 0x01}, // channel = 11, Tf = 5055MHz (26) + {0x0A, 0xAA, 0xA1}, // channel = 12, Tf = 5060MHz (27) + {0x15, 0x55, 0x51}, // channel = 16, Tf = 5080MHz (28) + {0x05, 0x55, 0x51}, // channel = 34, Tf = 5170MHz (29) + {0x0A, 0xAA, 0xA1}, // channel = 36, Tf = 5180MHz (30) + {0x10, 0x00, 0x01}, // channel = 38, Tf = 5190MHz (31) + {0x15, 0x55, 0x51}, // channel = 40, Tf = 5200MHz (32) + {0x1A, 0xAA, 0xA1}, // channel = 42, Tf = 5210MHz (33) + {0x00, 0x00, 0x01}, // channel = 44, Tf = 5220MHz (34) + {0x05, 0x55, 0x51}, // channel = 46, Tf = 5230MHz (35) + {0x0A, 0xAA, 0xA1}, // channel = 48, Tf = 5240MHz (36) + {0x15, 0x55, 0x51}, // channel = 52, Tf = 5260MHz (37) + {0x00, 0x00, 0x01}, // channel = 56, Tf = 5280MHz (38) + {0x0A, 0xAA, 0xA1}, // channel = 60, Tf = 5300MHz (39) + {0x15, 0x55, 0x51}, // channel = 64, Tf = 5320MHz (40) + {0x15, 0x55, 0x51}, // channel = 100, Tf = 5500MHz (41) + {0x00, 0x00, 0x01}, // channel = 104, Tf = 5520MHz (42) + {0x0A, 0xAA, 0xA1}, // channel = 108, Tf = 5540MHz (43) + {0x15, 0x55, 0x51}, // channel = 112, Tf = 5560MHz (44) + {0x00, 0x00, 0x01}, // channel = 116, Tf = 5580MHz (45) + {0x0A, 0xAA, 0xA1}, // channel = 120, Tf = 5600MHz (46) + {0x15, 0x55, 0x51}, // channel = 124, Tf = 5620MHz (47) + {0x00, 0x00, 0x01}, // channel = 128, Tf = 5640MHz (48) + {0x0A, 0xAA, 0xA1}, // channel = 132, Tf = 5660MHz (49) + {0x15, 0x55, 0x51}, // channel = 136, Tf = 5680MHz (50) + {0x00, 0x00, 0x01}, // channel = 140, Tf = 5700MHz (51) + {0x18, 0x00, 0x01}, // channel = 149, Tf = 5745MHz (52) + {0x02, 0xAA, 0xA1}, // channel = 153, Tf = 5765MHz (53) + {0x0D, 0x55, 0x51}, // channel = 157, Tf = 5785MHz (54) + {0x18, 0x00, 0x01}, // channel = 161, Tf = 5805MHz (55) + {0x02, 0xAA, 0xB1} // channel = 165, Tf = 5825MHz (56) + }; + +u8 abyAL7230ChannelTable2[CB_MAX_CHANNEL][3] = { + {0x7F, 0xD7, 0x84}, // channel = 1, Tf = 2412MHz + {0x7F, 0xD7, 0x84}, // channel = 2, Tf = 2417MHz + {0x7F, 0xD7, 0x84}, // channel = 3, Tf = 2422MHz + {0x7F, 0xD7, 0x84}, // channel = 4, Tf = 2427MHz + {0x7F, 0xD7, 0x84}, // channel = 5, Tf = 2432MHz + {0x7F, 0xD7, 0x84}, // channel = 6, Tf = 2437MHz + {0x7F, 0xD7, 0x84}, // channel = 7, Tf = 2442MHz + {0x7F, 0xD7, 0x84}, // channel = 8, Tf = 2447MHz + {0x7F, 0xD7, 0x84}, // channel = 9, Tf = 2452MHz + {0x7F, 0xD7, 0x84}, // channel = 10, Tf = 2457MHz + {0x7F, 0xD7, 0x84}, // channel = 11, Tf = 2462MHz + {0x7F, 0xD7, 0x84}, // channel = 12, Tf = 2467MHz + {0x7F, 0xD7, 0x84}, // channel = 13, Tf = 2472MHz + {0x7F, 0xD7, 0x84}, // channel = 14, Tf = 2484MHz + + // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + {0x7F, 0xD7, 0x84}, // channel = 183, Tf = 4915MHz (15) + {0x6F, 0xD7, 0x84}, // channel = 184, Tf = 4920MHz (16) + {0x7F, 0xD7, 0x84}, // channel = 185, Tf = 4925MHz (17) + {0x7F, 0xD7, 0x84}, // channel = 187, Tf = 4935MHz (18) + {0x7F, 0xD7, 0x84}, // channel = 188, Tf = 4940MHz (19) + {0x7F, 0xD7, 0x84}, // channel = 189, Tf = 4945MHz (20) + {0x7F, 0xD7, 0x84}, // channel = 192, Tf = 4960MHz (21) + {0x6F, 0xD7, 0x84}, // channel = 196, Tf = 4980MHz (22) + + // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, + // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + {0x7F, 0xD7, 0x84}, // channel = 7, Tf = 5035MHz (23) + {0x6F, 0xD7, 0x84}, // channel = 8, Tf = 5040MHz (24) + {0x7F, 0xD7, 0x84}, // channel = 9, Tf = 5045MHz (25) + {0x7F, 0xD7, 0x84}, // channel = 11, Tf = 5055MHz (26) + {0x7F, 0xD7, 0x84}, // channel = 12, Tf = 5060MHz (27) + {0x7F, 0xD7, 0x84}, // channel = 16, Tf = 5080MHz (28) + {0x7F, 0xD7, 0x84}, // channel = 34, Tf = 5170MHz (29) + {0x7F, 0xD7, 0x84}, // channel = 36, Tf = 5180MHz (30) + {0x7F, 0xD7, 0x84}, // channel = 38, Tf = 5190MHz (31) + {0x7F, 0xD7, 0x84}, // channel = 40, Tf = 5200MHz (32) + {0x7F, 0xD7, 0x84}, // channel = 42, Tf = 5210MHz (33) + {0x6F, 0xD7, 0x84}, // channel = 44, Tf = 5220MHz (34) + {0x7F, 0xD7, 0x84}, // channel = 46, Tf = 5230MHz (35) + {0x7F, 0xD7, 0x84}, // channel = 48, Tf = 5240MHz (36) + {0x7F, 0xD7, 0x84}, // channel = 52, Tf = 5260MHz (37) + {0x6F, 0xD7, 0x84}, // channel = 56, Tf = 5280MHz (38) + {0x7F, 0xD7, 0x84}, // channel = 60, Tf = 5300MHz (39) + {0x7F, 0xD7, 0x84}, // channel = 64, Tf = 5320MHz (40) + {0x7F, 0xD7, 0x84}, // channel = 100, Tf = 5500MHz (41) + {0x6F, 0xD7, 0x84}, // channel = 104, Tf = 5520MHz (42) + {0x7F, 0xD7, 0x84}, // channel = 108, Tf = 5540MHz (43) + {0x7F, 0xD7, 0x84}, // channel = 112, Tf = 5560MHz (44) + {0x6F, 0xD7, 0x84}, // channel = 116, Tf = 5580MHz (45) + {0x7F, 0xD7, 0x84}, // channel = 120, Tf = 5600MHz (46) + {0x7F, 0xD7, 0x84}, // channel = 124, Tf = 5620MHz (47) + {0x6F, 0xD7, 0x84}, // channel = 128, Tf = 5640MHz (48) + {0x7F, 0xD7, 0x84}, // channel = 132, Tf = 5660MHz (49) + {0x7F, 0xD7, 0x84}, // channel = 136, Tf = 5680MHz (50) + {0x6F, 0xD7, 0x84}, // channel = 140, Tf = 5700MHz (51) + {0x7F, 0xD7, 0x84}, // channel = 149, Tf = 5745MHz (52) + {0x7F, 0xD7, 0x84}, // channel = 153, Tf = 5765MHz (53) + {0x7F, 0xD7, 0x84}, // channel = 157, Tf = 5785MHz (54) + {0x7F, 0xD7, 0x84}, // channel = 161, Tf = 5805MHz (55) + {0x7F, 0xD7, 0x84} // channel = 165, Tf = 5825MHz (56) + }; + +///{{RobertYu:20051111 +u8 abyVT3226_InitTable[CB_VT3226_INIT_SEQ][3] = { + {0x03, 0xFF, 0x80}, + {0x02, 0x82, 0xA1}, + {0x03, 0xC6, 0xA2}, + {0x01, 0x97, 0x93}, + {0x03, 0x66, 0x64}, + {0x00, 0x61, 0xA5}, + {0x01, 0x7B, 0xD6}, + {0x00, 0x80, 0x17}, + {0x03, 0xF8, 0x08}, + {0x00, 0x02, 0x39}, //RobertYu:20051116 + {0x02, 0x00, 0x2A} + }; + +u8 abyVT3226D0_InitTable[CB_VT3226_INIT_SEQ][3] = { + {0x03, 0xFF, 0x80}, + {0x03, 0x02, 0x21}, //RobertYu:20060327 + {0x03, 0xC6, 0xA2}, + {0x01, 0x97, 0x93}, + {0x03, 0x66, 0x64}, + {0x00, 0x71, 0xA5}, //RobertYu:20060103 + {0x01, 0x15, 0xC6}, //RobertYu:20060420 + {0x01, 0x2E, 0x07}, //RobertYu:20060420 + {0x00, 0x58, 0x08}, //RobertYu:20060111 + {0x00, 0x02, 0x79}, //RobertYu:20060420 + {0x02, 0x01, 0xAA} //RobertYu:20060523 + }; + +u8 abyVT3226_ChannelTable0[CB_MAX_CHANNEL_24G][3] = { + {0x01, 0x97, 0x83}, // channel = 1, Tf = 2412MHz + {0x01, 0x97, 0x83}, // channel = 2, Tf = 2417MHz + {0x01, 0x97, 0x93}, // channel = 3, Tf = 2422MHz + {0x01, 0x97, 0x93}, // channel = 4, Tf = 2427MHz + {0x01, 0x97, 0x93}, // channel = 5, Tf = 2432MHz + {0x01, 0x97, 0x93}, // channel = 6, Tf = 2437MHz + {0x01, 0x97, 0xA3}, // channel = 7, Tf = 2442MHz + {0x01, 0x97, 0xA3}, // channel = 8, Tf = 2447MHz + {0x01, 0x97, 0xA3}, // channel = 9, Tf = 2452MHz + {0x01, 0x97, 0xA3}, // channel = 10, Tf = 2457MHz + {0x01, 0x97, 0xB3}, // channel = 11, Tf = 2462MHz + {0x01, 0x97, 0xB3}, // channel = 12, Tf = 2467MHz + {0x01, 0x97, 0xB3}, // channel = 13, Tf = 2472MHz + {0x03, 0x37, 0xC3} // channel = 14, Tf = 2484MHz + }; + +u8 abyVT3226_ChannelTable1[CB_MAX_CHANNEL_24G][3] = { + {0x02, 0x66, 0x64}, // channel = 1, Tf = 2412MHz + {0x03, 0x66, 0x64}, // channel = 2, Tf = 2417MHz + {0x00, 0x66, 0x64}, // channel = 3, Tf = 2422MHz + {0x01, 0x66, 0x64}, // channel = 4, Tf = 2427MHz + {0x02, 0x66, 0x64}, // channel = 5, Tf = 2432MHz + {0x03, 0x66, 0x64}, // channel = 6, Tf = 2437MHz + {0x00, 0x66, 0x64}, // channel = 7, Tf = 2442MHz + {0x01, 0x66, 0x64}, // channel = 8, Tf = 2447MHz + {0x02, 0x66, 0x64}, // channel = 9, Tf = 2452MHz + {0x03, 0x66, 0x64}, // channel = 10, Tf = 2457MHz + {0x00, 0x66, 0x64}, // channel = 11, Tf = 2462MHz + {0x01, 0x66, 0x64}, // channel = 12, Tf = 2467MHz + {0x02, 0x66, 0x64}, // channel = 13, Tf = 2472MHz + {0x00, 0xCC, 0xC4} // channel = 14, Tf = 2484MHz + }; +///}}RobertYu + +//{{RobertYu:20060502, TWIF 1.14, LO Current for 11b mode +u32 dwVT3226D0LoCurrentTable[CB_MAX_CHANNEL_24G] = { + 0x0135C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz + 0x0135C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz + 0x0235C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz + 0x0235C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz + 0x0235C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz + 0x0335C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz + 0x0335C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz + 0x0335C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz + 0x0335C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz + 0x0335C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz + 0x0335C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz + 0x0335C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz + 0x0335C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz + 0x0135C600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW // channel = 14, Tf = 2484MHz +}; +//}} + +//{{RobertYu:20060609 +u8 abyVT3342A0_InitTable[CB_VT3342_INIT_SEQ][3] = { /* 11b/g mode */ + {0x03, 0xFF, 0x80}, //update for mode// + {0x02, 0x08, 0x81}, + {0x00, 0xC6, 0x02}, + {0x03, 0xC5, 0x13}, // channel6 + {0x00, 0xEE, 0xE4}, // channel6 + {0x00, 0x71, 0xA5}, + {0x01, 0x75, 0x46}, + {0x01, 0x40, 0x27}, + {0x01, 0x54, 0x08}, + {0x00, 0x01, 0x69}, + {0x02, 0x00, 0xAA}, + {0x00, 0x08, 0xCB}, + {0x01, 0x70, 0x0C} + }; + + //11b/g mode: 0x03, 0xFF, 0x80, + //11a mode: 0x03, 0xFF, 0xC0, + + // channel44, 5220MHz 0x00C402 + // channel56, 5280MHz 0x00C402 for disable Frac + // other channels 0x00C602 + +u8 abyVT3342_ChannelTable0[CB_MAX_CHANNEL][3] = { + {0x02, 0x05, 0x03}, // channel = 1, Tf = 2412MHz + {0x01, 0x15, 0x03}, // channel = 2, Tf = 2417MHz + {0x03, 0xC5, 0x03}, // channel = 3, Tf = 2422MHz + {0x02, 0x65, 0x03}, // channel = 4, Tf = 2427MHz + {0x01, 0x15, 0x13}, // channel = 5, Tf = 2432MHz + {0x03, 0xC5, 0x13}, // channel = 6, Tf = 2437MHz + {0x02, 0x05, 0x13}, // channel = 7, Tf = 2442MHz + {0x01, 0x15, 0x13}, // channel = 8, Tf = 2447MHz + {0x03, 0xC5, 0x13}, // channel = 9, Tf = 2452MHz + {0x02, 0x65, 0x13}, // channel = 10, Tf = 2457MHz + {0x01, 0x15, 0x23}, // channel = 11, Tf = 2462MHz + {0x03, 0xC5, 0x23}, // channel = 12, Tf = 2467MHz + {0x02, 0x05, 0x23}, // channel = 13, Tf = 2472MHz + {0x00, 0xD5, 0x23}, // channel = 14, Tf = 2484MHz + + // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + {0x01, 0x15, 0x13}, // channel = 183, Tf = 4915MHz (15), TBD + {0x01, 0x15, 0x13}, // channel = 184, Tf = 4920MHz (16), TBD + {0x01, 0x15, 0x13}, // channel = 185, Tf = 4925MHz (17), TBD + {0x01, 0x15, 0x13}, // channel = 187, Tf = 4935MHz (18), TBD + {0x01, 0x15, 0x13}, // channel = 188, Tf = 4940MHz (19), TBD + {0x01, 0x15, 0x13}, // channel = 189, Tf = 4945MHz (20), TBD + {0x01, 0x15, 0x13}, // channel = 192, Tf = 4960MHz (21), TBD + {0x01, 0x15, 0x13}, // channel = 196, Tf = 4980MHz (22), TBD + + // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, + // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + {0x01, 0x15, 0x13}, // channel = 7, Tf = 5035MHz (23), TBD + {0x01, 0x15, 0x13}, // channel = 8, Tf = 5040MHz (24), TBD + {0x01, 0x15, 0x13}, // channel = 9, Tf = 5045MHz (25), TBD + {0x01, 0x15, 0x13}, // channel = 11, Tf = 5055MHz (26), TBD + {0x01, 0x15, 0x13}, // channel = 12, Tf = 5060MHz (27), TBD + {0x01, 0x15, 0x13}, // channel = 16, Tf = 5080MHz (28), TBD + {0x01, 0x15, 0x13}, // channel = 34, Tf = 5170MHz (29), TBD + {0x01, 0x55, 0x63}, // channel = 36, Tf = 5180MHz (30) + {0x01, 0x55, 0x63}, // channel = 38, Tf = 5190MHz (31), TBD + {0x02, 0xA5, 0x63}, // channel = 40, Tf = 5200MHz (32) + {0x02, 0xA5, 0x63}, // channel = 42, Tf = 5210MHz (33), TBD + {0x00, 0x05, 0x73}, // channel = 44, Tf = 5220MHz (34) + {0x00, 0x05, 0x73}, // channel = 46, Tf = 5230MHz (35), TBD + {0x01, 0x55, 0x73}, // channel = 48, Tf = 5240MHz (36) + {0x02, 0xA5, 0x73}, // channel = 52, Tf = 5260MHz (37) + {0x00, 0x05, 0x83}, // channel = 56, Tf = 5280MHz (38) + {0x01, 0x55, 0x83}, // channel = 60, Tf = 5300MHz (39) + {0x02, 0xA5, 0x83}, // channel = 64, Tf = 5320MHz (40) + + {0x02, 0xA5, 0x83}, // channel = 100, Tf = 5500MHz (41), TBD + {0x02, 0xA5, 0x83}, // channel = 104, Tf = 5520MHz (42), TBD + {0x02, 0xA5, 0x83}, // channel = 108, Tf = 5540MHz (43), TBD + {0x02, 0xA5, 0x83}, // channel = 112, Tf = 5560MHz (44), TBD + {0x02, 0xA5, 0x83}, // channel = 116, Tf = 5580MHz (45), TBD + {0x02, 0xA5, 0x83}, // channel = 120, Tf = 5600MHz (46), TBD + {0x02, 0xA5, 0x83}, // channel = 124, Tf = 5620MHz (47), TBD + {0x02, 0xA5, 0x83}, // channel = 128, Tf = 5640MHz (48), TBD + {0x02, 0xA5, 0x83}, // channel = 132, Tf = 5660MHz (49), TBD + {0x02, 0xA5, 0x83}, // channel = 136, Tf = 5680MHz (50), TBD + {0x02, 0xA5, 0x83}, // channel = 140, Tf = 5700MHz (51), TBD + + {0x00, 0x05, 0xF3}, // channel = 149, Tf = 5745MHz (52) + {0x01, 0x56, 0x03}, // channel = 153, Tf = 5765MHz (53) + {0x02, 0xA6, 0x03}, // channel = 157, Tf = 5785MHz (54) + {0x00, 0x06, 0x03}, // channel = 161, Tf = 5805MHz (55) + {0x00, 0x06, 0x03} // channel = 165, Tf = 5825MHz (56), TBD + }; + +u8 abyVT3342_ChannelTable1[CB_MAX_CHANNEL][3] = { + {0x01, 0x99, 0x94}, // channel = 1, Tf = 2412MHz + {0x02, 0x44, 0x44}, // channel = 2, Tf = 2417MHz + {0x02, 0xEE, 0xE4}, // channel = 3, Tf = 2422MHz + {0x03, 0x99, 0x94}, // channel = 4, Tf = 2427MHz + {0x00, 0x44, 0x44}, // channel = 5, Tf = 2432MHz + {0x00, 0xEE, 0xE4}, // channel = 6, Tf = 2437MHz + {0x01, 0x99, 0x94}, // channel = 7, Tf = 2442MHz + {0x02, 0x44, 0x44}, // channel = 8, Tf = 2447MHz + {0x02, 0xEE, 0xE4}, // channel = 9, Tf = 2452MHz + {0x03, 0x99, 0x94}, // channel = 10, Tf = 2457MHz + {0x00, 0x44, 0x44}, // channel = 11, Tf = 2462MHz + {0x00, 0xEE, 0xE4}, // channel = 12, Tf = 2467MHz + {0x01, 0x99, 0x94}, // channel = 13, Tf = 2472MHz + {0x03, 0x33, 0x34}, // channel = 14, Tf = 2484MHz + + // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + {0x00, 0x44, 0x44}, // channel = 183, Tf = 4915MHz (15), TBD + {0x00, 0x44, 0x44}, // channel = 184, Tf = 4920MHz (16), TBD + {0x00, 0x44, 0x44}, // channel = 185, Tf = 4925MHz (17), TBD + {0x00, 0x44, 0x44}, // channel = 187, Tf = 4935MHz (18), TBD + {0x00, 0x44, 0x44}, // channel = 188, Tf = 4940MHz (19), TBD + {0x00, 0x44, 0x44}, // channel = 189, Tf = 4945MHz (20), TBD + {0x00, 0x44, 0x44}, // channel = 192, Tf = 4960MHz (21), TBD + {0x00, 0x44, 0x44}, // channel = 196, Tf = 4980MHz (22), TBD + + // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, + // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + {0x00, 0x44, 0x44}, // channel = 7, Tf = 5035MHz (23), TBD + {0x00, 0x44, 0x44}, // channel = 8, Tf = 5040MHz (24), TBD + {0x00, 0x44, 0x44}, // channel = 9, Tf = 5045MHz (25), TBD + {0x00, 0x44, 0x44}, // channel = 11, Tf = 5055MHz (26), TBD + {0x00, 0x44, 0x44}, // channel = 12, Tf = 5060MHz (27), TBD + {0x00, 0x44, 0x44}, // channel = 16, Tf = 5080MHz (28), TBD + {0x00, 0x44, 0x44}, // channel = 34, Tf = 5170MHz (29), TBD + {0x01, 0x55, 0x54}, // channel = 36, Tf = 5180MHz (30) + {0x01, 0x55, 0x54}, // channel = 38, Tf = 5190MHz (31), TBD + {0x02, 0xAA, 0xA4}, // channel = 40, Tf = 5200MHz (32) + {0x02, 0xAA, 0xA4}, // channel = 42, Tf = 5210MHz (33), TBD + {0x00, 0x00, 0x04}, // channel = 44, Tf = 5220MHz (34) + {0x00, 0x00, 0x04}, // channel = 46, Tf = 5230MHz (35), TBD + {0x01, 0x55, 0x54}, // channel = 48, Tf = 5240MHz (36) + {0x02, 0xAA, 0xA4}, // channel = 52, Tf = 5260MHz (37) + {0x00, 0x00, 0x04}, // channel = 56, Tf = 5280MHz (38) + {0x01, 0x55, 0x54}, // channel = 60, Tf = 5300MHz (39) + {0x02, 0xAA, 0xA4}, // channel = 64, Tf = 5320MHz (40) + {0x02, 0xAA, 0xA4}, // channel = 100, Tf = 5500MHz (41), TBD + {0x02, 0xAA, 0xA4}, // channel = 104, Tf = 5520MHz (42), TBD + {0x02, 0xAA, 0xA4}, // channel = 108, Tf = 5540MHz (43), TBD + {0x02, 0xAA, 0xA4}, // channel = 112, Tf = 5560MHz (44), TBD + {0x02, 0xAA, 0xA4}, // channel = 116, Tf = 5580MHz (45), TBD + {0x02, 0xAA, 0xA4}, // channel = 120, Tf = 5600MHz (46), TBD + {0x02, 0xAA, 0xA4}, // channel = 124, Tf = 5620MHz (47), TBD + {0x02, 0xAA, 0xA4}, // channel = 128, Tf = 5640MHz (48), TBD + {0x02, 0xAA, 0xA4}, // channel = 132, Tf = 5660MHz (49), TBD + {0x02, 0xAA, 0xA4}, // channel = 136, Tf = 5680MHz (50), TBD + {0x02, 0xAA, 0xA4}, // channel = 140, Tf = 5700MHz (51), TBD + {0x03, 0x00, 0x04}, // channel = 149, Tf = 5745MHz (52) + {0x00, 0x55, 0x54}, // channel = 153, Tf = 5765MHz (53) + {0x01, 0xAA, 0xA4}, // channel = 157, Tf = 5785MHz (54) + {0x03, 0x00, 0x04}, // channel = 161, Tf = 5805MHz (55) + {0x03, 0x00, 0x04} // channel = 165, Tf = 5825MHz (56), TBD + }; + +/*+ + * + * Power Table + * +-*/ + +const u32 dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { + 0x04040900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04041900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04042900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04043900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04044900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04045900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04046900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04047900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04048900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04049900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04050900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04051900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04052900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04053900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04054900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04055900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04056900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04057900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04058900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04059900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04060900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04061900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04062900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04063900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04064900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04065900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04066900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04067900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04068900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04069900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04070900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04071900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04072900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04073900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04074900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04075900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04076900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04077900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04078900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04079900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW + }; + +//{{ RobertYu:20050103, Channel 11a Number To Index +// 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) +// 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, +// 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + +const u8 RFaby11aChannelIndex[200] = { + // 1 2 3 4 5 6 7 8 9 10 + 00, 00, 00, 00, 00, 00, 23, 24, 25, 00, // 10 + 26, 27, 00, 00, 00, 28, 00, 00, 00, 00, // 20 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, // 30 + 00, 00, 00, 29, 00, 30, 00, 31, 00, 32, // 40 + 00, 33, 00, 34, 00, 35, 00, 36, 00, 00, // 50 + 00, 37, 00, 00, 00, 38, 00, 00, 00, 39, // 60 + 00, 00, 00, 40, 00, 00, 00, 00, 00, 00, // 70 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, // 80 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, // 90 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 41, //100 + + 00, 00, 00, 42, 00, 00, 00, 43, 00, 00, //110 + 00, 44, 00, 00, 00, 45, 00, 00, 00, 46, //120 + 00, 00, 00, 47, 00, 00, 00, 48, 00, 00, //130 + 00, 49, 00, 00, 00, 50, 00, 00, 00, 51, //140 + 00, 00, 00, 00, 00, 00, 00, 00, 52, 00, //150 + 00, 00, 53, 00, 00, 00, 54, 00, 00, 00, //160 + 55, 00, 00, 00, 56, 00, 00, 00, 00, 00, //170 + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, //180 + 00, 00, 15, 16, 17, 00, 18, 19, 20, 00, //190 + 00, 21, 00, 00, 00, 22, 00, 00, 00, 00 //200 +}; +//}} RobertYu + +/* + * Description: Write to IF/RF, by embedded programming + * + * Parameters: + * In: + * dwData - data to write + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +int IFRFbWriteEmbedded(struct vnt_private *pDevice, u32 dwData) +{ + u8 pbyData[4]; + + pbyData[0] = (u8)dwData; + pbyData[1] = (u8)(dwData >> 8); + pbyData[2] = (u8)(dwData >> 16); + pbyData[3] = (u8)(dwData >> 24); + + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE_IFRF, 0, 0, 4, pbyData); + + return true; +} + +/* + * Description: Set Tx power + * + * Parameters: + * In: + * dwIoBase - I/O base address + * dwRFPowerTable - RF Tx Power Setting + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +int RFbSetPower(struct vnt_private *pDevice, u32 uRATE, u32 uCH) +{ + int bResult = true; + u8 byPwr = pDevice->byCCKPwr; + + if (pDevice->dwDiagRefCount) + return true; + + if (uCH == 0) + return -EINVAL; + + switch (uRATE) { + case RATE_1M: + case RATE_2M: + case RATE_5M: + case RATE_11M: + byPwr = pDevice->abyCCKPwrTbl[uCH-1]; + break; + case RATE_6M: + case RATE_9M: + case RATE_18M: + case RATE_24M: + case RATE_36M: + case RATE_48M: + case RATE_54M: + if (uCH > CB_MAX_CHANNEL_24G) { + byPwr = pDevice->abyOFDMAPwrTbl[uCH-15]; + } else { + byPwr = pDevice->abyOFDMPwrTbl[uCH-1]; + } + break; + } + + bResult = RFbRawSetPower(pDevice, byPwr, uRATE); + + return bResult; +} + +/* + * Description: Set Tx power + * + * Parameters: + * In: + * dwIoBase - I/O base address + * dwRFPowerTable - RF Tx Power Setting + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ + +int RFbRawSetPower(struct vnt_private *pDevice, u8 byPwr, u32 uRATE) +{ + int bResult = true; + + if (pDevice->byCurPwr == byPwr) + return true; + + pDevice->byCurPwr = byPwr; + + switch (pDevice->byRFType) { + + case RF_AL2230 : + if (pDevice->byCurPwr >= AL2230_PWR_IDX_LEN) + return false; + bResult &= IFRFbWriteEmbedded(pDevice, dwAL2230PowerTable[pDevice->byCurPwr]); + if (uRATE <= RATE_11M) + bResult &= IFRFbWriteEmbedded(pDevice, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + else + bResult &= IFRFbWriteEmbedded(pDevice, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + break; + + case RF_AL2230S : + if (pDevice->byCurPwr >= AL2230_PWR_IDX_LEN) + return false; + bResult &= IFRFbWriteEmbedded(pDevice, dwAL2230PowerTable[pDevice->byCurPwr]); + if (uRATE <= RATE_11M) { + bResult &= IFRFbWriteEmbedded(pDevice, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbedded(pDevice, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + }else { + bResult &= IFRFbWriteEmbedded(pDevice, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbedded(pDevice, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + } + break; + + case RF_AIROHA7230: + { + u32 dwMax7230Pwr; + + if (uRATE <= RATE_11M) { //RobertYu:20060426, for better 11b mask + bResult &= IFRFbWriteEmbedded(pDevice, 0x111BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); + } + else { + bResult &= IFRFbWriteEmbedded(pDevice, 0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); + } + + if (pDevice->byCurPwr > AL7230_PWR_IDX_LEN) return false; + + // 0x080F1B00 for 3 wire control TxGain(D10) and 0x31 as TX Gain value + dwMax7230Pwr = 0x080C0B00 | ( (pDevice->byCurPwr) << 12 ) | + (BY_AL7230_REG_LEN << 3 ) | IFREGCTL_REGW; + + bResult &= IFRFbWriteEmbedded(pDevice, dwMax7230Pwr); + break; + } + break; + + case RF_VT3226: //RobertYu:20051111, VT3226C0 and before + { + u32 dwVT3226Pwr; + + if (pDevice->byCurPwr >= VT3226_PWR_IDX_LEN) + return false; + dwVT3226Pwr = ((0x3F-pDevice->byCurPwr) << 20 ) | ( 0x17 << 8 ) /* Reg7 */ | + (BY_VT3226_REG_LEN << 3 ) | IFREGCTL_REGW; + bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226Pwr); + break; + } + + case RF_VT3226D0: //RobertYu:20051228 + { + u32 dwVT3226Pwr; + + if (pDevice->byCurPwr >= VT3226_PWR_IDX_LEN) + return false; + + if (uRATE <= RATE_11M) { + + dwVT3226Pwr = ((0x3F-pDevice->byCurPwr) << 20 ) | ( 0xE07 << 8 ) /* Reg7 */ | //RobertYu:20060420, TWIF 1.10 + (BY_VT3226_REG_LEN << 3 ) | IFREGCTL_REGW; + bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226Pwr); + + bResult &= IFRFbWriteEmbedded(pDevice, 0x03C6A200+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); + if (pDevice->vnt_mgmt.eScanState != WMAC_NO_SCANNING) { + /* scanning, channel number is pDevice->uScanChannel */ + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "RFbRawSetPower> 11B mode uCurrChannel[%d]\n", + pDevice->vnt_mgmt.uScanChannel); + bResult &= IFRFbWriteEmbedded(pDevice, + dwVT3226D0LoCurrentTable[pDevice-> + vnt_mgmt.uScanChannel - 1]); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "RFbRawSetPower> 11B mode uCurrChannel[%d]\n", + pDevice->vnt_mgmt.uCurrChannel); + bResult &= IFRFbWriteEmbedded(pDevice, + dwVT3226D0LoCurrentTable[pDevice-> + vnt_mgmt.uCurrChannel - 1]); + } + + bResult &= IFRFbWriteEmbedded(pDevice, 0x015C0800+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060420, ok now, new switching power (mini-pci can have bigger power consumption) + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"@@@@ RFbRawSetPower> 11G mode\n"); + dwVT3226Pwr = ((0x3F-pDevice->byCurPwr) << 20 ) | ( 0x7 << 8 ) /* Reg7 */ | //RobertYu:20060420, TWIF 1.10 + (BY_VT3226_REG_LEN << 3 ) | IFREGCTL_REGW; + bResult &= IFRFbWriteEmbedded(pDevice, dwVT3226Pwr); + bResult &= IFRFbWriteEmbedded(pDevice, 0x00C6A200+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060327 + bResult &= IFRFbWriteEmbedded(pDevice, 0x016BC600+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060111 + bResult &= IFRFbWriteEmbedded(pDevice, 0x00900800+(BY_VT3226_REG_LEN<<3)+IFREGCTL_REGW); //RobertYu:20060111 + } + break; + } + + //{{RobertYu:20060609 + case RF_VT3342A0: + { + u32 dwVT3342Pwr; + + if (pDevice->byCurPwr >= VT3342_PWR_IDX_LEN) + return false; + + dwVT3342Pwr = ((0x3F-pDevice->byCurPwr) << 20 ) | ( 0x27 << 8 ) /* Reg7 */ | + (BY_VT3342_REG_LEN << 3 ) | IFREGCTL_REGW; + bResult &= IFRFbWriteEmbedded(pDevice, dwVT3342Pwr); + break; + } + + default : + break; + } + return bResult; +} + +/*+ + * + * Routine Description: + * Translate RSSI to dBm + * + * Parameters: + * In: + * pDevice - The adapter to be translated + * byCurrRSSI - RSSI to be translated + * Out: + * pdwdbm - Translated dbm number + * + * Return Value: none + * +-*/ +void RFvRSSITodBm(struct vnt_private *pDevice, u8 byCurrRSSI, long *pldBm) +{ + u8 byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03); + signed long b = (byCurrRSSI & 0x3F); + signed long a = 0; + u8 abyAIROHARF[4] = {0, 18, 0, 40}; + + switch (pDevice->byRFType) { + case RF_AL2230: + case RF_AL2230S: + case RF_AIROHA7230: + case RF_VT3226: //RobertYu:20051111 + case RF_VT3226D0: + case RF_VT3342A0: //RobertYu:20060609 + a = abyAIROHARF[byIdx]; + break; + default: + break; + } + + *pldBm = -1 * (a + b * 2); +} + +void RFbRFTableDownload(struct vnt_private *pDevice) +{ + u16 wLength1 = 0, wLength2 = 0, wLength3 = 0; + u8 *pbyAddr1 = NULL, *pbyAddr2 = NULL, *pbyAddr3 = NULL; + u16 wLength, wValue; + u8 abyArray[256]; + + switch ( pDevice->byRFType ) { + case RF_AL2230: + case RF_AL2230S: + wLength1 = CB_AL2230_INIT_SEQ * 3; + wLength2 = CB_MAX_CHANNEL_24G * 3; + wLength3 = CB_MAX_CHANNEL_24G * 3; + pbyAddr1 = &(abyAL2230InitTable[0][0]); + pbyAddr2 = &(abyAL2230ChannelTable0[0][0]); + pbyAddr3 = &(abyAL2230ChannelTable1[0][0]); + break; + case RF_AIROHA7230: + wLength1 = CB_AL7230_INIT_SEQ * 3; + wLength2 = CB_MAX_CHANNEL * 3; + wLength3 = CB_MAX_CHANNEL * 3; + pbyAddr1 = &(abyAL7230InitTable[0][0]); + pbyAddr2 = &(abyAL7230ChannelTable0[0][0]); + pbyAddr3 = &(abyAL7230ChannelTable1[0][0]); + break; + case RF_VT3226: //RobertYu:20051111 + wLength1 = CB_VT3226_INIT_SEQ * 3; + wLength2 = CB_MAX_CHANNEL_24G * 3; + wLength3 = CB_MAX_CHANNEL_24G * 3; + pbyAddr1 = &(abyVT3226_InitTable[0][0]); + pbyAddr2 = &(abyVT3226_ChannelTable0[0][0]); + pbyAddr3 = &(abyVT3226_ChannelTable1[0][0]); + break; + case RF_VT3226D0: //RobertYu:20051114 + wLength1 = CB_VT3226_INIT_SEQ * 3; + wLength2 = CB_MAX_CHANNEL_24G * 3; + wLength3 = CB_MAX_CHANNEL_24G * 3; + pbyAddr1 = &(abyVT3226D0_InitTable[0][0]); + pbyAddr2 = &(abyVT3226_ChannelTable0[0][0]); + pbyAddr3 = &(abyVT3226_ChannelTable1[0][0]); + break; + case RF_VT3342A0: //RobertYu:20060609 + wLength1 = CB_VT3342_INIT_SEQ * 3; + wLength2 = CB_MAX_CHANNEL * 3; + wLength3 = CB_MAX_CHANNEL * 3; + pbyAddr1 = &(abyVT3342A0_InitTable[0][0]); + pbyAddr2 = &(abyVT3342_ChannelTable0[0][0]); + pbyAddr3 = &(abyVT3342_ChannelTable1[0][0]); + break; + + } + //Init Table + + memcpy(abyArray, pbyAddr1, wLength1); + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + 0, + MESSAGE_REQUEST_RF_INIT, + wLength1, + abyArray + ); + //Channel Table 0 + wValue = 0; + while ( wLength2 > 0 ) { + + if ( wLength2 >= 64 ) { + wLength = 64; + } else { + wLength = wLength2; + } + memcpy(abyArray, pbyAddr2, wLength); + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + wValue, + MESSAGE_REQUEST_RF_CH0, + wLength, + abyArray); + + wLength2 -= wLength; + wValue += wLength; + pbyAddr2 += wLength; + } + //Channel table 1 + wValue = 0; + while ( wLength3 > 0 ) { + + if ( wLength3 >= 64 ) { + wLength = 64; + } else { + wLength = wLength3; + } + memcpy(abyArray, pbyAddr3, wLength); + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + wValue, + MESSAGE_REQUEST_RF_CH1, + wLength, + abyArray); + + wLength3 -= wLength; + wValue += wLength; + pbyAddr3 += wLength; + } + + //7230 needs 2 InitTable and 3 Channel Table + if ( pDevice->byRFType == RF_AIROHA7230 ) { + wLength1 = CB_AL7230_INIT_SEQ * 3; + wLength2 = CB_MAX_CHANNEL * 3; + pbyAddr1 = &(abyAL7230InitTableAMode[0][0]); + pbyAddr2 = &(abyAL7230ChannelTable2[0][0]); + memcpy(abyArray, pbyAddr1, wLength1); + //Init Table 2 + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + 0, + MESSAGE_REQUEST_RF_INIT2, + wLength1, + abyArray); + + //Channel Table 0 + wValue = 0; + while ( wLength2 > 0 ) { + + if ( wLength2 >= 64 ) { + wLength = 64; + } else { + wLength = wLength2; + } + memcpy(abyArray, pbyAddr2, wLength); + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_WRITE, + wValue, + MESSAGE_REQUEST_RF_CH2, + wLength, + abyArray); + + wLength2 -= wLength; + wValue += wLength; + pbyAddr2 += wLength; + } + } + +} diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h new file mode 100644 index 00000000..de5c613b --- /dev/null +++ b/drivers/staging/vt6656/rf.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: rf.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Feb. 19, 2004 + * + */ + +#ifndef __RF_H__ +#define __RF_H__ + +#include "device.h" + +// +// Baseband RF pair definition in eeprom (Bits 6..0) +// +#define RF_RFMD2959 0x01 +#define RF_MAXIMAG 0x02 +#define RF_AL2230 0x03 +#define RF_GCT5103 0x04 +#define RF_UW2451 0x05 +#define RF_MAXIMG 0x06 +#define RF_MAXIM2829 0x07 +#define RF_UW2452 0x08 +#define RF_VT3226 0x09 +#define RF_AIROHA7230 0x0a +#define RF_UW2453 0x0b +#define RF_VT3226D0 0x0c //RobertYu:20051114 +#define RF_VT3342A0 0x0d //RobertYu:20060609 +#define RF_AL2230S 0x0e + +#define RF_EMU 0x80 +#define RF_MASK 0x7F + +extern const u8 RFaby11aChannelIndex[200]; + +int IFRFbWriteEmbedded(struct vnt_private *, u32 dwData); +int RFbSetPower(struct vnt_private *, u32 uRATE, u32 uCH); +int RFbRawSetPower(struct vnt_private *, u8 byPwr, u32 uRATE); +void RFvRSSITodBm(struct vnt_private *, u8 byCurrRSSI, long *pldBm); +void RFbRFTableDownload(struct vnt_private *pDevice); + +#endif /* __RF_H__ */ diff --git a/drivers/staging/vt6656/rndis.h b/drivers/staging/vt6656/rndis.h new file mode 100644 index 00000000..5cf5e732 --- /dev/null +++ b/drivers/staging/vt6656/rndis.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: rndis.h + * + * Purpose: Interface between firmware and driver + * + * Author: Warren Hsu + * + * Date: Nov 24, 2004 + * + */ + +#ifndef __RNDIS_H__ +#define __RNDIS_H__ + +#define MESSAGE_TYPE_READ 0x01 +#define MESSAGE_TYPE_WRITE 0x00 +#define MESSAGE_TYPE_LOCK_OR 0x02 +#define MESSAGE_TYPE_LOCK_AND 0x03 +#define MESSAGE_TYPE_WRITE_MASK 0x04 +#define MESSAGE_TYPE_CARDINIT 0x05 +#define MESSAGE_TYPE_INIT_RSP 0x06 +#define MESSAGE_TYPE_MACSHUTDOWN 0x07 +#define MESSAGE_TYPE_SETKEY 0x08 +#define MESSAGE_TYPE_CLRKEYENTRY 0x09 +#define MESSAGE_TYPE_WRITE_MISCFF 0x0A +#define MESSAGE_TYPE_SET_ANTMD 0x0B +#define MESSAGE_TYPE_SELECT_CHANNLE 0x0C +#define MESSAGE_TYPE_SET_TSFTBTT 0x0D +#define MESSAGE_TYPE_SET_SSTIFS 0x0E +#define MESSAGE_TYPE_CHANGE_BBTYPE 0x0F +#define MESSAGE_TYPE_DISABLE_PS 0x10 +#define MESSAGE_TYPE_WRITE_IFRF 0x11 + +//used for read/write(index) +#define MESSAGE_REQUEST_MEM 0x01 +#define MESSAGE_REQUEST_BBREG 0x02 +#define MESSAGE_REQUEST_MACREG 0x03 +#define MESSAGE_REQUEST_EEPROM 0x04 +#define MESSAGE_REQUEST_TSF 0x05 +#define MESSAGE_REQUEST_TBTT 0x06 +#define MESSAGE_REQUEST_BBAGC 0x07 +#define MESSAGE_REQUEST_VERSION 0x08 +#define MESSAGE_REQUEST_RF_INIT 0x09 +#define MESSAGE_REQUEST_RF_INIT2 0x0A +#define MESSAGE_REQUEST_RF_CH0 0x0B +#define MESSAGE_REQUEST_RF_CH1 0x0C +#define MESSAGE_REQUEST_RF_CH2 0x0D + +#define VIAUSB20_PACKET_HEADER 0x04 + +#define USB_REG4 0x604 + +typedef struct _CMD_MESSAGE +{ + u8 byData[256]; +} CMD_MESSAGE, *PCMD_MESSAGE; + +typedef struct _CMD_WRITE_MASK +{ + u8 byData; + u8 byMask; +} CMD_WRITE_MASK, *PCMD_WRITE_MASK; + +typedef struct _CMD_CARD_INIT +{ + u8 byInitClass; + u8 bExistSWNetAddr; + u8 bySWNetAddr[6]; + u8 byShortRetryLimit; + u8 byLongRetryLimit; +} CMD_CARD_INIT, *PCMD_CARD_INIT; + +typedef struct _RSP_CARD_INIT +{ + u8 byStatus; + u8 byNetAddr[6]; + u8 byRFType; + u8 byMinChannel; + u8 byMaxChannel; +} RSP_CARD_INIT, *PRSP_CARD_INIT; + +typedef struct _CMD_SET_KEY +{ + u16 wKCTL; + u8 abyMacAddr[6]; + u8 abyKey[16]; +} CMD_SET_KEY, *PCMD_SET_KEY; + +typedef struct _CMD_CLRKEY_ENTRY +{ + u8 abyKeyEntry[11]; +} CMD_CLRKEY_ENTRY, *PCMD_CLRKEY_ENTRY; + +typedef struct _CMD_WRITE_MISCFF +{ + u32 adwMiscFFData[22][4]; //a key entry has only 22 dwords +} CMD_WRITE_MISCFF, *PCMD_WRITE_MISCFF; + +typedef struct _CMD_SET_TSFTBTT +{ + u8 abyTSF_TBTT[8]; +} CMD_SET_TSFTBTT, *PCMD_SET_TSFTBTT; + +typedef struct _CMD_SET_SSTIFS +{ + u8 bySIFS; + u8 byDIFS; + u8 byEIFS; + u8 bySlotTime; + u8 byCwMax_Min; + u8 byBBCR10; +} CMD_SET_SSTIFS, *PCMD_SET_SSTIFS; + +typedef struct _CMD_CHANGE_BBTYPE +{ + u8 bySIFS; + u8 byDIFS; + u8 byEIFS; + u8 bySlotTime; + u8 byCwMax_Min; + u8 byBBCR10; + u8 byBB_BBType; //CR88 + u8 byMAC_BBType; + u32 dwRSPINF_b_1; + u32 dwRSPINF_b_2; + u32 dwRSPINF_b_55; + u32 dwRSPINF_b_11; + u16 wRSPINF_a[9]; +} CMD_CHANGE_BBTYPE, *PCMD_CHANGE_BBTYPE; + +#define EXCH_WORD(w) ((u16)((u16)(w)<<8) | (u16)((u16)(w)>>8)) + +#endif /* _RNDIS_H_ */ diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c new file mode 100644 index 00000000..9bf2f8d5 --- /dev/null +++ b/drivers/staging/vt6656/rxtx.c @@ -0,0 +1,2928 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: rxtx.c + * + * Purpose: handle WMAC/802.3/802.11 rx & tx functions + * + * Author: Lyndon Chen + * + * Date: May 20, 2003 + * + * Functions: + * s_vGenerateTxParameter - Generate tx dma required parameter. + * s_vGenerateMACHeader - Translate 802.3 to 802.11 header + * csBeacon_xmit - beacon tx function + * csMgmt_xmit - management tx function + * s_uGetDataDuration - get tx data required duration + * s_uFillDataHead- fulfill tx data duration header + * s_uGetRTSCTSDuration- get rtx/cts required duration + * s_uGetRTSCTSRsvTime- get rts/cts reserved time + * s_uGetTxRsvTime- get frame reserved time + * s_vFillCTSHead- fulfill CTS ctl header + * s_vFillFragParameter- Set fragment ctl parameter. + * s_vFillRTSHead- fulfill RTS ctl header + * s_vFillTxKey- fulfill tx encrypt key + * s_vSWencryption- Software encrypt header + * vDMA0_tx_80211- tx 802.11 frame via dma0 + * vGenerateFIFOHeader- Generate tx FIFO ctl header + * + * Revision History: + * + */ + +#include "device.h" +#include "rxtx.h" +#include "tether.h" +#include "card.h" +#include "bssdb.h" +#include "mac.h" +#include "baseband.h" +#include "michael.h" +#include "tkip.h" +#include "tcrc.h" +#include "wctl.h" +#include "hostap.h" +#include "rf.h" +#include "datarate.h" +#include "usbpipe.h" +#include "iocmd.h" + +static int msglevel = MSG_LEVEL_INFO; + +const u16 wTimeStampOff[2][MAX_RATE] = { + {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble + {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble + }; + +const u16 wFB_Opt0[2][5] = { + {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0 + {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1 + }; +const u16 wFB_Opt1[2][5] = { + {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0 + {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1 + }; + +#define RTSDUR_BB 0 +#define RTSDUR_BA 1 +#define RTSDUR_AA 2 +#define CTSDUR_BA 3 +#define RTSDUR_BA_F0 4 +#define RTSDUR_AA_F0 5 +#define RTSDUR_BA_F1 6 +#define RTSDUR_AA_F1 7 +#define CTSDUR_BA_F0 8 +#define CTSDUR_BA_F1 9 +#define DATADUR_B 10 +#define DATADUR_A 11 +#define DATADUR_A_F0 12 +#define DATADUR_A_F1 13 + +static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, + u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl); + +static void *s_vGetFreeContext(struct vnt_private *pDevice); + +static void s_vGenerateTxParameter(struct vnt_private *pDevice, + u8 byPktType, u16 wCurrentRate, void *pTxBufHead, void *pvRrvTime, + void *pvRTS, void *pvCTS, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx, + struct ethhdr *psEthHeader); + +static u32 s_uFillDataHead(struct vnt_private *pDevice, + u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength, + u32 uDMAIdx, int bNeedAck, u32 uFragIdx, u32 cbLastFragmentSize, + u32 uMACfragNum, u8 byFBOption); + +static void s_vGenerateMACHeader(struct vnt_private *pDevice, + u8 *pbyBufferAddr, u16 wDuration, struct ethhdr *psEthHeader, + int bNeedEncrypt, u16 wFragType, u32 uDMAIdx, u32 uFragIdx); + +static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf, + u8 *pbyIVHead, PSKeyItem pTransmitKey, u8 *pbyHdrBuf, u16 wPayloadLen, + u8 *pMICHDR); + +static void s_vSWencryption(struct vnt_private *pDevice, + PSKeyItem pTransmitKey, u8 *pbyPayloadHead, u16 wPayloadSize); + +static unsigned int s_uGetTxRsvTime(struct vnt_private *pDevice, u8 byPktType, + u32 cbFrameLength, u16 wRate, int bNeedAck); + +static u32 s_uGetRTSCTSRsvTime(struct vnt_private *pDevice, u8 byRTSRsvType, + u8 byPktType, u32 cbFrameLength, u16 wCurrentRate); + +static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx, + u8 byPktType, void *pvCTS, u32 cbFrameLength, int bNeedAck, + int bDisCRC, u16 wCurrentRate, u8 byFBOption); + +static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType, + void *pvRTS, u32 cbFrameLength, int bNeedAck, int bDisCRC, + struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption); + +static u32 s_uGetDataDuration(struct vnt_private *pDevice, u8 byDurType, + u32 cbFrameLength, u8 byPktType, u16 wRate, int bNeedAck, + u32 uFragIdx, u32 cbLastFragmentSize, u32 uMACfragNum, + u8 byFBOption); + +static unsigned int s_uGetRTSCTSDuration(struct vnt_private *pDevice, + u8 byDurType, u32 cbFrameLength, u8 byPktType, u16 wRate, + int bNeedAck, u8 byFBOption); + +static void *s_vGetFreeContext(struct vnt_private *pDevice) +{ + PUSB_SEND_CONTEXT pContext = NULL; + PUSB_SEND_CONTEXT pReturnContext = NULL; + int ii; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n"); + + for (ii = 0; ii < pDevice->cbTD; ii++) { + pContext = pDevice->apTD[ii]; + if (pContext->bBoolInUse == false) { + pContext->bBoolInUse = true; + pReturnContext = pContext; + break; + } + } + if ( ii == pDevice->cbTD ) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Free Tx Context\n"); + } + return (void *) pReturnContext; +} + +static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, + u8 *pbyDestAddr, u16 wPktLength, u16 wFIFOCtl) +{ + PSStatCounter pStatistic = &pDevice->scStatistic; + + if (is_broadcast_ether_addr(pbyDestAddr)) + pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_BROAD; + else if (is_multicast_ether_addr(pbyDestAddr)) + pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_MULTI; + else + pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_UNI; + + pStatistic->abyTxPktInfo[byPktNum].wLength = wPktLength; + pStatistic->abyTxPktInfo[byPktNum].wFIFOCtl = wFIFOCtl; + memcpy(pStatistic->abyTxPktInfo[byPktNum].abyDestAddr, + pbyDestAddr, + ETH_ALEN); +} + +static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf, + u8 *pbyIVHead, PSKeyItem pTransmitKey, u8 *pbyHdrBuf, + u16 wPayloadLen, u8 *pMICHDR) +{ + u32 *pdwIV = (u32 *)pbyIVHead; + u32 *pdwExtIV = (u32 *)((u8 *)pbyIVHead + 4); + u16 wValue; + struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *)pbyHdrBuf; + u32 dwRevIVCounter; + + //Fill TXKEY + if (pTransmitKey == NULL) + return; + + dwRevIVCounter = cpu_to_le32(pDevice->dwIVCounter); + *pdwIV = pDevice->dwIVCounter; + pDevice->byKeyIndex = pTransmitKey->dwKeyIndex & 0xf; + + if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { + if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN ){ + memcpy(pDevice->abyPRNG, (u8 *)&(dwRevIVCounter), 3); + memcpy(pDevice->abyPRNG+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength); + } else { + memcpy(pbyBuf, (u8 *)&(dwRevIVCounter), 3); + memcpy(pbyBuf+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength); + if(pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) { + memcpy(pbyBuf+8, (u8 *)&(dwRevIVCounter), 3); + memcpy(pbyBuf+11, pTransmitKey->abyKey, pTransmitKey->uKeyLength); + } + memcpy(pDevice->abyPRNG, pbyBuf, 16); + } + // Append IV after Mac Header + *pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111 + *pdwIV |= (u32)pDevice->byKeyIndex << 30; + *pdwIV = cpu_to_le32(*pdwIV); + pDevice->dwIVCounter++; + if (pDevice->dwIVCounter > WEP_IV_MASK) { + pDevice->dwIVCounter = 0; + } + } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + pTransmitKey->wTSC15_0++; + if (pTransmitKey->wTSC15_0 == 0) { + pTransmitKey->dwTSC47_16++; + } + TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, + pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); + memcpy(pbyBuf, pDevice->abyPRNG, 16); + // Make IV + memcpy(pdwIV, pDevice->abyPRNG, 3); + + *(pbyIVHead+3) = (u8)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV + // Append IV&ExtIV after Mac Header + *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %x\n", + *pdwExtIV); + + } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { + pTransmitKey->wTSC15_0++; + if (pTransmitKey->wTSC15_0 == 0) { + pTransmitKey->dwTSC47_16++; + } + memcpy(pbyBuf, pTransmitKey->abyKey, 16); + + // Make IV + *pdwIV = 0; + *(pbyIVHead+3) = (u8)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV + *pdwIV |= cpu_to_le16((u16)(pTransmitKey->wTSC15_0)); + //Append IV&ExtIV after Mac Header + *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); + + //Fill MICHDR0 + *pMICHDR = 0x59; + *((u8 *)(pMICHDR+1)) = 0; // TxPriority + memcpy(pMICHDR+2, &(pMACHeader->addr2[0]), 6); + *((u8 *)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16)); + *((u8 *)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16)); + *((u8 *)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16)); + *((u8 *)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16)); + *((u8 *)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0); + *((u8 *)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0); + *((u8 *)(pMICHDR+14)) = HIBYTE(wPayloadLen); + *((u8 *)(pMICHDR+15)) = LOBYTE(wPayloadLen); + + //Fill MICHDR1 + *((u8 *)(pMICHDR+16)) = 0; // HLEN[15:8] + if (pDevice->bLongHeader) { + *((u8 *)(pMICHDR+17)) = 28; // HLEN[7:0] + } else { + *((u8 *)(pMICHDR+17)) = 22; // HLEN[7:0] + } + wValue = cpu_to_le16(pMACHeader->frame_control & 0xC78F); + memcpy(pMICHDR+18, (u8 *)&wValue, 2); // MSKFRACTL + memcpy(pMICHDR+20, &(pMACHeader->addr1[0]), 6); + memcpy(pMICHDR+26, &(pMACHeader->addr2[0]), 6); + + //Fill MICHDR2 + memcpy(pMICHDR+32, &(pMACHeader->addr3[0]), 6); + wValue = pMACHeader->seq_ctrl; + wValue &= 0x000F; + wValue = cpu_to_le16(wValue); + memcpy(pMICHDR+38, (u8 *)&wValue, 2); // MSKSEQCTL + if (pDevice->bLongHeader) { + memcpy(pMICHDR+40, &(pMACHeader->addr4[0]), 6); + } + } +} + +static void s_vSWencryption(struct vnt_private *pDevice, + PSKeyItem pTransmitKey, u8 *pbyPayloadHead, u16 wPayloadSize) +{ + u32 cbICVlen = 4; + u32 dwICV = 0xffffffff; + u32 *pdwICV; + + if (pTransmitKey == NULL) + return; + + if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { + //======================================================================= + // Append ICV after payload + dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload) + pdwICV = (u32 *)(pbyPayloadHead + wPayloadSize); + // finally, we must invert dwCRC to get the correct answer + *pdwICV = cpu_to_le32(~dwICV); + // RC4 encryption + rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength + 3); + rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen); + //======================================================================= + } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + //======================================================================= + //Append ICV after payload + dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload) + pdwICV = (u32 *)(pbyPayloadHead + wPayloadSize); + // finally, we must invert dwCRC to get the correct answer + *pdwICV = cpu_to_le32(~dwICV); + // RC4 encryption + rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); + rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen); + //======================================================================= + } +} + +/*byPktType : PK_TYPE_11A 0 + PK_TYPE_11B 1 + PK_TYPE_11GB 2 + PK_TYPE_11GA 3 +*/ +static u32 s_uGetTxRsvTime(struct vnt_private *pDevice, u8 byPktType, + u32 cbFrameLength, u16 wRate, int bNeedAck) +{ + u32 uDataTime, uAckTime; + + uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate); + if (byPktType == PK_TYPE_11B) {//llb,CCK mode + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (u16)pDevice->byTopCCKBasicRate); + } else {//11g 2.4G OFDM mode & 11a 5G OFDM mode + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (u16)pDevice->byTopOFDMBasicRate); + } + + if (bNeedAck) { + return (uDataTime + pDevice->uSIFS + uAckTime); + } + else { + return uDataTime; + } +} + +//byFreqType: 0=>5GHZ 1=>2.4GHZ +static u32 s_uGetRTSCTSRsvTime(struct vnt_private *pDevice, + u8 byRTSRsvType, u8 byPktType, u32 cbFrameLength, u16 wCurrentRate) +{ + u32 uRrvTime, uRTSTime, uCTSTime, uAckTime, uDataTime; + + uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0; + + uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate); + if (byRTSRsvType == 0) { //RTSTxRrvTime_bb + uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate); + uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + } + else if (byRTSRsvType == 1){ //RTSTxRrvTime_ba, only in 2.4GHZ + uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate); + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + } + else if (byRTSRsvType == 2) { //RTSTxRrvTime_aa + uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopOFDMBasicRate); + uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + } + else if (byRTSRsvType == 3) { //CTSTxRrvTime_ba, only in 2.4GHZ + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + uRrvTime = uCTSTime + uAckTime + uDataTime + 2*pDevice->uSIFS; + return uRrvTime; + } + + //RTSRrvTime + uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3*pDevice->uSIFS; + return uRrvTime; +} + +//byFreqType 0: 5GHz, 1:2.4Ghz +static u32 s_uGetDataDuration(struct vnt_private *pDevice, u8 byDurType, + u32 cbFrameLength, u8 byPktType, u16 wRate, int bNeedAck, + u32 uFragIdx, u32 cbLastFragmentSize, u32 uMACfragNum, + u8 byFBOption) +{ + int bLastFrag = 0; + u32 uAckTime = 0, uNextPktTime = 0; + + if (uFragIdx == (uMACfragNum-1)) { + bLastFrag = 1; + } + + switch (byDurType) { + + case DATADUR_B: //DATADUR_B + if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag + if (bNeedAck) { + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + return (pDevice->uSIFS + uAckTime); + } else { + return 0; + } + } + else {//First Frag or Mid Frag + if (uFragIdx == (uMACfragNum-2)) { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + } + if (bNeedAck) { + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + return (pDevice->uSIFS + uAckTime + uNextPktTime); + } else { + return (pDevice->uSIFS + uNextPktTime); + } + } + break; + + case DATADUR_A: //DATADUR_A + if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime); + } else { + return 0; + } + } + else {//First Frag or Mid Frag + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + } + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime + uNextPktTime); + } else { + return (pDevice->uSIFS + uNextPktTime); + } + } + break; + + case DATADUR_A_F0: //DATADUR_A_F0 + if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime); + } else { + return 0; + } + } + else { //First Frag or Mid Frag + if (byFBOption == AUTO_FB_0) { + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + } else { // (byFBOption == AUTO_FB_1) + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + } + + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime + uNextPktTime); + } else { + return (pDevice->uSIFS + uNextPktTime); + } + } + break; + + case DATADUR_A_F1: //DATADUR_A_F1 + if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime); + } else { + return 0; + } + } + else { //First Frag or Mid Frag + if (byFBOption == AUTO_FB_0) { + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + + } else { // (byFBOption == AUTO_FB_1) + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + } + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime + uNextPktTime); + } else { + return (pDevice->uSIFS + uNextPktTime); + } + } + break; + + default: + break; + } + + ASSERT(false); + return 0; +} + +//byFreqType: 0=>5GHZ 1=>2.4GHZ +static u32 s_uGetRTSCTSDuration(struct vnt_private *pDevice, u8 byDurType, + u32 cbFrameLength, u8 byPktType, u16 wRate, int bNeedAck, + u8 byFBOption) +{ + u32 uCTSTime = 0, uDurTime = 0; + + switch (byDurType) { + + case RTSDUR_BB: //RTSDuration_bb + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_BA: //RTSDuration_ba + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_AA: //RTSDuration_aa + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case CTSDUR_BA: //CTSDuration_ba + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_BA_F0: //RTSDuration_ba_f0 + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + break; + + case RTSDUR_AA_F0: //RTSDuration_aa_f0 + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + break; + + case RTSDUR_BA_F1: //RTSDuration_ba_f1 + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + break; + + case RTSDUR_AA_F1: //RTSDuration_aa_f1 + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + break; + + case CTSDUR_BA_F0: //CTSDuration_ba_f0 + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + break; + + case CTSDUR_BA_F1: //CTSDuration_ba_f1 + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + break; + + default: + break; + } + + return uDurTime; + +} + +static u32 s_uFillDataHead(struct vnt_private *pDevice, + u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength, + u32 uDMAIdx, int bNeedAck, u32 uFragIdx, u32 cbLastFragmentSize, + u32 uMACfragNum, u8 byFBOption) +{ + + if (pTxDataHead == NULL) { + return 0; + } + + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + if ((uDMAIdx == TYPE_ATIMDMA) || (uDMAIdx == TYPE_BEACONDMA)) { + PSTxDataHead_ab pBuf = (PSTxDataHead_ab) pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField) + ); + //Get Duration and TimeStampOff + pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption); //1: 2.4GHz + if(uDMAIdx!=TYPE_ATIMDMA) { + pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; + } + return (pBuf->wDuration); + } + else { // DATA & MANAGE Frame + if (byFBOption == AUTO_FB_NONE) { + PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + (u16 *)&(pBuf->wTransmitLength_a), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a) + ); + BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (u16 *)&(pBuf->wTransmitLength_b), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b) + ); + //Get Duration and TimeStamp + pBuf->wDuration_a = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, + byPktType, wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption); //1: 2.4GHz + pBuf->wDuration_b = (u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, + PK_TYPE_11B, pDevice->byTopCCKBasicRate, + bNeedAck, uFragIdx, cbLastFragmentSize, + uMACfragNum, byFBOption); //1: 2.4GHz + + pBuf->wTimeStampOff_a = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; + pBuf->wTimeStampOff_b = wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]; + return (pBuf->wDuration_a); + } else { + // Auto Fallback + PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + (u16 *)&(pBuf->wTransmitLength_a), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a) + ); + BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (u16 *)&(pBuf->wTransmitLength_b), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b) + ); + //Get Duration and TimeStamp + pBuf->wDuration_a = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz + pBuf->wDuration_b = (u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B, + pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz + pBuf->wDuration_a_f0 = (u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz + pBuf->wDuration_a_f1 = (u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz + pBuf->wTimeStampOff_a = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; + pBuf->wTimeStampOff_b = wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]; + return (pBuf->wDuration_a); + } //if (byFBOption == AUTO_FB_NONE) + } + } + else if (byPktType == PK_TYPE_11A) { + if ((byFBOption != AUTO_FB_NONE) && (uDMAIdx != TYPE_ATIMDMA) && (uDMAIdx != TYPE_BEACONDMA)) { + // Auto Fallback + PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField) + ); + //Get Duration and TimeStampOff + pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz + pBuf->wDuration_f0 = (u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz + pBuf->wDuration_f1 = (u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz + if(uDMAIdx!=TYPE_ATIMDMA) { + pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; + } + return (pBuf->wDuration); + } else { + PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField) + ); + //Get Duration and TimeStampOff + pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption); + + if(uDMAIdx!=TYPE_ATIMDMA) { + pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; + } + return (pBuf->wDuration); + } + } + else if (byPktType == PK_TYPE_11B) { + PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, + (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField) + ); + //Get Duration and TimeStampOff + pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption); + if (uDMAIdx != TYPE_ATIMDMA) { + pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; + } + return (pBuf->wDuration); + } + return 0; +} + +static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType, + void *pvRTS, u32 cbFrameLength, int bNeedAck, int bDisCRC, + struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption) +{ + u32 uRTSFrameLen = 20; + u16 wLen = 0; + + if (pvRTS == NULL) + return; + + if (bDisCRC) { + // When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame, + // in this case we need to decrease its length by 4. + uRTSFrameLen -= 4; + } + + // Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, so we don't need to take them into account. + // Otherwise, we need to modified codes for them. + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + if (byFBOption == AUTO_FB_NONE) { + PSRTS_g pBuf = (PSRTS_g)pvRTS; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a) + ); + pBuf->wTransmitLength_a = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration_bb = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData + pBuf->wDuration_aa = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3: 2.4G OFDMData + pBuf->wDuration_ba = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data + + pBuf->Data.wDurationID = pBuf->wDuration_aa; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + memcpy(&(pBuf->Data.abyRA[0]), + &(psEthHeader->h_dest[0]), + ETH_ALEN); + } + else { + memcpy(&(pBuf->Data.abyRA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } + if (pDevice->eOPMode == OP_MODE_AP) { + memcpy(&(pBuf->Data.abyTA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } + else { + memcpy(&(pBuf->Data.abyTA[0]), + &(psEthHeader->h_source[0]), + ETH_ALEN); + } + } + else { + PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a) + ); + pBuf->wTransmitLength_a = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration_bb = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData + pBuf->wDuration_aa = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3:2.4G OFDMData + pBuf->wDuration_ba = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDMData + pBuf->wRTSDuration_ba_f0 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //4:wRTSDuration_ba_f0, 1:2.4G, 1:CCKData + pBuf->wRTSDuration_aa_f0 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //5:wRTSDuration_aa_f0, 1:2.4G, 1:CCKData + pBuf->wRTSDuration_ba_f1 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //6:wRTSDuration_ba_f1, 1:2.4G, 1:CCKData + pBuf->wRTSDuration_aa_f1 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //7:wRTSDuration_aa_f1, 1:2.4G, 1:CCKData + pBuf->Data.wDurationID = pBuf->wDuration_aa; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + memcpy(&(pBuf->Data.abyRA[0]), + &(psEthHeader->h_dest[0]), + ETH_ALEN); + } + else { + memcpy(&(pBuf->Data.abyRA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } + + if (pDevice->eOPMode == OP_MODE_AP) { + memcpy(&(pBuf->Data.abyTA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } + else { + memcpy(&(pBuf->Data.abyTA[0]), + &(psEthHeader->h_source[0]), + ETH_ALEN); + } + + } // if (byFBOption == AUTO_FB_NONE) + } + else if (byPktType == PK_TYPE_11A) { + if (byFBOption == AUTO_FB_NONE) { + PSRTS_ab pBuf = (PSRTS_ab)pvRTS; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData + pBuf->Data.wDurationID = pBuf->wDuration; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + memcpy(&(pBuf->Data.abyRA[0]), + &(psEthHeader->h_dest[0]), + ETH_ALEN); + } else { + memcpy(&(pBuf->Data.abyRA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } + + if (pDevice->eOPMode == OP_MODE_AP) { + memcpy(&(pBuf->Data.abyTA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } else { + memcpy(&(pBuf->Data.abyTA[0]), + &(psEthHeader->h_source[0]), + ETH_ALEN); + } + + } + else { + PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData + pBuf->wRTSDuration_f0 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //5:RTSDuration_aa_f0, 0:5G, 0: 5G OFDMData + pBuf->wRTSDuration_f1 = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //7:RTSDuration_aa_f1, 0:5G, 0: + pBuf->Data.wDurationID = pBuf->wDuration; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + memcpy(&(pBuf->Data.abyRA[0]), + &(psEthHeader->h_dest[0]), + ETH_ALEN); + } else { + memcpy(&(pBuf->Data.abyRA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } + if (pDevice->eOPMode == OP_MODE_AP) { + memcpy(&(pBuf->Data.abyTA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } else { + memcpy(&(pBuf->Data.abyTA[0]), + &(psEthHeader->h_source[0]), + ETH_ALEN); + } + } + } + else if (byPktType == PK_TYPE_11B) { + PSRTS_ab pBuf = (PSRTS_ab)pvRTS; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData + pBuf->Data.wDurationID = pBuf->wDuration; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + memcpy(&(pBuf->Data.abyRA[0]), + &(psEthHeader->h_dest[0]), + ETH_ALEN); + } + else { + memcpy(&(pBuf->Data.abyRA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } + + if (pDevice->eOPMode == OP_MODE_AP) { + memcpy(&(pBuf->Data.abyTA[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } else { + memcpy(&(pBuf->Data.abyTA[0]), + &(psEthHeader->h_source[0]), + ETH_ALEN); + } + } +} + +static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx, + u8 byPktType, void *pvCTS, u32 cbFrameLength, int bNeedAck, + int bDisCRC, u16 wCurrentRate, u8 byFBOption) +{ + u32 uCTSFrameLen = 14; + u16 wLen = 0; + + if (pvCTS == NULL) { + return; + } + + if (bDisCRC) { + // When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame, + // in this case we need to decrease its length by 4. + uCTSFrameLen -= 4; + } + + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) { + // Auto Fall back + PSCTS_FB pBuf = (PSCTS_FB)pvCTS; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + pBuf->wDuration_ba = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data + pBuf->wDuration_ba += pDevice->wCTSDuration; + pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba); + //Get CTSDuration_ba_f0 + pBuf->wCTSDuration_ba_f0 = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data + pBuf->wCTSDuration_ba_f0 += pDevice->wCTSDuration; + pBuf->wCTSDuration_ba_f0 = cpu_to_le16(pBuf->wCTSDuration_ba_f0); + //Get CTSDuration_ba_f1 + pBuf->wCTSDuration_ba_f1 = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data + pBuf->wCTSDuration_ba_f1 += pDevice->wCTSDuration; + pBuf->wCTSDuration_ba_f1 = cpu_to_le16(pBuf->wCTSDuration_ba_f1); + //Get CTS Frame body + pBuf->Data.wDurationID = pBuf->wDuration_ba; + pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4 + pBuf->Data.wReserved = 0x0000; + memcpy(&(pBuf->Data.abyRA[0]), + &(pDevice->abyCurrentNetAddr[0]), + ETH_ALEN); + } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) + PSCTS pBuf = (PSCTS)pvCTS; + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + //Get CTSDuration_ba + pBuf->wDuration_ba = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data + pBuf->wDuration_ba += pDevice->wCTSDuration; + pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba); + + //Get CTS Frame body + pBuf->Data.wDurationID = pBuf->wDuration_ba; + pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4 + pBuf->Data.wReserved = 0x0000; + memcpy(&(pBuf->Data.abyRA[0]), + &(pDevice->abyCurrentNetAddr[0]), + ETH_ALEN); + } + } +} + +/*+ + * + * Description: + * Generate FIFO control for MAC & Baseband controller + * + * Parameters: + * In: + * pDevice - Pointer to adpater + * pTxDataHead - Transmit Data Buffer + * pTxBufHead - pTxBufHead + * pvRrvTime - pvRrvTime + * pvRTS - RTS Buffer + * pCTS - CTS Buffer + * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS) + * bNeedACK - If need ACK + * uDMAIdx - DMA Index + * Out: + * none + * + * Return Value: none + * +-*/ + +static void s_vGenerateTxParameter(struct vnt_private *pDevice, + u8 byPktType, u16 wCurrentRate, void *pTxBufHead, void *pvRrvTime, + void *pvRTS, void *pvCTS, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx, + struct ethhdr *psEthHeader) +{ + u32 cbMACHdLen = WLAN_HDR_ADDR3_LEN; /* 24 */ + u16 wFifoCtl; + int bDisCRC = false; + u8 byFBOption = AUTO_FB_NONE; + + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter...\n"); + PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead; + pFifoHead->wReserved = wCurrentRate; + wFifoCtl = pFifoHead->wFIFOCtl; + + if (wFifoCtl & FIFOCTL_CRCDIS) { + bDisCRC = true; + } + + if (wFifoCtl & FIFOCTL_AUTO_FB_0) { + byFBOption = AUTO_FB_0; + } + else if (wFifoCtl & FIFOCTL_AUTO_FB_1) { + byFBOption = AUTO_FB_1; + } + + if (pDevice->bLongHeader) + cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; + + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + + if (pvRTS != NULL) { //RTS_need + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_gRTS pBuf = (PSRrvTime_gRTS)pvRrvTime; + pBuf->wRTSTxRrvTime_aa = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 1:2.4GHz + pBuf->wRTSTxRrvTime_ba = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate));//1:RTSTxRrvTime_ba, 1:2.4GHz + pBuf->wRTSTxRrvTime_bb = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz + pBuf->wTxRrvTime_a = cpu_to_le16((u16) s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM + pBuf->wTxRrvTime_b = cpu_to_le16((u16) s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK + } + //Fill RTS + s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } + else {//RTS_needless, PCF mode + + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_gCTS pBuf = (PSRrvTime_gCTS)pvRrvTime; + pBuf->wTxRrvTime_a = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM + pBuf->wTxRrvTime_b = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK + pBuf->wCTSTxRrvTime_ba = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate));//3:CTSTxRrvTime_Ba, 1:2.4GHz + } + //Fill CTS + s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption); + } + } + else if (byPktType == PK_TYPE_11A) { + + if (pvRTS != NULL) {//RTS_need, non PCF mode + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; + pBuf->wRTSTxRrvTime = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 0:5GHz + pBuf->wTxRrvTime = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//0:OFDM + } + //Fill RTS + s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } + else if (pvRTS == NULL) {//RTS_needless, non PCF mode + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; + pBuf->wTxRrvTime = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK)); //0:OFDM + } + } + } + else if (byPktType == PK_TYPE_11B) { + + if ((pvRTS != NULL)) {//RTS_need, non PCF mode + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; + pBuf->wRTSTxRrvTime = cpu_to_le16((u16)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz + pBuf->wTxRrvTime = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK));//1:CCK + } + //Fill RTS + s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } + else { //RTS_needless, non PCF mode + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; + pBuf->wTxRrvTime = cpu_to_le16((u16)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK)); //1:CCK + } + } + } + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n"); +} +/* + u8 * pbyBuffer,//point to pTxBufHead + u16 wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last + unsigned int cbFragmentSize,//Hdr+payoad+FCS +*/ + +static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType, + u8 *usbPacketBuf, int bNeedEncryption, u32 uSkbPacketLen, u32 uDMAIdx, + struct ethhdr *psEthHeader, u8 *pPacket, PSKeyItem pTransmitKey, + u32 uNodeIndex, u16 wCurrentRate, u32 *pcbHeaderLen, u32 *pcbTotalLen) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u32 cbFrameSize, cbFrameBodySize; + PTX_BUFFER pTxBufHead; + u32 cb802_1_H_len; + u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbMACHdLen = 0; + u32 cbFCSlen = 4, cbMICHDR = 0; + int bNeedACK, bRTS; + u8 *pbyType, *pbyMacHdr, *pbyIVHead, *pbyPayloadHead, *pbyTxBufferAddr; + u8 abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; + u8 abySNAP_Bridgetunnel[ETH_ALEN] + = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8}; + u32 uDuration; + u32 cbHeaderLength = 0, uPadding = 0; + void *pvRrvTime; + PSMICHDRHead pMICHDR; + void *pvRTS; + void *pvCTS; + void *pvTxDataHd; + u8 byFBOption = AUTO_FB_NONE, byFragType; + u16 wTxBufSize; + u32 dwMICKey0, dwMICKey1, dwMIC_Priority, dwCRC; + u32 *pdwMIC_L, *pdwMIC_R; + int bSoftWEP = false; + + pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL; + + if (bNeedEncryption && pTransmitKey->pvKeyTable) { + if (((PSKeyTable)pTransmitKey->pvKeyTable)->bSoftWEP == true) + bSoftWEP = true; /* WEP 256 */ + } + + pTxBufHead = (PTX_BUFFER) usbPacketBuf; + memset(pTxBufHead, 0, sizeof(TX_BUFFER)); + + // Get pkt type + if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) { + if (pDevice->dwDiagRefCount == 0) { + cb802_1_H_len = 8; + } else { + cb802_1_H_len = 2; + } + } else { + cb802_1_H_len = 0; + } + + cbFrameBodySize = uSkbPacketLen - ETH_HLEN + cb802_1_H_len; + + //Set packet type + pTxBufHead->wFIFOCtl |= (u16)(byPktType<<8); + + if (pDevice->dwDiagRefCount != 0) { + bNeedACK = false; + pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK); + } else { //if (pDevice->dwDiagRefCount != 0) { + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + if (is_multicast_ether_addr(psEthHeader->h_dest)) { + bNeedACK = false; + pTxBufHead->wFIFOCtl = + pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK); + } else { + bNeedACK = true; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + } + } + else { + // MSDUs in Infra mode always need ACK + bNeedACK = true; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + } + } //if (pDevice->dwDiagRefCount != 0) { + + pTxBufHead->wTimeStamp = DEFAULT_MSDU_LIFETIME_RES_64us; + + //Set FIFOCTL_LHEAD + if (pDevice->bLongHeader) + pTxBufHead->wFIFOCtl |= FIFOCTL_LHEAD; + + if (pDevice->bSoftwareGenCrcErr) { + pTxBufHead->wFIFOCtl |= FIFOCTL_CRCDIS; // set tx descriptors to NO hardware CRC + } + + //Set FRAGCTL_MACHDCNT + if (pDevice->bLongHeader) { + cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; + } else { + cbMACHdLen = WLAN_HDR_ADDR3_LEN; + } + pTxBufHead->wFragCtl |= (u16)(cbMACHdLen << 10); + + //Set FIFOCTL_GrpAckPolicy + if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; + } + + //Set Auto Fallback Ctl + if (wCurrentRate >= RATE_18M) { + if (pDevice->byAutoFBCtrl == AUTO_FB_0) { + pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0; + byFBOption = AUTO_FB_0; + } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) { + pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1; + byFBOption = AUTO_FB_1; + } + } + + if (bSoftWEP != true) { + if ((bNeedEncryption) && (pTransmitKey != NULL)) { //WEP enabled + if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //WEP40 or WEP104 + pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; + } + if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Tx Set wFragCtl == FRAGCTL_TKIP\n"); + pTxBufHead->wFragCtl |= FRAGCTL_TKIP; + } + else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { //CCMP + pTxBufHead->wFragCtl |= FRAGCTL_AES; + } + } + } + + if ((bNeedEncryption) && (pTransmitKey != NULL)) { + if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { + cbIVlen = 4; + cbICVlen = 4; + } + else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + cbIVlen = 8;//IV+ExtIV + cbMIClen = 8; + cbICVlen = 4; + } + if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { + cbIVlen = 8;//RSN Header + cbICVlen = 8;//MIC + cbMICHDR = sizeof(SMICHDRHead); + } + if (bSoftWEP == false) { + //MAC Header should be padding 0 to DW alignment. + uPadding = 4 - (cbMACHdLen%4); + uPadding %= 4; + } + } + + cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen; + + if ( (bNeedACK == false) ||(cbFrameSize < pDevice->wRTSThreshold) ) { + bRTS = false; + } else { + bRTS = true; + pTxBufHead->wFIFOCtl |= (FIFOCTL_RTS | FIFOCTL_LRETRY); + } + + pbyTxBufferAddr = (u8 *) &(pTxBufHead->adwTxKey[0]); + wTxBufSize = sizeof(STxBufHead); + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet + if (byFBOption == AUTO_FB_NONE) { + if (bRTS == true) {//RTS_need + pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS)); + pvRTS = (PSRTS_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g)); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g) + sizeof(STxDataHead_g); + } + else { //RTS_needless + pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); + pvRTS = NULL; + pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); + pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS)); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g); + } + } else { + // Auto Fall Back + if (bRTS == true) {//RTS_need + pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS)); + pvRTS = (PSRTS_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB)); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB) + sizeof(STxDataHead_g_FB); + } + else if (bRTS == false) { //RTS_needless + pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); + pvRTS = NULL; + pvCTS = (PSCTS_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); + pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB)); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB) + sizeof(STxDataHead_g_FB); + } + } // Auto Fall Back + } + else {//802.11a/b packet + if (byFBOption == AUTO_FB_NONE) { + if (bRTS == true) {//RTS_need + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = (PSRTS_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab)); + cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab) + sizeof(STxDataHead_ab); + } + else if (bRTS == false) { //RTS_needless, no MICHDR + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = NULL; + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab); + } + } else { + // Auto Fall Back + if (bRTS == true) {//RTS_need + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = (PSRTS_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB)); + cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB) + sizeof(STxDataHead_a_FB); + } + else if (bRTS == false) { //RTS_needless + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = NULL; + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_a_FB); + } + } // Auto Fall Back + } + + pbyMacHdr = (u8 *)(pbyTxBufferAddr + cbHeaderLength); + pbyIVHead = (u8 *)(pbyMacHdr + cbMACHdLen + uPadding); + pbyPayloadHead = (u8 *)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen); + + //========================= + // No Fragmentation + //========================= + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Fragmentation...\n"); + byFragType = FRAGCTL_NONFRAG; + //uDMAIdx = TYPE_AC0DMA; + //pTxBufHead = (PSTxBufHead) &(pTxBufHead->adwTxKey[0]); + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate, + (void *)pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS, + cbFrameSize, bNeedACK, uDMAIdx, psEthHeader); + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK, + 0, 0, 1/*uMACfragNum*/, byFBOption); + // Generate TX MAC Header + s_vGenerateMACHeader(pDevice, pbyMacHdr, (u16)uDuration, psEthHeader, bNeedEncryption, + byFragType, uDMAIdx, 0); + + if (bNeedEncryption == true) { + //Fill TXKEY + s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (u16)cbFrameBodySize, (u8 *)pMICHDR); + + if (pDevice->bEnableHostWEP) { + pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; + pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; + } + } + + // 802.1H + if (ntohs(psEthHeader->h_proto) > ETH_DATA_LEN) { + if (pDevice->dwDiagRefCount == 0) { + if ((psEthHeader->h_proto == cpu_to_be16(ETH_P_IPX)) || + (psEthHeader->h_proto == cpu_to_le16(0xF380))) { + memcpy((u8 *) (pbyPayloadHead), + abySNAP_Bridgetunnel, 6); + } else { + memcpy((u8 *) (pbyPayloadHead), &abySNAP_RFC1042[0], 6); + } + pbyType = (u8 *) (pbyPayloadHead + 6); + memcpy(pbyType, &(psEthHeader->h_proto), sizeof(u16)); + } else { + memcpy((u8 *) (pbyPayloadHead), &(psEthHeader->h_proto), sizeof(u16)); + + } + + } + + if (pPacket != NULL) { + // Copy the Packet into a tx Buffer + memcpy((pbyPayloadHead + cb802_1_H_len), + (pPacket + ETH_HLEN), + uSkbPacketLen - ETH_HLEN + ); + + } else { + // while bRelayPacketSend psEthHeader is point to header+payload + memcpy((pbyPayloadHead + cb802_1_H_len), ((u8 *)psEthHeader) + ETH_HLEN, uSkbPacketLen - ETH_HLEN); + } + + ASSERT(uLength == cbNdisBodySize); + + if ((bNeedEncryption == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { + + /////////////////////////////////////////////////////////////////// + + if (pDevice->vnt_mgmt.eAuthenMode == WMAC_AUTH_WPANONE) { + dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]); + } + else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) { + dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]); + } + else { + dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[24]); + dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[28]); + } + // DO Software Michael + MIC_vInit(dwMICKey0, dwMICKey1); + MIC_vAppend((u8 *)&(psEthHeader->h_dest[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((u8 *)&dwMIC_Priority, 4); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n", + dwMICKey0, dwMICKey1); + + /////////////////////////////////////////////////////////////////// + + //DBG_PRN_GRP12(("Length:%d, %d\n", cbFrameBodySize, uFromHDtoPLDLength)); + //for (ii = 0; ii < cbFrameBodySize; ii++) { + // DBG_PRN_GRP12(("%02x ", *((u8 *)((pbyPayloadHead + cb802_1_H_len) + ii)))); + //} + //DBG_PRN_GRP12(("\n\n\n")); + + MIC_vAppend(pbyPayloadHead, cbFrameBodySize); + + pdwMIC_L = (u32 *)(pbyPayloadHead + cbFrameBodySize); + pdwMIC_R = (u32 *)(pbyPayloadHead + cbFrameBodySize + 4); + + MIC_vGetMIC(pdwMIC_L, pdwMIC_R); + MIC_vUnInit(); + + if (pDevice->bTxMICFail == true) { + *pdwMIC_L = 0; + *pdwMIC_R = 0; + pDevice->bTxMICFail = false; + } + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderLength, uPadding, cbIVlen); + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R); + } + + if (bSoftWEP == true) { + + s_vSWencryption(pDevice, pTransmitKey, (pbyPayloadHead), (u16)(cbFrameBodySize + cbMIClen)); + + } else if ( ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) && (bNeedEncryption == true)) || + ((pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) && (bNeedEncryption == true)) || + ((pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) && (bNeedEncryption == true)) ) { + cbFrameSize -= cbICVlen; + } + + if (pDevice->bSoftwareGenCrcErr == true) { + unsigned int cbLen; + u32 * pdwCRC; + + dwCRC = 0xFFFFFFFFL; + cbLen = cbFrameSize - cbFCSlen; + // calculate CRC, and wrtie CRC value to end of TD + dwCRC = CRCdwGetCrc32Ex(pbyMacHdr, cbLen, dwCRC); + pdwCRC = (u32 *)(pbyMacHdr + cbLen); + // finally, we must invert dwCRC to get the correct answer + *pdwCRC = ~dwCRC; + // Force Error + *pdwCRC -= 1; + } else { + cbFrameSize -= cbFCSlen; + } + + *pcbHeaderLen = cbHeaderLength; + *pcbTotalLen = cbHeaderLength + cbFrameSize ; + + //Set FragCtl in TxBufferHead + pTxBufHead->wFragCtl |= (u16)byFragType; + + return true; + +} + +/*+ + * + * Description: + * Translate 802.3 to 802.11 header + * + * Parameters: + * In: + * pDevice - Pointer to adapter + * dwTxBufferAddr - Transmit Buffer + * pPacket - Packet from upper layer + * cbPacketSize - Transmit Data Length + * Out: + * pcbHeadSize - Header size of MAC&Baseband control and 802.11 Header + * pcbAppendPayload - size of append payload for 802.1H translation + * + * Return Value: none + * +-*/ + +static void s_vGenerateMACHeader(struct vnt_private *pDevice, + u8 *pbyBufferAddr, u16 wDuration, struct ethhdr *psEthHeader, + int bNeedEncrypt, u16 wFragType, u32 uDMAIdx, u32 uFragIdx) +{ + struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *)pbyBufferAddr; + + memset(pMACHeader, 0, (sizeof(struct ieee80211_hdr))); + + if (uDMAIdx == TYPE_ATIMDMA) { + pMACHeader->frame_control = TYPE_802_11_ATIM; + } else { + pMACHeader->frame_control = TYPE_802_11_DATA; + } + + if (pDevice->eOPMode == OP_MODE_AP) { + memcpy(&(pMACHeader->addr1[0]), + &(psEthHeader->h_dest[0]), + ETH_ALEN); + memcpy(&(pMACHeader->addr2[0]), &(pDevice->abyBSSID[0]), ETH_ALEN); + memcpy(&(pMACHeader->addr3[0]), + &(psEthHeader->h_source[0]), + ETH_ALEN); + pMACHeader->frame_control |= FC_FROMDS; + } else { + if (pDevice->eOPMode == OP_MODE_ADHOC) { + memcpy(&(pMACHeader->addr1[0]), + &(psEthHeader->h_dest[0]), + ETH_ALEN); + memcpy(&(pMACHeader->addr2[0]), + &(psEthHeader->h_source[0]), + ETH_ALEN); + memcpy(&(pMACHeader->addr3[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + } else { + memcpy(&(pMACHeader->addr3[0]), + &(psEthHeader->h_dest[0]), + ETH_ALEN); + memcpy(&(pMACHeader->addr2[0]), + &(psEthHeader->h_source[0]), + ETH_ALEN); + memcpy(&(pMACHeader->addr1[0]), + &(pDevice->abyBSSID[0]), + ETH_ALEN); + pMACHeader->frame_control |= FC_TODS; + } + } + + if (bNeedEncrypt) + pMACHeader->frame_control |= cpu_to_le16((u16)WLAN_SET_FC_ISWEP(1)); + + pMACHeader->duration_id = cpu_to_le16(wDuration); + + if (pDevice->bLongHeader) { + PWLAN_80211HDR_A4 pMACA4Header = (PWLAN_80211HDR_A4) pbyBufferAddr; + pMACHeader->frame_control |= (FC_TODS | FC_FROMDS); + memcpy(pMACA4Header->abyAddr4, pDevice->abyBSSID, WLAN_ADDR_LEN); + } + pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4); + + //Set FragNumber in Sequence Control + pMACHeader->seq_ctrl |= cpu_to_le16((u16)uFragIdx); + + if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) { + pDevice->wSeqCounter++; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; + } + + if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) { //StartFrag or MidFrag + pMACHeader->frame_control |= FC_MOREFRAG; + } +} + +/*+ + * + * Description: + * Request instructs a MAC to transmit a 802.11 management packet through + * the adapter onto the medium. + * + * Parameters: + * In: + * hDeviceContext - Pointer to the adapter + * pPacket - A pointer to a descriptor for the packet to transmit + * Out: + * none + * + * Return Value: CMD_STATUS_PENDING if MAC Tx resource available; otherwise false + * +-*/ + +CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice, + struct vnt_tx_mgmt *pPacket) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PTX_BUFFER pTX_Buffer; + PSTxBufHead pTxBufHead; + PUSB_SEND_CONTEXT pContext; + struct ieee80211_hdr *pMACHeader; + PSCTS pCTS; + struct ethhdr sEthHeader; + u8 byPktType, *pbyTxBufferAddr; + void *pvRTS, *pvTxDataHd, *pvRrvTime, *pMICHDR; + u32 uDuration, cbReqCount, cbHeaderSize, cbFrameBodySize, cbFrameSize; + int bNeedACK, bIsPSPOLL = false; + u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4; + u32 uPadding = 0; + u16 wTxBufSize; + u32 cbMacHdLen; + u16 wCurrentRate = RATE_1M; + + pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); + + if (NULL == pContext) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ManagementSend TX...NO CONTEXT!\n"); + return CMD_STATUS_RESOURCES; + } + + pTX_Buffer = (PTX_BUFFER) (&pContext->Data[0]); + pbyTxBufferAddr = (u8 *)&(pTX_Buffer->adwTxKey[0]); + cbFrameBodySize = pPacket->cbPayloadLen; + pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; + wTxBufSize = sizeof(STxBufHead); + memset(pTxBufHead, 0, wTxBufSize); + + if (pDevice->byBBType == BB_TYPE_11A) { + wCurrentRate = RATE_6M; + byPktType = PK_TYPE_11A; + } else { + wCurrentRate = RATE_1M; + byPktType = PK_TYPE_11B; + } + + // SetPower will cause error power TX state for OFDM Date packet in TX buffer. + // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability. + // And cmd timer will wait data pkt TX finish before scanning so it's OK + // to set power here. + if (pMgmt->eScanState != WMAC_NO_SCANNING) { + RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh); + } else { + RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel); + } + pDevice->wCurrentRate = wCurrentRate; + + //Set packet type + if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000 + pTxBufHead->wFIFOCtl = 0; + } + else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11B; + } + else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GB; + } + else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GA; + } + + pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN; + pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); + + if (is_multicast_ether_addr(pPacket->p80211Header->sA3.abyAddr1)) { + bNeedACK = false; + } + else { + bNeedACK = true; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + }; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || + (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) { + + pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY; + //Set Preamble type always long + //pDevice->byPreambleType = PREAMBLE_LONG; + // probe-response don't retry + //if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) { + // bNeedACK = false; + // pTxBufHead->wFIFOCtl &= (~FIFOCTL_NEEDACK); + //} + } + + pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0); + + if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) { + bIsPSPOLL = true; + cbMacHdLen = WLAN_HDR_ADDR2_LEN; + } else { + cbMacHdLen = WLAN_HDR_ADDR3_LEN; + } + + //Set FRAGCTL_MACHDCNT + pTxBufHead->wFragCtl |= cpu_to_le16((u16)(cbMacHdLen << 10)); + + // Notes: + // Although spec says MMPDU can be fragmented; In most case, + // no one will send a MMPDU under fragmentation. With RTS may occur. + pDevice->bAES = false; //Set FRAGCTL_WEPTYP + + if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) { + if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) { + cbIVlen = 4; + cbICVlen = 4; + pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; + } + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + cbIVlen = 8;//IV+ExtIV + cbMIClen = 8; + cbICVlen = 4; + pTxBufHead->wFragCtl |= FRAGCTL_TKIP; + //We need to get seed here for filling TxKey entry. + //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, + // pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); + } + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + cbIVlen = 8;//RSN Header + cbICVlen = 8;//MIC + pTxBufHead->wFragCtl |= FRAGCTL_AES; + pDevice->bAES = true; + } + //MAC Header should be padding 0 to DW alignment. + uPadding = 4 - (cbMacHdLen%4); + uPadding %= 4; + } + + cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen; + + //Set FIFOCTL_GrpAckPolicy + if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; + } + //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter() + + //Set RrvTime/RTS/CTS Buffer + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet + + pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = NULL; + pvRTS = NULL; + pCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); + pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS)); + cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS) + sizeof(STxDataHead_g); + } + else { // 802.11a/b packet + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = NULL; + pvRTS = NULL; + pCTS = NULL; + pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + sizeof(STxDataHead_ab); + } + + memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, + (cbHeaderSize - wTxBufSize)); + + memcpy(&(sEthHeader.h_dest[0]), + &(pPacket->p80211Header->sA3.abyAddr1[0]), + ETH_ALEN); + memcpy(&(sEthHeader.h_source[0]), + &(pPacket->p80211Header->sA3.abyAddr2[0]), + ETH_ALEN); + //========================= + // No Fragmentation + //========================= + pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG; + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate, pbyTxBufferAddr, pvRrvTime, pvRTS, pCTS, + cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader); + + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK, + 0, 0, 1, AUTO_FB_NONE); + + pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize); + + cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize; + + if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) { + u8 * pbyIVHead; + u8 * pbyPayloadHead; + u8 * pbyBSSID; + PSKeyItem pTransmitKey = NULL; + + pbyIVHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding); + pbyPayloadHead = (u8 *)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen); + do { + if ((pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) && + (pDevice->bLinkPass == true)) { + pbyBSSID = pDevice->abyBSSID; + // get pairwise key + if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) { + // get group key + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n"); + break; + } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get PTK.\n"); + break; + } + } + // get group key + pbyBSSID = pDevice->abyBroadcastAddr; + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) { + pTransmitKey = NULL; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KEY is NULL. OP Mode[%d]\n", pDevice->eOPMode); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n"); + } + } while(false); + //Fill TXKEY + s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + (u8 *)pMACHeader, (u16)cbFrameBodySize, NULL); + + memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen); + memcpy(pbyPayloadHead, ((u8 *)(pPacket->p80211Header) + cbMacHdLen), + cbFrameBodySize); + } + else { + // Copy the Packet into a tx Buffer + memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen); + } + + pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4); + pDevice->wSeqCounter++ ; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; + + if (bIsPSPOLL) { + // The MAC will automatically replace the Duration-field of MAC header by Duration-field + // of FIFO control header. + // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is + // in the same place of other packet's Duration-field). + // And it will cause Cisco-AP to issue Disassociation-packet + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + ((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); + ((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); + } else { + ((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); + } + } + + pTX_Buffer->wTxByteCount = cpu_to_le16((u16)(cbReqCount)); + pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); + pTX_Buffer->byType = 0x00; + + pContext->pPacket = NULL; + pContext->Type = CONTEXT_MGMT_PACKET; + pContext->uBufLen = (u16)cbReqCount + 4; //USB header + + if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) { + s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl); + } + else { + s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl); + } + + PIPEnsSendBulkOut(pDevice,pContext); + return CMD_STATUS_PENDING; +} + +CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice, + struct vnt_tx_mgmt *pPacket) +{ + u32 cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN; + u32 cbHeaderSize = 0; + u16 wTxBufSize = sizeof(STxShortBufHead); + PSTxShortBufHead pTxBufHead; + struct ieee80211_hdr *pMACHeader; + PSTxDataHead_ab pTxDataHead; + u16 wCurrentRate; + u32 cbFrameBodySize; + u32 cbReqCount; + PBEACON_BUFFER pTX_Buffer; + u8 *pbyTxBufferAddr; + PUSB_SEND_CONTEXT pContext; + CMD_STATUS status; + + pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); + if (NULL == pContext) { + status = CMD_STATUS_RESOURCES; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ManagementSend TX...NO CONTEXT!\n"); + return status ; + } + pTX_Buffer = (PBEACON_BUFFER) (&pContext->Data[0]); + pbyTxBufferAddr = (u8 *)&(pTX_Buffer->wFIFOCtl); + + cbFrameBodySize = pPacket->cbPayloadLen; + + pTxBufHead = (PSTxShortBufHead) pbyTxBufferAddr; + wTxBufSize = sizeof(STxShortBufHead); + memset(pTxBufHead, 0, wTxBufSize); + + if (pDevice->byBBType == BB_TYPE_11A) { + wCurrentRate = RATE_6M; + pTxDataHead = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize); + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11A, + (u16 *)&(pTxDataHead->wTransmitLength), (u8 *)&(pTxDataHead->byServiceField), (u8 *)&(pTxDataHead->bySignalField) + ); + //Get Duration and TimeStampOff + pTxDataHead->wDuration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameSize, PK_TYPE_11A, + wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE)); + pTxDataHead->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; + cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab); + } else { + wCurrentRate = RATE_1M; + pTxBufHead->wFIFOCtl |= FIFOCTL_11B; + pTxDataHead = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize); + //Get SignalField,ServiceField,Length + BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11B, + (u16 *)&(pTxDataHead->wTransmitLength), (u8 *)&(pTxDataHead->byServiceField), (u8 *)&(pTxDataHead->bySignalField) + ); + //Get Duration and TimeStampOff + pTxDataHead->wDuration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameSize, PK_TYPE_11B, + wCurrentRate, false, 0, 0, 1, AUTO_FB_NONE)); + pTxDataHead->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; + cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab); + } + + //Generate Beacon Header + pMACHeader = (struct ieee80211_hdr *)(pbyTxBufferAddr + cbHeaderSize); + memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen); + + pMACHeader->duration_id = 0; + pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4); + pDevice->wSeqCounter++ ; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; + + cbReqCount = cbHeaderSize + WLAN_HDR_ADDR3_LEN + cbFrameBodySize; + + pTX_Buffer->wTxByteCount = (u16)cbReqCount; + pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); + pTX_Buffer->byType = 0x01; + + pContext->pPacket = NULL; + pContext->Type = CONTEXT_MGMT_PACKET; + pContext->uBufLen = (u16)cbReqCount + 4; //USB header + + PIPEnsSendBulkOut(pDevice,pContext); + return CMD_STATUS_PENDING; + +} + +void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u8 byPktType; + u8 *pbyTxBufferAddr; + void *pvRTS, *pvCTS, *pvTxDataHd; + u32 uDuration, cbReqCount; + struct ieee80211_hdr *pMACHeader; + u32 cbHeaderSize, cbFrameBodySize; + int bNeedACK, bIsPSPOLL = false; + PSTxBufHead pTxBufHead; + u32 cbFrameSize; + u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4; + u32 uPadding = 0; + u32 cbMICHDR = 0, uLength = 0; + u32 dwMICKey0, dwMICKey1; + u32 dwMIC_Priority; + u32 *pdwMIC_L, *pdwMIC_R; + u16 wTxBufSize; + u32 cbMacHdLen; + struct ethhdr sEthHeader; + void *pvRrvTime, *pMICHDR; + u32 wCurrentRate = RATE_1M; + PUWLAN_80211HDR p80211Header; + u32 uNodeIndex = 0; + int bNodeExist = false; + SKeyItem STempKey; + PSKeyItem pTransmitKey = NULL; + u8 *pbyIVHead, *pbyPayloadHead, *pbyMacHdr; + u32 cbExtSuppRate = 0; + PTX_BUFFER pTX_Buffer; + PUSB_SEND_CONTEXT pContext; + + pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL; + + if(skb->len <= WLAN_HDR_ADDR3_LEN) { + cbFrameBodySize = 0; + } + else { + cbFrameBodySize = skb->len - WLAN_HDR_ADDR3_LEN; + } + p80211Header = (PUWLAN_80211HDR)skb->data; + + pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); + + if (NULL == pContext) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0 TX...NO CONTEXT!\n"); + dev_kfree_skb_irq(skb); + return ; + } + + pTX_Buffer = (PTX_BUFFER)(&pContext->Data[0]); + pbyTxBufferAddr = (u8 *)(&pTX_Buffer->adwTxKey[0]); + pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; + wTxBufSize = sizeof(STxBufHead); + memset(pTxBufHead, 0, wTxBufSize); + + if (pDevice->byBBType == BB_TYPE_11A) { + wCurrentRate = RATE_6M; + byPktType = PK_TYPE_11A; + } else { + wCurrentRate = RATE_1M; + byPktType = PK_TYPE_11B; + } + + // SetPower will cause error power TX state for OFDM Date packet in TX buffer. + // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability. + // And cmd timer will wait data pkt TX finish before scanning so it's OK + // to set power here. + if (pMgmt->eScanState != WMAC_NO_SCANNING) { + RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh); + } else { + RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel); + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vDMA0_tx_80211: p80211Header->sA3.wFrameCtl = %x \n", p80211Header->sA3.wFrameCtl); + + //Set packet type + if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000 + pTxBufHead->wFIFOCtl = 0; + } + else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11B; + } + else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GB; + } + else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GA; + } + + pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN; + pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); + + if (is_multicast_ether_addr(p80211Header->sA3.abyAddr1)) { + bNeedACK = false; + if (pDevice->bEnableHostWEP) { + uNodeIndex = 0; + bNodeExist = true; + } + } + else { + if (pDevice->bEnableHostWEP) { + if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(p80211Header->sA3.abyAddr1), &uNodeIndex)) + bNodeExist = true; + } + bNeedACK = true; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + }; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || + (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) { + + pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY; + //Set Preamble type always long + //pDevice->byPreambleType = PREAMBLE_LONG; + + // probe-response don't retry + //if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) { + // bNeedACK = false; + // pTxBufHead->wFIFOCtl &= (~FIFOCTL_NEEDACK); + //} + } + + pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0); + + if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) { + bIsPSPOLL = true; + cbMacHdLen = WLAN_HDR_ADDR2_LEN; + } else { + cbMacHdLen = WLAN_HDR_ADDR3_LEN; + } + + // hostapd daemon ext support rate patch + if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) { + + if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) { + cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN; + } + + if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0) { + cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + } + + if (cbExtSuppRate >0) { + cbFrameBodySize = WLAN_ASSOCRESP_OFF_SUPP_RATES; + } + } + + //Set FRAGCTL_MACHDCNT + pTxBufHead->wFragCtl |= cpu_to_le16((u16)cbMacHdLen << 10); + + // Notes: + // Although spec says MMPDU can be fragmented; In most case, + // no one will send a MMPDU under fragmentation. With RTS may occur. + pDevice->bAES = false; //Set FRAGCTL_WEPTYP + + if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) { + if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) { + cbIVlen = 4; + cbICVlen = 4; + pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; + } + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + cbIVlen = 8;//IV+ExtIV + cbMIClen = 8; + cbICVlen = 4; + pTxBufHead->wFragCtl |= FRAGCTL_TKIP; + //We need to get seed here for filling TxKey entry. + //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, + // pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); + } + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + cbIVlen = 8;//RSN Header + cbICVlen = 8;//MIC + cbMICHDR = sizeof(SMICHDRHead); + pTxBufHead->wFragCtl |= FRAGCTL_AES; + pDevice->bAES = true; + } + //MAC Header should be padding 0 to DW alignment. + uPadding = 4 - (cbMacHdLen%4); + uPadding %= 4; + } + + cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen + cbExtSuppRate; + + //Set FIFOCTL_GrpAckPolicy + if (pDevice->bGrpAckPolicy == true) {//0000 0100 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; + } + //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter() + + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet + + pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); + pvRTS = NULL; + pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); + pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS)); + cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g); + + } + else {//802.11a/b packet + + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = NULL; + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab); + } + memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, + (cbHeaderSize - wTxBufSize)); + memcpy(&(sEthHeader.h_dest[0]), + &(p80211Header->sA3.abyAddr1[0]), + ETH_ALEN); + memcpy(&(sEthHeader.h_source[0]), + &(p80211Header->sA3.abyAddr2[0]), + ETH_ALEN); + //========================= + // No Fragmentation + //========================= + pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG; + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate, pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS, + cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader); + + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK, + 0, 0, 1, AUTO_FB_NONE); + + pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize); + + cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate; + + pbyMacHdr = (u8 *)(pbyTxBufferAddr + cbHeaderSize); + pbyPayloadHead = (u8 *)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen); + pbyIVHead = (u8 *)(pbyMacHdr + cbMacHdLen + uPadding); + + // Copy the Packet into a tx Buffer + memcpy(pbyMacHdr, skb->data, cbMacHdLen); + + // version set to 0, patch for hostapd deamon + pMACHeader->frame_control &= cpu_to_le16(0xfffc); + memcpy(pbyPayloadHead, (skb->data + cbMacHdLen), cbFrameBodySize); + + // replace support rate, patch for hostapd daemon( only support 11M) + if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) { + if (cbExtSuppRate != 0) { + if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) + memcpy((pbyPayloadHead + cbFrameBodySize), + pMgmt->abyCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0) + memcpy((pbyPayloadHead + cbFrameBodySize) + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN, + pMgmt->abyCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + } + + // Set wep + if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) { + + if (pDevice->bEnableHostWEP) { + pTransmitKey = &STempKey; + pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; + pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; + pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength; + pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16; + pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0; + memcpy(pTransmitKey->abyKey, + &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0], + pTransmitKey->uKeyLength + ); + } + + if ((pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { + + dwMICKey0 = *(u32 *)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(u32 *)(&pTransmitKey->abyKey[20]); + + // DO Software Michael + MIC_vInit(dwMICKey0, dwMICKey1); + MIC_vAppend((u8 *)&(sEthHeader.h_dest[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((u8 *)&dwMIC_Priority, 4); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY:"\ + " %X, %X\n", dwMICKey0, dwMICKey1); + + uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; + + MIC_vAppend((pbyTxBufferAddr + uLength), cbFrameBodySize); + + pdwMIC_L = (u32 *)(pbyTxBufferAddr + uLength + cbFrameBodySize); + pdwMIC_R = (u32 *)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4); + + MIC_vGetMIC(pdwMIC_L, pdwMIC_R); + MIC_vUnInit(); + + if (pDevice->bTxMICFail == true) { + *pdwMIC_L = 0; + *pdwMIC_R = 0; + pDevice->bTxMICFail = false; + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%x, %x\n", + *pdwMIC_L, *pdwMIC_R); + + } + + s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (u16)cbFrameBodySize, (u8 *)pMICHDR); + + if (pDevice->bEnableHostWEP) { + pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; + pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; + } + + if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) { + s_vSWencryption(pDevice, pTransmitKey, pbyPayloadHead, (u16)(cbFrameBodySize + cbMIClen)); + } + } + + pMACHeader->seq_ctrl = cpu_to_le16(pDevice->wSeqCounter << 4); + pDevice->wSeqCounter++ ; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; + + if (bIsPSPOLL) { + // The MAC will automatically replace the Duration-field of MAC header by Duration-field + // of FIFO control header. + // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is + // in the same place of other packet's Duration-field). + // And it will cause Cisco-AP to issue Disassociation-packet + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + ((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(p80211Header->sA2.wDurationID); + ((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(p80211Header->sA2.wDurationID); + } else { + ((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(p80211Header->sA2.wDurationID); + } + } + + pTX_Buffer->wTxByteCount = cpu_to_le16((u16)(cbReqCount)); + pTX_Buffer->byPKTNO = (u8) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); + pTX_Buffer->byType = 0x00; + + pContext->pPacket = skb; + pContext->Type = CONTEXT_MGMT_PACKET; + pContext->uBufLen = (u16)cbReqCount + 4; //USB header + + if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) { + s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl); + } + else { + s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl); + } + PIPEnsSendBulkOut(pDevice,pContext); + return ; + +} + +//TYPE_AC0DMA data tx +/* + * Description: + * Tx packet via AC0DMA(DMA1) + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * skb - Pointer to tx skb packet + * Out: + * void + * + * Return Value: NULL + */ + +int nsDMA_tx_packet(struct vnt_private *pDevice, + u32 uDMAIdx, struct sk_buff *skb) +{ + struct net_device_stats *pStats = &pDevice->stats; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u32 BytesToWrite = 0, uHeaderLen = 0; + u32 uNodeIndex = 0; + u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + u16 wAID; + u8 byPktType; + int bNeedEncryption = false; + PSKeyItem pTransmitKey = NULL; + SKeyItem STempKey; + int ii; + int bTKIP_UseGTK = false; + int bNeedDeAuth = false; + u8 *pbyBSSID; + int bNodeExist = false; + PUSB_SEND_CONTEXT pContext; + bool fConvertedPacket; + PTX_BUFFER pTX_Buffer; + u32 status; + u16 wKeepRate = pDevice->wCurrentRate; + int bTxeapol_key = false; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + + if (pDevice->uAssocCount == 0) { + dev_kfree_skb_irq(skb); + return 0; + } + + if (is_multicast_ether_addr((u8 *)(skb->data))) { + uNodeIndex = 0; + bNodeExist = true; + if (pMgmt->sNodeDBTable[0].bPSEnable) { + + skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb); + pMgmt->sNodeDBTable[0].wEnQueueCnt++; + // set tx map + pMgmt->abyPSTxMap[0] |= byMask[0]; + return 0; + } + // multicast/broadcast data rate + + if (pDevice->byBBType != BB_TYPE_11A) + pDevice->wCurrentRate = RATE_2M; + else + pDevice->wCurrentRate = RATE_24M; + // long preamble type + pDevice->byPreambleType = PREAMBLE_SHORT; + + }else { + + if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(skb->data), &uNodeIndex)) { + + if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) { + + skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb); + + pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++; + // set tx map + wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID; + pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n", + (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]); + + return 0; + } + // AP rate decided from node + pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; + // tx preamble decided from node + + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { + pDevice->byPreambleType = pDevice->byShortPreamble; + + }else { + pDevice->byPreambleType = PREAMBLE_LONG; + } + bNodeExist = true; + } + } + + if (bNodeExist == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Unknown STA not found in node DB \n"); + dev_kfree_skb_irq(skb); + return 0; + } + } + + pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); + + if (pContext == NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG" pContext == NULL\n"); + dev_kfree_skb_irq(skb); + return STATUS_RESOURCES; + } + + memcpy(pDevice->sTxEthHeader.h_dest, (u8 *)(skb->data), ETH_HLEN); + +//mike add:station mode check eapol-key challenge---> +{ + u8 Protocol_Version; //802.1x Authentication + u8 Packet_Type; //802.1x Authentication + u8 Descriptor_type; + u16 Key_info; + + Protocol_Version = skb->data[ETH_HLEN]; + Packet_Type = skb->data[ETH_HLEN+1]; + Descriptor_type = skb->data[ETH_HLEN+1+1+2]; + Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]); + if (pDevice->sTxEthHeader.h_proto == cpu_to_be16(ETH_P_PAE)) { + /* 802.1x OR eapol-key challenge frame transfer */ + if (((Protocol_Version == 1) || (Protocol_Version == 2)) && + (Packet_Type == 3)) { + bTxeapol_key = true; + if(!(Key_info & BIT3) && //WPA or RSN group-key challenge + (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key + if(Descriptor_type==254) { + pDevice->fWPA_Authened = true; + PRINT_K("WPA "); + } + else { + pDevice->fWPA_Authened = true; + PRINT_K("WPA2(re-keying) "); + } + PRINT_K("Authentication completed!!\n"); + } + else if((Key_info & BIT3) && (Descriptor_type==2) && //RSN pairwise-key challenge + (Key_info & BIT8) && (Key_info & BIT9)) { + pDevice->fWPA_Authened = true; + PRINT_K("WPA2 Authentication completed!!\n"); + } + } + } +} +//mike add:station mode check eapol-key challenge<--- + + if (pDevice->bEncryptionEnable == true) { + bNeedEncryption = true; + // get Transmit key + do { + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + pbyBSSID = pDevice->abyBSSID; + // get pairwise key + if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) { + // get group key + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) { + bTKIP_UseGTK = true; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); + break; + } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get PTK.\n"); + break; + } + }else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + /* TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1 */ + pbyBSSID = pDevice->sTxEthHeader.h_dest; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS Serach Key: \n"); + for (ii = 0; ii< 6; ii++) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"%x \n", *(pbyBSSID+ii)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"\n"); + + // get pairwise key + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == true) + break; + } + // get group key + pbyBSSID = pDevice->abyBroadcastAddr; + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) { + pTransmitKey = NULL; + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS and KEY is NULL. [%d]\n", pMgmt->eCurrMode); + } + else + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"NOT IBSS and KEY is NULL. [%d]\n", pMgmt->eCurrMode); + } else { + bTKIP_UseGTK = true; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); + } + } while(false); + } + + if (pDevice->bEnableHostWEP) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"acdma0: STA index %d\n", uNodeIndex); + if (pDevice->bEncryptionEnable == true) { + pTransmitKey = &STempKey; + pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; + pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; + pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength; + pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16; + pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0; + memcpy(pTransmitKey->abyKey, + &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0], + pTransmitKey->uKeyLength + ); + } + } + + byPktType = (u8)pDevice->byPacketType; + + if (pDevice->bFixRate) { + if (pDevice->byBBType == BB_TYPE_11B) { + if (pDevice->uConnectionRate >= RATE_11M) { + pDevice->wCurrentRate = RATE_11M; + } else { + pDevice->wCurrentRate = (u16)pDevice->uConnectionRate; + } + } else { + if ((pDevice->byBBType == BB_TYPE_11A) && + (pDevice->uConnectionRate <= RATE_6M)) { + pDevice->wCurrentRate = RATE_6M; + } else { + if (pDevice->uConnectionRate >= RATE_54M) + pDevice->wCurrentRate = RATE_54M; + else + pDevice->wCurrentRate = (u16)pDevice->uConnectionRate; + } + } + } + else { + if (pDevice->eOPMode == OP_MODE_ADHOC) { + // Adhoc Tx rate decided from node DB + if (is_multicast_ether_addr(pDevice->sTxEthHeader.h_dest)) { + // Multicast use highest data rate + pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate; + // preamble type + pDevice->byPreambleType = pDevice->byShortPreamble; + } + else { + if (BSSbIsSTAInNodeDB(pDevice, &(pDevice->sTxEthHeader.h_dest[0]), &uNodeIndex)) { + pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { + pDevice->byPreambleType = pDevice->byShortPreamble; + + } + else { + pDevice->byPreambleType = PREAMBLE_LONG; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Found Node Index is [%d] Tx Data Rate:[%d]\n",uNodeIndex, pDevice->wCurrentRate); + } + else { + if (pDevice->byBBType != BB_TYPE_11A) + pDevice->wCurrentRate = RATE_2M; + else + pDevice->wCurrentRate = RATE_24M; // refer to vMgrCreateOwnIBSS()'s + // abyCurrExtSuppRates[] + pDevice->byPreambleType = PREAMBLE_SHORT; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Not Found Node use highest basic Rate.....\n"); + } + } + } + if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) { + // Infra STA rate decided from AP Node, index = 0 + pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate; + } + } + + if (pDevice->sTxEthHeader.h_proto == cpu_to_be16(ETH_P_PAE)) { + if (pDevice->byBBType != BB_TYPE_11A) { + pDevice->wCurrentRate = RATE_1M; + pDevice->byACKRate = RATE_1M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + pDevice->wCurrentRate = RATE_6M; + pDevice->byACKRate = RATE_6M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + } + + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n", + pDevice->wCurrentRate); + + if (wKeepRate != pDevice->wCurrentRate) { + bScheduleCommand((void *) pDevice, WLAN_CMD_SETPOWER, NULL); + } + + if (pDevice->wCurrentRate <= RATE_11M) { + byPktType = PK_TYPE_11B; + } + + if (bNeedEncryption == true) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.h_proto)); + if ((pDevice->sTxEthHeader.h_proto) == cpu_to_be16(ETH_P_PAE)) { + bNeedEncryption = false; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.h_proto)); + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + if (pTransmitKey == NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Don't Find TX KEY\n"); + } + else { + if (bTKIP_UseGTK == true) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n"); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", + pTransmitKey->dwKeyIndex); + bNeedEncryption = true; + } + } + } + + if (pDevice->bEnableHostWEP) { + if ((uNodeIndex != 0) && + (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", + pTransmitKey->dwKeyIndex); + bNeedEncryption = true; + } + } + } + else { + + if (pTransmitKey == NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n"); + pContext->bBoolInUse = false; + dev_kfree_skb_irq(skb); + pStats->tx_dropped++; + return STATUS_FAILURE; + } + } + } + + fConvertedPacket = s_bPacketToWirelessUsb(pDevice, byPktType, + (u8 *)(&pContext->Data[0]), bNeedEncryption, + skb->len, uDMAIdx, &pDevice->sTxEthHeader, + (u8 *)skb->data, pTransmitKey, uNodeIndex, + pDevice->wCurrentRate, + &uHeaderLen, &BytesToWrite + ); + + if (fConvertedPacket == false) { + pContext->bBoolInUse = false; + dev_kfree_skb_irq(skb); + return STATUS_FAILURE; + } + + if ( pDevice->bEnablePSMode == true ) { + if ( !pDevice->bPSModeTxBurst ) { + bScheduleCommand((void *) pDevice, + WLAN_CMD_MAC_DISPOWERSAVING, + NULL); + pDevice->bPSModeTxBurst = true; + } + } + + pTX_Buffer = (PTX_BUFFER)&(pContext->Data[0]); + pTX_Buffer->byPKTNO = (u8) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); + pTX_Buffer->wTxByteCount = (u16)BytesToWrite; + + pContext->pPacket = skb; + pContext->Type = CONTEXT_DATA_PACKET; + pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header + + s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl); + + status = PIPEnsSendBulkOut(pDevice,pContext); + + if (bNeedDeAuth == true) { + u16 wReason = WLAN_MGMT_REASON_MIC_FAILURE; + + bScheduleCommand((void *) pDevice, WLAN_CMD_DEAUTH, (u8 *) &wReason); + } + + if(status!=STATUS_PENDING) { + pContext->bBoolInUse = false; + dev_kfree_skb_irq(skb); + return STATUS_FAILURE; + } + else + return 0; + +} + +/* + * Description: + * Relay packet send (AC1DMA) from rx dpc. + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * pPacket - Pointer to rx packet + * cbPacketSize - rx ethernet frame size + * Out: + * TURE, false + * + * Return Value: Return true if packet is copy to dma1; otherwise false + */ + +int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen, + u32 uNodeIndex) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u32 BytesToWrite = 0, uHeaderLen = 0; + u8 byPktType = PK_TYPE_11B; + int bNeedEncryption = false; + SKeyItem STempKey; + PSKeyItem pTransmitKey = NULL; + u8 *pbyBSSID; + PUSB_SEND_CONTEXT pContext; + u8 byPktTyp; + int fConvertedPacket; + PTX_BUFFER pTX_Buffer; + u32 status; + u16 wKeepRate = pDevice->wCurrentRate; + + pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); + + if (NULL == pContext) { + return false; + } + + memcpy(pDevice->sTxEthHeader.h_dest, (u8 *)pbySkbData, ETH_HLEN); + + if (pDevice->bEncryptionEnable == true) { + bNeedEncryption = true; + // get group key + pbyBSSID = pDevice->abyBroadcastAddr; + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) { + pTransmitKey = NULL; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"KEY is NULL. [%d]\n", pMgmt->eCurrMode); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); + } + } + + if (pDevice->bEnableHostWEP) { + if (uNodeIndex < MAX_NODE_NUM + 1) { + pTransmitKey = &STempKey; + pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; + pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; + pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength; + pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16; + pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0; + memcpy(pTransmitKey->abyKey, + &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0], + pTransmitKey->uKeyLength + ); + } + } + + if ( bNeedEncryption && (pTransmitKey == NULL) ) { + pContext->bBoolInUse = false; + return false; + } + + byPktTyp = (u8)pDevice->byPacketType; + + if (pDevice->bFixRate) { + if (pDevice->byBBType == BB_TYPE_11B) { + if (pDevice->uConnectionRate >= RATE_11M) { + pDevice->wCurrentRate = RATE_11M; + } else { + pDevice->wCurrentRate = (u16)pDevice->uConnectionRate; + } + } else { + if ((pDevice->byBBType == BB_TYPE_11A) && + (pDevice->uConnectionRate <= RATE_6M)) { + pDevice->wCurrentRate = RATE_6M; + } else { + if (pDevice->uConnectionRate >= RATE_54M) + pDevice->wCurrentRate = RATE_54M; + else + pDevice->wCurrentRate = (u16)pDevice->uConnectionRate; + } + } + } + else { + pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; + } + + if (wKeepRate != pDevice->wCurrentRate) { + bScheduleCommand((void *) pDevice, WLAN_CMD_SETPOWER, NULL); + } + + if (pDevice->wCurrentRate <= RATE_11M) + byPktType = PK_TYPE_11B; + + BytesToWrite = uDataLen + ETH_FCS_LEN; + + // Convert the packet to an usb frame and copy into our buffer + // and send the irp. + + fConvertedPacket = s_bPacketToWirelessUsb(pDevice, byPktType, + (u8 *)(&pContext->Data[0]), bNeedEncryption, + uDataLen, TYPE_AC0DMA, &pDevice->sTxEthHeader, + pbySkbData, pTransmitKey, uNodeIndex, + pDevice->wCurrentRate, + &uHeaderLen, &BytesToWrite + ); + + if (fConvertedPacket == false) { + pContext->bBoolInUse = false; + return false; + } + + pTX_Buffer = (PTX_BUFFER)&(pContext->Data[0]); + pTX_Buffer->byPKTNO = (u8) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); + pTX_Buffer->wTxByteCount = (u16)BytesToWrite; + + pContext->pPacket = NULL; + pContext->Type = CONTEXT_DATA_PACKET; + pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header + + s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl); + + status = PIPEnsSendBulkOut(pDevice,pContext); + + return true; +} + diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h new file mode 100644 index 00000000..dd7e85dd --- /dev/null +++ b/drivers/staging/vt6656/rxtx.h @@ -0,0 +1,638 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: rxtx.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + */ + +#ifndef __RXTX_H__ +#define __RXTX_H__ + +#include "device.h" +#include "wcmd.h" + +// +// RTS buffer header +// +typedef struct tagSRTSDataF { + u16 wFrameControl; + u16 wDurationID; + u8 abyRA[ETH_ALEN]; + u8 abyTA[ETH_ALEN]; +} SRTSDataF, *PSRTSDataF; + +// +// CTS buffer header +// +typedef struct tagSCTSDataF { + u16 wFrameControl; + u16 wDurationID; + u8 abyRA[ETH_ALEN]; + u16 wReserved; +} SCTSDataF, *PSCTSDataF; + +// +// MICHDR data header +// +typedef struct tagSMICHDR { + u32 adwHDR0[4]; + u32 adwHDR1[4]; + u32 adwHDR2[4]; +} SMICHDR, *PSMICHDR; + +typedef struct tagSTX_NAF_G_RTS +{ + //RsvTime + u16 wRTSTxRrvTime_ba; + u16 wRTSTxRrvTime_aa; + u16 wRTSTxRrvTime_bb; + u16 wReserved2; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; + + //RTS + u8 byRTSSignalField_b; + u8 byRTSServiceField_b; + u16 wRTSTransmitLength_b; + u8 byRTSSignalField_a; + u8 byRTSServiceField_a; + u16 wRTSTransmitLength_a; + u16 wRTSDuration_ba; + u16 wRTSDuration_aa; + u16 wRTSDuration_bb; + u16 wReserved3; + SRTSDataF sRTS; + + //Data + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; + +} TX_NAF_G_RTS, *PTX_NAF_G_RTS; + +typedef struct tagSTX_NAF_G_RTS_MIC +{ + //RsvTime + u16 wRTSTxRrvTime_ba; + u16 wRTSTxRrvTime_aa; + u16 wRTSTxRrvTime_bb; + u16 wReserved2; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; + + SMICHDR sMICHDR; + + //RTS + u8 byRTSSignalField_b; + u8 byRTSServiceField_b; + u16 wRTSTransmitLength_b; + u8 byRTSSignalField_a; + u8 byRTSServiceField_a; + u16 wRTSTransmitLength_a; + u16 wRTSDuration_ba; + u16 wRTSDuration_aa; + u16 wRTSDuration_bb; + u16 wReserved3; + SRTSDataF sRTS; + + //Data + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; + +} TX_NAF_G_RTS_MIC, *PTX_NAF_G_RTS_MIC; + +typedef struct tagSTX_NAF_G_CTS +{ + //RsvTime + u16 wCTSTxRrvTime_ba; + u16 wReserved2; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; + + //CTS + u8 byCTSSignalField_b; + u8 byCTSServiceField_b; + u16 wCTSTransmitLength_b; + u16 wCTSDuration_ba; + u16 wReserved3; + SCTSDataF sCTS; + + //Data + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; + +} TX_NAF_G_CTS, *PTX_NAF_G_CTS; + +typedef struct tagSTX_NAF_G_CTS_MIC +{ + //RsvTime + u16 wCTSTxRrvTime_ba; + u16 wReserved2; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; + + SMICHDR sMICHDR; + + //CTS + u8 byCTSSignalField_b; + u8 byCTSServiceField_b; + u16 wCTSTransmitLength_b; + u16 wCTSDuration_ba; + u16 wReserved3; + SCTSDataF sCTS; + + //Data + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; + +} TX_NAF_G_CTS_MIC, *PTX_NAF_G_CTS_MIC; + +typedef struct tagSTX_NAF_G_BEACON +{ + u16 wFIFOCtl; + u16 wTimeStamp; + + //CTS + u8 byCTSSignalField_b; + u8 byCTSServiceField_b; + u16 wCTSTransmitLength_b; + u16 wCTSDuration_ba; + u16 wReserved1; + SCTSDataF sCTS; + + //Data + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_a; + u16 wTimeStampOff_a; + +} TX_NAF_G_BEACON, *PTX_NAF_G_BEACON; + +typedef struct tagSTX_NAF_AB_RTS +{ + //RsvTime + u16 wRTSTxRrvTime_ab; + u16 wTxRrvTime_ab; + + //RTS + u8 byRTSSignalField_ab; + u8 byRTSServiceField_ab; + u16 wRTSTransmitLength_ab; + u16 wRTSDuration_ab; + u16 wReserved2; + SRTSDataF sRTS; + + //Data + u8 bySignalField_ab; + u8 byServiceField_ab; + u16 wTransmitLength_ab; + u16 wDuration_ab; + u16 wTimeStampOff_ab; + +} TX_NAF_AB_RTS, *PTX_NAF_AB_RTS; + +typedef struct tagSTX_NAF_AB_RTS_MIC +{ + //RsvTime + u16 wRTSTxRrvTime_ab; + u16 wTxRrvTime_ab; + + SMICHDR sMICHDR; + + //RTS + u8 byRTSSignalField_ab; + u8 byRTSServiceField_ab; + u16 wRTSTransmitLength_ab; + u16 wRTSDuration_ab; + u16 wReserved2; + SRTSDataF sRTS; + + //Data + u8 bySignalField_ab; + u8 byServiceField_ab; + u16 wTransmitLength_ab; + u16 wDuration_ab; + u16 wTimeStampOff_ab; + +} TX_NAF_AB_RTS_MIC, *PTX_NAF_AB_RTS_MIC; + +typedef struct tagSTX_NAF_AB_CTS +{ + //RsvTime + u16 wReserved2; + u16 wTxRrvTime_ab; + + //Data + u8 bySignalField_ab; + u8 byServiceField_ab; + u16 wTransmitLength_ab; + u16 wDuration_ab; + u16 wTimeStampOff_ab; + +} TX_NAF_AB_CTS, *PTX_NAF_AB_CTS; + +typedef struct tagSTX_NAF_AB_CTS_MIC +{ + //RsvTime + u16 wReserved2; + u16 wTxRrvTime_ab; + + SMICHDR sMICHDR; + + //Data + u8 bySignalField_ab; + u8 byServiceField_ab; + u16 wTransmitLength_ab; + u16 wDuration_ab; + u16 wTimeStampOff_ab; + +} TX_NAF_AB_CTS_MIC, *PTX_NAF_AB_CTS_MIC; + +typedef struct tagSTX_NAF_AB_BEACON +{ + u16 wFIFOCtl; + u16 wTimeStamp; + + //Data + u8 bySignalField_ab; + u8 byServiceField_ab; + u16 wTransmitLength_ab; + u16 wDuration_ab; + u16 wTimeStampOff_ab; + +} TX_NAF_AB_BEACON, *PTX_NAF_AB_BEACON; + +typedef struct tagSTX_AF_G_RTS +{ + //RsvTime + u16 wRTSTxRrvTime_ba; + u16 wRTSTxRrvTime_aa; + u16 wRTSTxRrvTime_bb; + u16 wReserved2; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; + + //RTS + u8 byRTSSignalField_b; + u8 byRTSServiceField_b; + u16 wRTSTransmitLength_b; + u8 byRTSSignalField_a; + u8 byRTSServiceField_a; + u16 wRTSTransmitLength_a; + u16 wRTSDuration_ba; + u16 wRTSDuration_aa; + u16 wRTSDuration_bb; + u16 wReserved3; + u16 wRTSDuration_ba_f0; + u16 wRTSDuration_aa_f0; + u16 wRTSDuration_ba_f1; + u16 wRTSDuration_aa_f1; + SRTSDataF sRTS; + + //Data + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; + +} TX_AF_G_RTS, *PTX_AF_G_RTS; + +typedef struct tagSTX_AF_G_RTS_MIC +{ + //RsvTime + u16 wRTSTxRrvTime_ba; + u16 wRTSTxRrvTime_aa; + u16 wRTSTxRrvTime_bb; + u16 wReserved2; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; + + SMICHDR sMICHDR; + + //RTS + u8 byRTSSignalField_b; + u8 byRTSServiceField_b; + u16 wRTSTransmitLength_b; + u8 byRTSSignalField_a; + u8 byRTSServiceField_a; + u16 wRTSTransmitLength_a; + u16 wRTSDuration_ba; + u16 wRTSDuration_aa; + u16 wRTSDuration_bb; + u16 wReserved3; + u16 wRTSDuration_ba_f0; + u16 wRTSDuration_aa_f0; + u16 wRTSDuration_ba_f1; + u16 wRTSDuration_aa_f1; + SRTSDataF sRTS; + + //Data + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; + +} TX_AF_G_RTS_MIC, *PTX_AF_G_RTS_MIC; + +typedef struct tagSTX_AF_G_CTS +{ + //RsvTime + u16 wCTSTxRrvTime_ba; + u16 wReserved2; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; + + //CTS + u8 byCTSSignalField_b; + u8 byCTSServiceField_b; + u16 wCTSTransmitLength_b; + u16 wCTSDuration_ba; + u16 wReserved3; + u16 wCTSDuration_ba_f0; + u16 wCTSDuration_ba_f1; + SCTSDataF sCTS; + + //Data + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; + +} TX_AF_G_CTS, *PTX_AF_G_CTS; + +typedef struct tagSTX_AF_G_CTS_MIC +{ + //RsvTime + u16 wCTSTxRrvTime_ba; + u16 wReserved2; + u16 wTxRrvTime_b; + u16 wTxRrvTime_a; + + SMICHDR sMICHDR; + + //CTS + u8 byCTSSignalField_b; + u8 byCTSServiceField_b; + u16 wCTSTransmitLength_b; + u16 wCTSDuration_ba; + u16 wReserved3; + u16 wCTSDuration_ba_f0; + u16 wCTSDuration_ba_f1; + SCTSDataF sCTS; + + //Data + u8 bySignalField_b; + u8 byServiceField_b; + u16 wTransmitLength_b; + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_b; + u16 wDuration_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + u16 wTimeStampOff_b; + u16 wTimeStampOff_a; + +} TX_AF_G_CTS_MIC, *PTX_AF_G_CTS_MIC; + +typedef struct tagSTX_AF_A_RTS +{ + //RsvTime + u16 wRTSTxRrvTime_a; + u16 wTxRrvTime_a; + + //RTS + u8 byRTSSignalField_a; + u8 byRTSServiceField_a; + u16 wRTSTransmitLength_a; + u16 wRTSDuration_a; + u16 wReserved2; + u16 wRTSDuration_a_f0; + u16 wRTSDuration_a_f1; + SRTSDataF sRTS; + + //Data + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_a; + u16 wTimeStampOff_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + +} TX_AF_A_RTS, *PTX_AF_A_RTS; + +typedef struct tagSTX_AF_A_RTS_MIC +{ + //RsvTime + u16 wRTSTxRrvTime_a; + u16 wTxRrvTime_a; + + SMICHDR sMICHDR; + + //RTS + u8 byRTSSignalField_a; + u8 byRTSServiceField_a; + u16 wRTSTransmitLength_a; + u16 wRTSDuration_a; + u16 wReserved2; + u16 wRTSDuration_a_f0; + u16 wRTSDuration_a_f1; + SRTSDataF sRTS; + + //Data + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_a; + u16 wTimeStampOff_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + +} TX_AF_A_RTS_MIC, *PTX_AF_A_RTS_MIC; + +typedef struct tagSTX_AF_A_CTS +{ + //RsvTime + u16 wReserved2; + u16 wTxRrvTime_a; + + //Data + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_a; + u16 wTimeStampOff_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + +} TX_AF_A_CTS, *PTX_AF_A_CTS; + +typedef struct tagSTX_AF_A_CTS_MIC +{ + //RsvTime + u16 wReserved2; + u16 wTxRrvTime_a; + + SMICHDR sMICHDR; + + //Data + u8 bySignalField_a; + u8 byServiceField_a; + u16 wTransmitLength_a; + u16 wDuration_a; + u16 wTimeStampOff_a; + u16 wDuration_a_f0; + u16 wDuration_a_f1; + +} TX_AF_A_CTS_MIC, *PTX_AF_A_CTS_MIC; + +// +// union with all of the TX Buffer Type +// +typedef union tagUTX_BUFFER_CONTAINER +{ + TX_NAF_G_RTS RTS_G; + TX_NAF_G_RTS_MIC RTS_G_MIC; + TX_NAF_G_CTS CTS_G; + TX_NAF_G_CTS_MIC CTS_G_MIC; + //TX_NAF_G_BEACON Beacon_G; + TX_NAF_AB_RTS RTS_AB; + TX_NAF_AB_RTS_MIC RTS_AB_MIC; + TX_NAF_AB_CTS CTS_AB; + TX_NAF_AB_CTS_MIC CTS_AB_MIC; + //TX_NAF_AB_BEACON Beacon_AB; + TX_AF_G_RTS RTS_G_AutoFB; + TX_AF_G_RTS_MIC RTS_G_AutoFB_MIC; + TX_AF_G_CTS CTS_G_AutoFB; + TX_AF_G_CTS_MIC CTS_G_AutoFB_MIC; + TX_AF_A_RTS RTS_A_AutoFB; + TX_AF_A_RTS_MIC RTS_A_AutoFB_MIC; + TX_AF_A_CTS CTS_A_AutoFB; + TX_AF_A_CTS_MIC CTS_A_AutoFB_MIC; + +} TX_BUFFER_CONTAINER, *PTX_BUFFER_CONTAINER; + +// +// Remote NDIS message format +// +typedef struct tagSTX_BUFFER +{ + u8 byType; + u8 byPKTNO; + u16 wTxByteCount; + + u32 adwTxKey[4]; + u16 wFIFOCtl; + u16 wTimeStamp; + u16 wFragCtl; + u16 wReserved; + + // Actual message + TX_BUFFER_CONTAINER BufferHeader; + +} TX_BUFFER, *PTX_BUFFER; + +// +// Remote NDIS message format +// +typedef struct tagSBEACON_BUFFER +{ + u8 byType; + u8 byPKTNO; + u16 wTxByteCount; + + u16 wFIFOCtl; + u16 wTimeStamp; + + // Actual message + TX_BUFFER_CONTAINER BufferHeader; + +} BEACON_BUFFER, *PBEACON_BUFFER; + +void vDMA0_tx_80211(struct vnt_private *, struct sk_buff *skb); +int nsDMA_tx_packet(struct vnt_private *, u32 uDMAIdx, struct sk_buff *skb); +CMD_STATUS csMgmt_xmit(struct vnt_private *, struct vnt_tx_mgmt *); +CMD_STATUS csBeacon_xmit(struct vnt_private *, struct vnt_tx_mgmt *); +int bRelayPacketSend(struct vnt_private *, u8 *pbySkbData, u32 uDataLen, + u32 uNodeIndex); + +#endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6656/srom.h b/drivers/staging/vt6656/srom.h new file mode 100644 index 00000000..488192d7 --- /dev/null +++ b/drivers/staging/vt6656/srom.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: srom.h + * + * Purpose: Implement functions to access eeprom + * + * Author: Jerry Chen + * + * Date: Jan 29, 2003 + * + */ + +#ifndef __SROM_H__ +#define __SROM_H__ + +#define EEP_MAX_CONTEXT_SIZE 256 + +#define CB_EEPROM_READBYTE_WAIT 900 //us + +#define W_MAX_I2CRETRY 0x0fff + +// +// Contents in the EEPROM +// +#define EEP_OFS_PAR 0x00 // physical address +#define EEP_OFS_ANTENNA 0x17 +#define EEP_OFS_RADIOCTL 0x18 +#define EEP_OFS_RFTYPE 0x1B // for select RF +#define EEP_OFS_MINCHANNEL 0x1C // Min Channel # +#define EEP_OFS_MAXCHANNEL 0x1D // Max Channel # +#define EEP_OFS_SIGNATURE 0x1E // +#define EEP_OFS_ZONETYPE 0x1F // +#define EEP_OFS_RFTABLE 0x20 // RF POWER TABLE +#define EEP_OFS_PWR_CCK 0x20 +#define EEP_OFS_SETPT_CCK 0x21 +#define EEP_OFS_PWR_OFDMG 0x23 + +#define EEP_OFS_CALIB_TX_IQ 0x24 +#define EEP_OFS_CALIB_TX_DC 0x25 +#define EEP_OFS_CALIB_RX_IQ 0x26 + +#define EEP_OFS_MAJOR_VER 0x2E +#define EEP_OFS_MINOR_VER 0x2F + +#define EEP_OFS_CCK_PWR_TBL 0x30 +#define EEP_OFS_OFDM_PWR_TBL 0x40 +#define EEP_OFS_OFDMA_PWR_TBL 0x50 + +// +// Bits in EEP_OFS_ANTENNA +// +#define EEP_ANTENNA_MAIN 0x01 +#define EEP_ANTENNA_AUX 0x02 +#define EEP_ANTINV 0x04 + +// +// Bits in EEP_OFS_RADIOCTL +// +#define EEP_RADIOCTL_ENABLE 0x80 + +// AT24C02 eeprom contents +// 2048 bits = 256 bytes = 128 words +// +typedef struct tagSSromReg { + u8 abyPAR[6]; // 0x00 (u16) + + u16 wSUB_VID; // 0x03 (u16) + u16 wSUB_SID; + + u8 byBCFG0; // 0x05 (u16) + u8 byBCFG1; + + u8 byFCR0; // 0x06 (u16) + u8 byFCR1; + u8 byPMC0; // 0x07 (u16) + u8 byPMC1; + u8 byMAXLAT; // 0x08 (u16) + u8 byMINGNT; + u8 byCFG0; // 0x09 (u16) + u8 byCFG1; + u16 wCISPTR; // 0x0A (u16) + u16 wRsv0; // 0x0B (u16) + u16 wRsv1; // 0x0C (u16) + u8 byBBPAIR; // 0x0D (u16) + u8 byRFTYPE; + u8 byMinChannel; // 0x0E (u16) + u8 byMaxChannel; + u8 bySignature; // 0x0F (u16) + u8 byCheckSum; + + u8 abyReserved0[96]; // 0x10 (u16) + u8 abyCIS[128]; // 0x80 (u16) +} SSromReg, *PSSromReg; + +#endif /* __EEPROM_H__ */ diff --git a/drivers/staging/vt6656/tcrc.c b/drivers/staging/vt6656/tcrc.c new file mode 100644 index 00000000..7229f26c --- /dev/null +++ b/drivers/staging/vt6656/tcrc.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2003 VIA Networking, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: tcrc.c + * + * Purpose: Implement functions to calculate CRC + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * CRCdwCrc32 - + * CRCdwGetCrc32 - + * CRCdwGetCrc32Ex - + * + * Revision History: + * + */ + +#include "tcrc.h" + +/* 32-bit CRC table */ +static const u32 s_adwCrc32Table[256] = { + 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, + 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, + 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, + 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, + 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, + 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, + 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, + 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, + 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, + 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, + 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, + 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, + 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, + 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, + 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, + 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, + 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, + 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, + 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, + 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, + 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, + 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, + 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, + 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, + 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, + 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, + 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, + 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, + 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, + 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, + 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, + 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, + 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, + 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, + 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, + 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, + 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, + 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, + 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, + 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, + 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, + 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, + 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, + 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, + 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, + 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, + 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, + 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, + 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, + 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, + 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, + 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, + 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, + 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, + 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, + 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, + 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, + 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, + 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, + 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, + 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, + 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, + 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, + 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL +}; + +/*+ + * + * Description: + * Generate a CRC-32 from the data stream + * + * Parameters: + * In: + * pbyData - the data stream + * cbByte - the length of the stream + * dwCrcSeed - Seed for CRC32 + * Out: + * none + * + * Return Value: CRC-32 + * +-*/ +u32 CRCdwCrc32(u8 * pbyData, unsigned int cbByte, u32 dwCrcSeed) +{ + u32 dwCrc; + + dwCrc = dwCrcSeed; + while (cbByte--) { + dwCrc = s_adwCrc32Table[(u8)((dwCrc ^ (*pbyData)) & 0xFF)] ^ + (dwCrc >> 8); + pbyData++; + } + + return dwCrc; +} + +/*+ + * + * Description: + * To test CRC generator, input 8 bytes packet + * -- 0xff 0xff 0xff 0xff 0x00 0x00 0x00 0x00 + * the generated CRC should be + * -- 0xff 0xff 0xff 0xff + * + * Parameters: + * In: + * pbyData - the data stream + * cbByte - the length of the stream + * Out: + * none + * + * Return Value: CRC-32 + * +-*/ +u32 CRCdwGetCrc32(u8 * pbyData, unsigned int cbByte) +{ + return ~CRCdwCrc32(pbyData, cbByte, 0xFFFFFFFFL); +} + +/*+ + * + * Description: + * + * NOTE.... Because CRCdwGetCrc32Ex() is an iteration function, + * this means we will use the output of CRCdwGetCrc32Ex() + * to be a new argument to do next CRCdwGetCrc32Ex() calculation. + * Thus, the final result must be inverted to be the + * correct answer. + * + * Parameters: + * In: + * pbyData - the data stream + * cbByte - the length of the stream + * Out: + * none + * + * Return Value: CRC-32 + * +-*/ +u32 CRCdwGetCrc32Ex(u8 * pbyData, unsigned int cbByte, u32 dwPreCRC) +{ + return CRCdwCrc32(pbyData, cbByte, dwPreCRC); +} + diff --git a/drivers/staging/vt6656/tcrc.h b/drivers/staging/vt6656/tcrc.h new file mode 100644 index 00000000..5b1f3689 --- /dev/null +++ b/drivers/staging/vt6656/tcrc.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2003 VIA Networking, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: tcrc.h + * + * Purpose: Implement functions to calculate CRC + * + * Author: Tevin Chen + * + * Date: Jan. 28, 1997 + * + */ + +#ifndef __TCRC_H__ +#define __TCRC_H__ + +#include <linux/types.h> + +u32 CRCdwCrc32(u8 * pbyData, unsigned int cbByte, u32 dwCrcSeed); +u32 CRCdwGetCrc32(u8 * pbyData, unsigned int cbByte); +u32 CRCdwGetCrc32Ex(u8 * pbyData, unsigned int cbByte, u32 dwPreCRC); + +#endif /* __TCRC_H__ */ diff --git a/drivers/staging/vt6656/tether.c b/drivers/staging/vt6656/tether.c new file mode 100644 index 00000000..1db1e841 --- /dev/null +++ b/drivers/staging/vt6656/tether.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003 VIA Networking, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: tether.c + * + * Purpose: + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * ETHbIsBufferCrc32Ok - Check CRC value of the buffer if Ok or not + * + * Revision History: + * + */ + +#include "device.h" +#include "tmacro.h" +#include "tcrc.h" +#include "tether.h" + +/* + * Description: Check CRC value of the buffer if Ok or not + * + * Parameters: + * In: + * pbyBuffer - pointer of buffer (normally is rx buffer) + * cbFrameLength - length of buffer, including CRC portion + * Out: + * none + * + * Return Value: true if ok; false if error. + * + */ +bool ETHbIsBufferCrc32Ok(u8 * pbyBuffer, unsigned int cbFrameLength) +{ + u32 dwCRC; + + dwCRC = CRCdwGetCrc32(pbyBuffer, cbFrameLength - 4); + if (cpu_to_le32(*((u32 *)(pbyBuffer + cbFrameLength - 4))) != dwCRC) + return false; + return true; +} + diff --git a/drivers/staging/vt6656/tether.h b/drivers/staging/vt6656/tether.h new file mode 100644 index 00000000..24465cfe --- /dev/null +++ b/drivers/staging/vt6656/tether.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: tether.h + * + * Purpose: + * + * Author: Tevin Chen + * + * Date: Jan. 28, 1997 + * + */ + +#ifndef __TETHER_H__ +#define __TETHER_H__ + +#include <linux/if_ether.h> + +// +// constants +// +#define U_ETHER_ADDR_STR_LEN (ETH_ALEN * 2 + 1) + // Ethernet address string length +#define U_MULTI_ADDR_LEN 8 // multicast address length + +#ifdef __BIG_ENDIAN + +#define TYPE_MGMT_PROBE_RSP 0x5000 + +#define FC_TODS 0x0001 +#define FC_FROMDS 0x0002 +#define FC_MOREFRAG 0x0004 +#define FC_RETRY 0x0008 +#define FC_POWERMGT 0x0010 +#define FC_MOREDATA 0x0020 +#define FC_WEP 0x0040 +#define TYPE_802_11_ATIM 0x9000 + +#define TYPE_802_11_DATA 0x0800 +#define TYPE_802_11_CTL 0x0400 +#define TYPE_802_11_MGMT 0x0000 +#define TYPE_802_11_MASK 0x0C00 +#define TYPE_SUBTYPE_MASK 0xFC00 +#define TYPE_802_11_NODATA 0x4000 +#define TYPE_DATE_NULL 0x4800 + +#define TYPE_CTL_PSPOLL 0xa400 +#define TYPE_CTL_RTS 0xb400 +#define TYPE_CTL_CTS 0xc400 +#define TYPE_CTL_ACK 0xd400 + +#else //if LITTLE_ENDIAN +// +// wType field in the SEthernetHeader +// +// NOTE.... +// in network byte order, high byte is going first + +#define TYPE_MGMT_PROBE_RSP 0x0050 + +#define FC_TODS 0x0100 +#define FC_FROMDS 0x0200 +#define FC_MOREFRAG 0x0400 +#define FC_RETRY 0x0800 +#define FC_POWERMGT 0x1000 +#define FC_MOREDATA 0x2000 +#define FC_WEP 0x4000 +#define TYPE_802_11_ATIM 0x0090 + +#define TYPE_802_11_DATA 0x0008 +#define TYPE_802_11_CTL 0x0004 +#define TYPE_802_11_MGMT 0x0000 +#define TYPE_802_11_MASK 0x000C +#define TYPE_SUBTYPE_MASK 0x00FC +#define TYPE_802_11_NODATA 0x0040 +#define TYPE_DATE_NULL 0x0048 + +#define TYPE_CTL_PSPOLL 0x00a4 +#define TYPE_CTL_RTS 0x00b4 +#define TYPE_CTL_CTS 0x00c4 +#define TYPE_CTL_ACK 0x00d4 + +#endif //#ifdef __BIG_ENDIAN + +#define WEP_IV_MASK 0x00FFFFFF + +// +// 802_3 packet +// +typedef struct tagS802_3Header { + u8 abyDstAddr[ETH_ALEN]; + u8 abySrcAddr[ETH_ALEN]; + u16 wLen; +} __attribute__ ((__packed__)) +S802_3Header, *PS802_3Header; + +//u8 ETHbyGetHashIndexByCrc(u8 * pbyMultiAddr); +bool ETHbIsBufferCrc32Ok(u8 * pbyBuffer, unsigned int cbFrameLength); + +#endif /* __TETHER_H__ */ diff --git a/drivers/staging/vt6656/tkip.c b/drivers/staging/vt6656/tkip.c new file mode 100644 index 00000000..9d643e44 --- /dev/null +++ b/drivers/staging/vt6656/tkip.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: tkip.c + * + * Purpose: Implement functions for 802.11i TKIP + * + * Author: Jerry Chen + * + * Date: Mar. 11, 2003 + * + * Functions: + * TKIPvMixKey - Get TKIP RC4 Key from TK,TA, and TSC + * + * Revision History: + * + */ + +#include "tmacro.h" +#include "tkip.h" + +/* The Sbox is reduced to 2 16-bit wide tables, each with 256 entries. */ +/* The 2nd table is the same as the 1st but with the upper and lower */ +/* bytes swapped. To allow an endian tolerant implementation, the byte */ +/* halves have been expressed independently here. */ +const u8 TKIP_Sbox_Lower[256] = { + 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, + 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, + 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, + 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B, + 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F, + 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F, + 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5, + 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F, + 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB, + 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97, + 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED, + 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A, + 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94, + 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3, + 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04, + 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D, + 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39, + 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95, + 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83, + 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76, + 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4, + 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B, + 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0, + 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18, + 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51, + 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85, + 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12, + 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9, + 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7, + 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A, + 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8, + 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A +}; + +const u8 TKIP_Sbox_Upper[256] = { + 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, + 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, + 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, + 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B, + 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83, + 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A, + 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F, + 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA, + 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B, + 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13, + 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6, + 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85, + 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11, + 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B, + 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1, + 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF, + 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E, + 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6, + 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B, + 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD, + 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8, + 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2, + 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49, + 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10, + 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97, + 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F, + 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C, + 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27, + 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33, + 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5, + 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0, + 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C +}; + +//STKIPKeyManagement sTKIPKeyTable[MAX_TKIP_KEY]; + +/************************************************************/ +/* tkip_sbox() */ +/* Returns a 16 bit value from a 64K entry table. The Table */ +/* is synthesized from two 256 entry byte wide tables. */ +/************************************************************/ +static unsigned int tkip_sbox(unsigned int index) +{ + unsigned int index_low; + unsigned int index_high; + unsigned int left, right; + + index_low = (index % 256); + index_high = ((index >> 8) % 256); + + left = TKIP_Sbox_Lower[index_low] + (TKIP_Sbox_Upper[index_low] * 256); + right = TKIP_Sbox_Upper[index_high] + (TKIP_Sbox_Lower[index_high] * 256); + + return (left ^ right); +}; + +static unsigned int rotr1(unsigned int a) +{ + unsigned int b; + + if ((a & 0x01) == 0x01) { + b = (a >> 1) | 0x8000; + } else { + b = (a >> 1) & 0x7fff; + } + b = b % 65536; + return b; +} + +/* + * Description: Calculate RC4Key fom TK, TA, and TSC + * + * Parameters: + * In: + * pbyTKey - TKey + * pbyTA - TA + * dwTSC - TSC + * Out: + * pbyRC4Key - RC4Key + * + * Return Value: none + * + */ +void TKIPvMixKey( + u8 * pbyTKey, + u8 * pbyTA, + u16 wTSC15_0, + u32 dwTSC47_16, + u8 * pbyRC4Key + ) +{ + u32 p1k[5]; + u32 tsc0, tsc1, tsc2; + u32 ppk0, ppk1, ppk2, ppk3, ppk4, ppk5; + u32 pnl, pnh; + int i, j; + + pnl = (u32)wTSC15_0; + pnh = (u32)(dwTSC47_16 & 0xffffffff); + + tsc0 = (u32)((pnh >> 16) % 65536); /* msb */ + tsc1 = (u32)(pnh % 65536); + tsc2 = (u32)(pnl % 65536); /* lsb */ + + /* Phase 1, step 1 */ + p1k[0] = tsc1; + p1k[1] = tsc0; + p1k[2] = (u32)(pbyTA[0] + (pbyTA[1]*256)); + p1k[3] = (u32)(pbyTA[2] + (pbyTA[3]*256)); + p1k[4] = (u32)(pbyTA[4] + (pbyTA[5]*256)); + + /* Phase 1, step 2 */ + for (i=0; i<8; i++) { + j = 2*(i & 1); + p1k[0] = (p1k[0] + tkip_sbox((p1k[4] ^ ((256*pbyTKey[1+j]) + pbyTKey[j])) % 65536)) % 65536; + p1k[1] = (p1k[1] + tkip_sbox((p1k[0] ^ ((256*pbyTKey[5+j]) + pbyTKey[4+j])) % 65536)) % 65536; + p1k[2] = (p1k[2] + tkip_sbox((p1k[1] ^ ((256*pbyTKey[9+j]) + pbyTKey[8+j])) % 65536)) % 65536; + p1k[3] = (p1k[3] + tkip_sbox((p1k[2] ^ ((256*pbyTKey[13+j]) + pbyTKey[12+j])) % 65536)) % 65536; + p1k[4] = (p1k[4] + tkip_sbox((p1k[3] ^ (((256*pbyTKey[1+j]) + pbyTKey[j]))) % 65536)) % 65536; + p1k[4] = (p1k[4] + i) % 65536; + } + + /* Phase 2, Step 1 */ + ppk0 = p1k[0]; + ppk1 = p1k[1]; + ppk2 = p1k[2]; + ppk3 = p1k[3]; + ppk4 = p1k[4]; + ppk5 = (p1k[4] + tsc2) % 65536; + + /* Phase2, Step 2 */ + ppk0 = ppk0 + tkip_sbox((ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) % 65536); + ppk1 = ppk1 + tkip_sbox((ppk0 ^ ((256*pbyTKey[3]) + pbyTKey[2])) % 65536); + ppk2 = ppk2 + tkip_sbox((ppk1 ^ ((256*pbyTKey[5]) + pbyTKey[4])) % 65536); + ppk3 = ppk3 + tkip_sbox((ppk2 ^ ((256*pbyTKey[7]) + pbyTKey[6])) % 65536); + ppk4 = ppk4 + tkip_sbox((ppk3 ^ ((256*pbyTKey[9]) + pbyTKey[8])) % 65536); + ppk5 = ppk5 + tkip_sbox((ppk4 ^ ((256*pbyTKey[11]) + pbyTKey[10])) % 65536); + + ppk0 = ppk0 + rotr1(ppk5 ^ ((256*pbyTKey[13]) + pbyTKey[12])); + ppk1 = ppk1 + rotr1(ppk0 ^ ((256*pbyTKey[15]) + pbyTKey[14])); + ppk2 = ppk2 + rotr1(ppk1); + ppk3 = ppk3 + rotr1(ppk2); + ppk4 = ppk4 + rotr1(ppk3); + ppk5 = ppk5 + rotr1(ppk4); + + /* Phase 2, Step 3 */ + pbyRC4Key[0] = (tsc2 >> 8) % 256; + pbyRC4Key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; + pbyRC4Key[2] = tsc2 % 256; + pbyRC4Key[3] = ((ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) >> 1) % 256; + + pbyRC4Key[4] = ppk0 % 256; + pbyRC4Key[5] = (ppk0 >> 8) % 256; + + pbyRC4Key[6] = ppk1 % 256; + pbyRC4Key[7] = (ppk1 >> 8) % 256; + + pbyRC4Key[8] = ppk2 % 256; + pbyRC4Key[9] = (ppk2 >> 8) % 256; + + pbyRC4Key[10] = ppk3 % 256; + pbyRC4Key[11] = (ppk3 >> 8) % 256; + + pbyRC4Key[12] = ppk4 % 256; + pbyRC4Key[13] = (ppk4 >> 8) % 256; + + pbyRC4Key[14] = ppk5 % 256; + pbyRC4Key[15] = (ppk5 >> 8) % 256; +} diff --git a/drivers/staging/vt6656/tkip.h b/drivers/staging/vt6656/tkip.h new file mode 100644 index 00000000..4fba7ef3 --- /dev/null +++ b/drivers/staging/vt6656/tkip.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: tkip.h + * + * Purpose: Implement functions for 802.11i TKIP + * + * Author: Jerry Chen + * + * Date: Mar. 11, 2003 + * + */ + +#ifndef __TKIP_H__ +#define __TKIP_H__ + +#include "tether.h" + +#define TKIP_KEY_LEN 16 + +void TKIPvMixKey( + u8 * pbyTKey, + u8 * pbyTA, + u16 wTSC15_0, + u32 dwTSC47_16, + u8 * pbyRC4Key + ); + +#endif /* __TKIP_H__ */ diff --git a/drivers/staging/vt6656/tmacro.h b/drivers/staging/vt6656/tmacro.h new file mode 100644 index 00000000..15cd5abb --- /dev/null +++ b/drivers/staging/vt6656/tmacro.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: tmacro.h + * + * Purpose: define basic common types and macros + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + +#ifndef __TMACRO_H__ +#define __TMACRO_H__ + +/****** Common helper macros ***********************************************/ + +#if !defined(LOBYTE) +#define LOBYTE(w) ((u8)(w)) +#endif +#if !defined(HIBYTE) +#define HIBYTE(w) ((u8)(((u16)(w) >> 8) & 0xFF)) +#endif + +#if !defined(LOWORD) +#define LOWORD(d) ((u16)(d)) +#endif +#if !defined(HIWORD) +#define HIWORD(d) ((u16)((((u32)(d)) >> 16) & 0xFFFF)) +#endif + +#define LODWORD(q) ((q).u.dwLowDword) +#define HIDWORD(q) ((q).u.dwHighDword) + +#if !defined(MAKEWORD) +#define MAKEWORD(lb, hb) ((u16)(((u8)(lb)) | (((u16)((u8)(hb))) << 8))) +#endif +#if !defined(MAKEDWORD) +#define MAKEDWORD(lw, hw) ((u32)(((u16)(lw)) | (((u32)((u16)(hw))) << 16))) +#endif + +#endif /* __TMACRO_H__ */ diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c new file mode 100644 index 00000000..098be609 --- /dev/null +++ b/drivers/staging/vt6656/usbpipe.c @@ -0,0 +1,696 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: usbpipe.c + * + * Purpose: Handle USB control endpoint + * + * Author: Warren Hsu + * + * Date: Mar. 29, 2005 + * + * Functions: + * CONTROLnsRequestOut - Write variable length bytes to MEM/BB/MAC/EEPROM + * CONTROLnsRequestIn - Read variable length bytes from MEM/BB/MAC/EEPROM + * ControlvWriteByte - Write one byte to MEM/BB/MAC/EEPROM + * ControlvReadByte - Read one byte from MEM/BB/MAC/EEPROM + * ControlvMaskByte - Read one byte from MEM/BB/MAC/EEPROM and clear/set some bits in the same address + * + * Revision History: + * 04-05-2004 Jerry Chen: Initial release + * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte + * + */ + +#include "int.h" +#include "rxtx.h" +#include "dpc.h" +#include "control.h" +#include "desc.h" +#include "device.h" + +//endpoint def +//endpoint 0: control +//endpoint 1: interrupt +//endpoint 2: read bulk +//endpoint 3: write bulk + +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +#define USB_CTL_WAIT 500 //ms + +#ifndef URB_ASYNC_UNLINK +#define URB_ASYNC_UNLINK 0 +#endif + +static void s_nsInterruptUsbIoCompleteRead(struct urb *urb); +static void s_nsBulkInUsbIoCompleteRead(struct urb *urb); +static void s_nsBulkOutIoCompleteWrite(struct urb *urb); +static void s_nsControlInUsbIoCompleteRead(struct urb *urb); +static void s_nsControlInUsbIoCompleteWrite(struct urb *urb); + +int PIPEnsControlOutAsyn(struct vnt_private *pDevice, u8 byRequest, + u16 wValue, u16 wIndex, u16 wLength, u8 *pbyBuffer) +{ + int ntStatus; + + if (pDevice->Flags & fMP_DISCONNECTED) + return STATUS_FAILURE; + + if (pDevice->Flags & fMP_CONTROL_WRITES) + return STATUS_FAILURE; + + if (in_interrupt()) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest); + return STATUS_FAILURE; + } + + ntStatus = usb_control_msg( + pDevice->usb, + usb_sndctrlpipe(pDevice->usb , 0), + byRequest, + 0x40, // RequestType + wValue, + wIndex, + (void *) pbyBuffer, + wLength, + HZ + ); + if (ntStatus >= 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe ntStatus= %d\n", ntStatus); + ntStatus = 0; + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe fail, ntStatus= %d\n", ntStatus); + } + + return ntStatus; +} + +int PIPEnsControlOut(struct vnt_private *pDevice, u8 byRequest, u16 wValue, + u16 wIndex, u16 wLength, u8 *pbyBuffer) +{ + int ntStatus = 0; + int ii; + + if (pDevice->Flags & fMP_DISCONNECTED) + return STATUS_FAILURE; + + if (pDevice->Flags & fMP_CONTROL_WRITES) + return STATUS_FAILURE; + + if (pDevice->Flags & fMP_CONTROL_READS) + return STATUS_FAILURE; + + MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); + + pDevice->sUsbCtlRequest.bRequestType = 0x40; + pDevice->sUsbCtlRequest.bRequest = byRequest; + pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); + pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex); + pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength); + pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK; + pDevice->pControlURB->actual_length = 0; + // Notice, pbyBuffer limited point to variable buffer, can't be constant. + usb_fill_control_urb(pDevice->pControlURB, pDevice->usb, + usb_sndctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest, + pbyBuffer, wLength, s_nsControlInUsbIoCompleteWrite, pDevice); + + ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); + if (ntStatus != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "control send request submission failed: %d\n", + ntStatus); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); + return STATUS_FAILURE; + } + + spin_unlock_irq(&pDevice->lock); + for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { + + if (pDevice->Flags & fMP_CONTROL_WRITES) + mdelay(1); + else + break; + + if (ii >= USB_CTL_WAIT) { + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "control send request submission timeout\n"); + spin_lock_irq(&pDevice->lock); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); + return STATUS_FAILURE; + } + } + spin_lock_irq(&pDevice->lock); + + return STATUS_SUCCESS; +} + +int PIPEnsControlIn(struct vnt_private *pDevice, u8 byRequest, u16 wValue, + u16 wIndex, u16 wLength, u8 *pbyBuffer) +{ + int ntStatus = 0; + int ii; + + if (pDevice->Flags & fMP_DISCONNECTED) + return STATUS_FAILURE; + + if (pDevice->Flags & fMP_CONTROL_READS) + return STATUS_FAILURE; + + if (pDevice->Flags & fMP_CONTROL_WRITES) + return STATUS_FAILURE; + + MP_SET_FLAG(pDevice, fMP_CONTROL_READS); + + pDevice->sUsbCtlRequest.bRequestType = 0xC0; + pDevice->sUsbCtlRequest.bRequest = byRequest; + pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); + pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex); + pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength); + pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK; + pDevice->pControlURB->actual_length = 0; + usb_fill_control_urb(pDevice->pControlURB, pDevice->usb, + usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest, + pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice); + + ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); + if (ntStatus != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "control request submission failed: %d\n", ntStatus); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); + return STATUS_FAILURE; + } + + spin_unlock_irq(&pDevice->lock); + for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { + + if (pDevice->Flags & fMP_CONTROL_READS) + mdelay(1); + else + break; + + if (ii >= USB_CTL_WAIT) { + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "control rcv request submission timeout\n"); + spin_lock_irq(&pDevice->lock); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); + return STATUS_FAILURE; + } + } + spin_lock_irq(&pDevice->lock); + + return ntStatus; +} + +static void s_nsControlInUsbIoCompleteWrite(struct urb *urb) +{ + struct vnt_private *pDevice = (struct vnt_private *)urb->context; + + pDevice = urb->context; + switch (urb->status) { + case 0: + break; + case -EINPROGRESS: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status); + break; + case -ENOENT: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status); + break; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status); + } + + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); +} + +/* + * Description: + * Complete function of usb Control callback + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * + * Out: + * none + * + * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver + * + */ + +static void s_nsControlInUsbIoCompleteRead(struct urb *urb) +{ + struct vnt_private *pDevice = (struct vnt_private *)urb->context; + + switch (urb->status) { + case 0: + break; + case -EINPROGRESS: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status); + break; + case -ENOENT: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status); + break; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status); + } + + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); +} + +/* + * Description: + * Allocates an usb interrupt in irp and calls USBD. + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * Out: + * none + * + * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver + * + */ + +int PIPEnsInterruptRead(struct vnt_private *pDevice) +{ + int ntStatus = STATUS_FAILURE; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n"); + + if(pDevice->intBuf.bInUse == true){ + return (STATUS_FAILURE); + } + pDevice->intBuf.bInUse = true; +// pDevice->bEventAvailable = false; + pDevice->ulIntInPosted++; + + // + // Now that we have created the urb, we will send a + // request to the USB device object. + // + pDevice->pInterruptURB->interval = pDevice->int_interval; + +usb_fill_bulk_urb(pDevice->pInterruptURB, + pDevice->usb, + usb_rcvbulkpipe(pDevice->usb, 1), + (void *) pDevice->intBuf.pDataBuf, + MAX_INTERRUPT_SIZE, + s_nsInterruptUsbIoCompleteRead, + pDevice); + + ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC); + if (ntStatus != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus); + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus); + return ntStatus; +} + +/* + * Description: + * Complete function of usb interrupt in irp. + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * + * Out: + * none + * + * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver + * + */ + +static void s_nsInterruptUsbIoCompleteRead(struct urb *urb) +{ + struct vnt_private *pDevice = (struct vnt_private *)urb->context; + int ntStatus; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptUsbIoCompleteRead\n"); + // + // The context given to IoSetCompletionRoutine is the receive buffer object + // + + // + // We have a number of cases: + // 1) The USB read timed out and we received no data. + // 2) The USB read timed out and we received some data. + // 3) The USB read was successful and fully filled our irp buffer. + // 4) The irp was cancelled. + // 5) Some other failure from the USB device object. + // + ntStatus = urb->status; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsInterruptUsbIoCompleteRead Status %d\n", ntStatus); + + // if we were not successful, we need to free the int buffer for future use right here + // otherwise interrupt data handler will free int buffer after it handle it. + if (( ntStatus != STATUS_SUCCESS )) { + pDevice->ulBulkInError++; + pDevice->intBuf.bInUse = false; + +// if (ntStatus == USBD_STATUS_CRC) { +// pDevice->ulIntInContCRCError++; +// } + +// if (ntStatus == STATUS_NOT_CONNECTED ) +// { + pDevice->fKillEventPollingThread = true; +// } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"IntUSBIoCompleteControl STATUS = %d\n", ntStatus ); + } else { + pDevice->ulIntInBytesRead += (unsigned long) urb->actual_length; + pDevice->ulIntInContCRCError = 0; + pDevice->bEventAvailable = true; + INTnsProcessData(pDevice); + } + + STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus); + + if (pDevice->fKillEventPollingThread != true) { + usb_fill_bulk_urb(pDevice->pInterruptURB, + pDevice->usb, + usb_rcvbulkpipe(pDevice->usb, 1), + (void *) pDevice->intBuf.pDataBuf, + MAX_INTERRUPT_SIZE, + s_nsInterruptUsbIoCompleteRead, + pDevice); + + ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC); + if (ntStatus != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus); + } + } + // + // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion + // routine (IofCompleteRequest) will stop working on the irp. + // + return ; +} + +/* + * Description: + * Allocates an usb BulkIn irp and calls USBD. + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * Out: + * none + * + * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver + * + */ + +int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, PRCB pRCB) +{ + int ntStatus = 0; + struct urb *pUrb; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n"); + + if (pDevice->Flags & fMP_DISCONNECTED) + return STATUS_FAILURE; + + pDevice->ulBulkInPosted++; + + pUrb = pRCB->pUrb; + // + // Now that we have created the urb, we will send a + // request to the USB device object. + // + if (pRCB->skb == NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n"); + return ntStatus; + } + + usb_fill_bulk_urb(pUrb, + pDevice->usb, + usb_rcvbulkpipe(pDevice->usb, 2), + (void *) (pRCB->skb->data), + MAX_TOTAL_SIZE_WITH_ALL_HEADERS, + s_nsBulkInUsbIoCompleteRead, + pRCB); + + ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC); + if (ntStatus != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus); + return STATUS_FAILURE ; + } + pRCB->Ref = 1; + pRCB->bBoolInUse= true; + + return ntStatus; +} + +/* + * Description: + * Complete function of usb BulkIn irp. + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * + * Out: + * none + * + * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver + * + */ + +static void s_nsBulkInUsbIoCompleteRead(struct urb *urb) +{ + PRCB pRCB = (PRCB)urb->context; + struct vnt_private *pDevice = pRCB->pDevice; + unsigned long bytesRead; + int bIndicateReceive = false; + int bReAllocSkb = false; + int status; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n"); + status = urb->status; + bytesRead = urb->actual_length; + + if (status) { + pDevice->ulBulkInError++; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status); + + pDevice->scStatistic.RxFcsErrCnt ++; +//todo...xxxxxx +// if (status == USBD_STATUS_CRC) { +// pDevice->ulBulkInContCRCError++; +// } +// if (status == STATUS_DEVICE_NOT_CONNECTED ) +// { +// MP_SET_FLAG(pDevice, fMP_DISCONNECTED); +// } + } else { + if (bytesRead) + bIndicateReceive = true; + pDevice->ulBulkInContCRCError = 0; + pDevice->ulBulkInBytesRead += bytesRead; + + pDevice->scStatistic.RxOkCnt ++; + } + + STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status); + + if (bIndicateReceive) { + spin_lock(&pDevice->lock); + if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == true) + bReAllocSkb = true; + spin_unlock(&pDevice->lock); + } + pRCB->Ref--; + if (pRCB->Ref == 0) + { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList); + spin_lock(&pDevice->lock); + RXvFreeRCB(pRCB, bReAllocSkb); + spin_unlock(&pDevice->lock); + } + + return; +} + +/* + * Description: + * Allocates an usb BulkOut irp and calls USBD. + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * Out: + * none + * + * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver + * + */ + +int PIPEnsSendBulkOut(struct vnt_private *pDevice, PUSB_SEND_CONTEXT pContext) +{ + int status; + struct urb *pUrb; + + pDevice->bPWBitOn = false; + +/* + if (pDevice->pPendingBulkOutContext != NULL) { + pDevice->NumContextsQueued++; + EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext); + status = STATUS_PENDING; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n"); + return status; + } +*/ + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n"); + + if (MP_IS_READY(pDevice) && (pDevice->Flags & fMP_POST_WRITES)) { + + pUrb = pContext->pUrb; + pDevice->ulBulkOutPosted++; +// pDevice->pPendingBulkOutContext = pContext; + usb_fill_bulk_urb( + pUrb, + pDevice->usb, + usb_sndbulkpipe(pDevice->usb, 3), + (void *) &(pContext->Data[0]), + pContext->uBufLen, + s_nsBulkOutIoCompleteWrite, + pContext); + + status = usb_submit_urb(pUrb, GFP_ATOMIC); + if (status != 0) + { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status); + pContext->bBoolInUse = false; + return STATUS_FAILURE; + } + return STATUS_PENDING; + } + else { + pContext->bBoolInUse = false; + return STATUS_RESOURCES; + } +} + +/* + * Description: s_nsBulkOutIoCompleteWrite + * 1a) Indicate to the protocol the status of the write. + * 1b) Return ownership of the packet to the protocol. + * + * 2) If any more packets are queue for sending, send another packet + * to USBD. + * If the attempt to send the packet to the driver fails, + * return ownership of the packet to the protocol and + * try another packet (until one succeeds). + * + * Parameters: + * In: + * pdoUsbDevObj - pointer to the USB device object which + * completed the irp + * pIrp - the irp which was completed by the + * device object + * pContext - the context given to IoSetCompletionRoutine + * before calling IoCallDriver on the irp + * The pContext is a pointer to the USB device object. + * Out: + * none + * + * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine + * (IofCompleteRequest) to stop working on the irp. + * + */ + +static void s_nsBulkOutIoCompleteWrite(struct urb *urb) +{ + struct vnt_private *pDevice; + int status; + CONTEXT_TYPE ContextType; + unsigned long ulBufLen; + PUSB_SEND_CONTEXT pContext; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n"); + // + // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct + // + pContext = (PUSB_SEND_CONTEXT) urb->context; + ASSERT( NULL != pContext ); + + pDevice = pContext->pDevice; + ContextType = pContext->Type; + ulBufLen = pContext->uBufLen; + + if (!netif_device_present(pDevice->dev)) + return; + + // + // Perform various IRP, URB, and buffer 'sanity checks' + // + + status = urb->status; + //we should have failed, succeeded, or cancelled, but NOT be pending + STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkOutStat, status); + + if(status == STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen); + pDevice->ulBulkOutBytesWrite += ulBufLen; + pDevice->ulBulkOutContCRCError = 0; + pDevice->nTxDataTimeCout = 0; + + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status); + pDevice->ulBulkOutError++; + } + +// pDevice->ulCheckForHangCount = 0; +// pDevice->pPendingBulkOutContext = NULL; + + if ( CONTEXT_DATA_PACKET == ContextType ) { + // Indicate to the protocol the status of the sent packet and return + // ownership of the packet. + if (pContext->pPacket != NULL) { + dev_kfree_skb_irq(pContext->pPacket); + pContext->pPacket = NULL; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx %d bytes\n",(int)ulBufLen); + } + + pDevice->dev->trans_start = jiffies; + + if (status == STATUS_SUCCESS) { + pDevice->packetsSent++; + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status); + pDevice->packetsSentDropped++; + } + + } + if (pDevice->bLinkPass == true) { + if (netif_queue_stopped(pDevice->dev)) + netif_wake_queue(pDevice->dev); + } + pContext->bBoolInUse = false; + + return; +} diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h new file mode 100644 index 00000000..bb7a6111 --- /dev/null +++ b/drivers/staging/vt6656/usbpipe.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: usbpipe.h + * + * Purpose: + * + * Author: Warren Hsu + * + * Date: Mar. 30, 2005 + * + */ + +#ifndef __USBPIPE_H__ +#define __USBPIPE_H__ + +#include "device.h" + +int PIPEnsControlOut(struct vnt_private *, u8 byRequest, u16 wValue, + u16 wIndex, u16 wLength, u8 *pbyBuffer); +int PIPEnsControlOutAsyn(struct vnt_private *, u8 byRequest, + u16 wValue, u16 wIndex, u16 wLength, u8 *pbyBuffer); +int PIPEnsControlIn(struct vnt_private *, u8 byRequest, u16 wValue, + u16 wIndex, u16 wLength, u8 *pbyBuffer); + +int PIPEnsInterruptRead(struct vnt_private *); +int PIPEnsBulkInUsbRead(struct vnt_private *, PRCB pRCB); +int PIPEnsSendBulkOut(struct vnt_private *, PUSB_SEND_CONTEXT pContext); + +#endif /* __USBPIPE_H__ */ diff --git a/drivers/staging/vt6656/vntconfiguration.dat b/drivers/staging/vt6656/vntconfiguration.dat new file mode 100644 index 00000000..933774c7 --- /dev/null +++ b/drivers/staging/vt6656/vntconfiguration.dat @@ -0,0 +1,6 @@ +#VNT Configuration +[start] +ZONETYPE=EUROPE +AUTHENMODE=12 +ENCRYPTIONMODE=34 +[end]
\ No newline at end of file diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c new file mode 100644 index 00000000..0013cb73 --- /dev/null +++ b/drivers/staging/vt6656/wcmd.c @@ -0,0 +1,1203 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: wcmd.c + * + * Purpose: Handles the management command interface functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2003 + * + * Functions: + * s_vProbeChannel - Active scan channel + * s_MgrMakeProbeRequest - Make ProbeRequest packet + * CommandTimer - Timer function to handle command + * s_bCommandComplete - Command Complete function + * bScheduleCommand - Push Command and wait Command Scheduler to do + * vCommandTimer- Command call back functions + * vCommandTimerWait- Call back timer + * s_bClearBSSID_SCAN- Clear BSSID_SCAN cmd in CMD Queue + * + * Revision History: + * + */ + +#include "tmacro.h" +#include "device.h" +#include "mac.h" +#include "card.h" +#include "80211hdr.h" +#include "wcmd.h" +#include "wmgr.h" +#include "power.h" +#include "wctl.h" +#include "baseband.h" +#include "control.h" +#include "rxtx.h" +#include "rf.h" +#include "rndis.h" +#include "channel.h" +#include "iowpa.h" + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +static void s_vProbeChannel(struct vnt_private *); + +static struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *, + struct vnt_manager *pMgmt, u8 *pScanBSSID, PWLAN_IE_SSID pSSID, + PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates); + +static int s_bCommandComplete(struct vnt_private *); + +static int s_bClearBSSID_SCAN(struct vnt_private *); + +/* + * Description: + * Stop AdHoc beacon during scan process + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * Out: + * none + * + * Return Value: none + * + */ + +static void vAdHocBeaconStop(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int bStop; + + /* + * temporarily stop Beacon packet for AdHoc Server + * if all of the following coditions are met: + * (1) STA is in AdHoc mode + * (2) VT3253 is programmed as automatic Beacon Transmitting + * (3) One of the following conditions is met + * (3.1) AdHoc channel is in B/G band and the + * current scan channel is in A band + * or + * (3.2) AdHoc channel is in A mode + */ + bStop = false; + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (pMgmt->eCurrState >= WMAC_STATE_STARTED)) + { + if ((pMgmt->uIBSSChannel <= CB_MAX_CHANNEL_24G) && + (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) + { + bStop = true; + } + if (pMgmt->uIBSSChannel > CB_MAX_CHANNEL_24G) + { + bStop = true; + } + } + + if (bStop) + { + //PMESG(("STOP_BEACON: IBSSChannel = %u, ScanChannel = %u\n", + // pMgmt->uIBSSChannel, pMgmt->uScanChannel)); + MACvRegBitsOff(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); + } + +} /* vAdHocBeaconStop */ + +/* + * Description: + * Restart AdHoc beacon after scan process complete + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * Out: + * none + * + * Return Value: none + * + */ +static void vAdHocBeaconRestart(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + /* + * Restart Beacon packet for AdHoc Server + * if all of the following coditions are met: + * (1) STA is in AdHoc mode + * (2) VT3253 is programmed as automatic Beacon Transmitting + */ + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (pMgmt->eCurrState >= WMAC_STATE_STARTED)) + { + //PMESG(("RESTART_BEACON\n")); + MACvRegBitsOn(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); + } + +} + +/*+ + * + * Routine Description: + * Prepare and send probe request management frames. + * + * + * Return Value: + * none. + * +-*/ + +static void s_vProbeChannel(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + struct vnt_tx_mgmt *pTxPacket; + u8 abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, + 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C}; + /* 1M, 2M, 5M, 11M, 18M, 24M, 36M, 54M*/ + u8 abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, + 4, 0x0C, 0x12, 0x18, 0x60}; + /* 6M, 9M, 12M, 48M*/ + u8 abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, + 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + u8 abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, + 4, 0x02, 0x04, 0x0B, 0x16}; + u8 *pbyRate; + int ii; + + if (pDevice->byBBType == BB_TYPE_11A) { + pbyRate = &abyCurrSuppRatesA[0]; + } else if (pDevice->byBBType == BB_TYPE_11B) { + pbyRate = &abyCurrSuppRatesB[0]; + } else { + pbyRate = &abyCurrSuppRatesG[0]; + } + // build an assocreq frame and send it + pTxPacket = s_MgrMakeProbeRequest + ( + pDevice, + pMgmt, + pMgmt->abyScanBSSID, + (PWLAN_IE_SSID)pMgmt->abyScanSSID, + (PWLAN_IE_SUPP_RATES)pbyRate, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG + ); + + if (pTxPacket != NULL ){ + for (ii = 0; ii < 1 ; ii++) { + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail.. \n"); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending.. \n"); + } + } + } + +} + +/*+ + * + * Routine Description: + * Constructs an probe request frame + * + * + * Return Value: + * A ptr to Tx frame or NULL on allocation failure + * +-*/ + +struct vnt_tx_mgmt *s_MgrMakeProbeRequest(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u8 *pScanBSSID, PWLAN_IE_SSID pSSID, + PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + WLAN_FR_PROBEREQ sFrame; + + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_PROBEREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_PROBEREQ_FR_MAXLEN; + vMgrEncodeProbeRequest(&sFrame); + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN); + // Copy the SSID, pSSID->len=0 indicate broadcast SSID + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += pSSID->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + // Copy the extension rate set + if (pDevice->byBBType == BB_TYPE_11G) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); + } + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + +void vCommandTimerWait(struct vnt_private *pDevice, unsigned long MSecond) +{ + + init_timer(&pDevice->sTimerCommand); + + pDevice->sTimerCommand.data = (unsigned long)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; + pDevice->sTimerCommand.expires = RUN_AT((MSecond * HZ) / 1000); + + add_timer(&pDevice->sTimerCommand); + + return; +} + +void vRunCommand(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PWLAN_IE_SSID pItemSSID; + PWLAN_IE_SSID pItemSSIDCurr; + CMD_STATUS Status; + struct sk_buff *skb; + union iwreq_data wrqu; + int ii; + u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + u8 byData; + + if (pDevice->dwDiagRefCount != 0) + return; + if (pDevice->bCmdRunning != true) + return; + + spin_lock_irq(&pDevice->lock); + + switch ( pDevice->eCommandState ) { + + case WLAN_CMD_SCAN_START: + + pDevice->byReAssocCount = 0; + if (pDevice->bRadioOff == true) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID; + + if (pMgmt->uScanChannel == 0 ) { + pMgmt->uScanChannel = pDevice->byMinChannel; + } + if (pMgmt->uScanChannel > pDevice->byMaxChannel) { + pDevice->eCommandState = WLAN_CMD_SCAN_END; + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + + } else { + if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n",pMgmt->uScanChannel); + pMgmt->uScanChannel++; + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + if (pMgmt->uScanChannel == pDevice->byMinChannel) { + // pMgmt->eScanType = WMAC_SCAN_ACTIVE; //mike mark + pMgmt->abyScanBSSID[0] = 0xFF; + pMgmt->abyScanBSSID[1] = 0xFF; + pMgmt->abyScanBSSID[2] = 0xFF; + pMgmt->abyScanBSSID[3] = 0xFF; + pMgmt->abyScanBSSID[4] = 0xFF; + pMgmt->abyScanBSSID[5] = 0xFF; + pItemSSID->byElementID = WLAN_EID_SSID; + // clear bssid list + /* BSSvClearBSSList((void *) pDevice, + pDevice->bLinkPass); */ + pMgmt->eScanState = WMAC_IS_SCANNING; + pDevice->byScanBBType = pDevice->byBBType; //lucas + pDevice->bStopDataPkt = true; + // Turn off RCR_BSSID filter every time + MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_BSSID); + pDevice->byRxMode &= ~RCR_BSSID; + + } + //lucas + vAdHocBeaconStop(pDevice); + if ((pDevice->byBBType != BB_TYPE_11A) && (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) { + pDevice->byBBType = BB_TYPE_11A; + CARDvSetBSSMode(pDevice); + } + else if ((pDevice->byBBType == BB_TYPE_11A) && (pMgmt->uScanChannel <= CB_MAX_CHANNEL_24G)) { + pDevice->byBBType = BB_TYPE_11G; + CARDvSetBSSMode(pDevice); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning.... channel: [%d]\n", pMgmt->uScanChannel); + // Set channel + CARDbSetMediaChannel(pDevice, pMgmt->uScanChannel); + // Set Baseband to be more sensitive. + + if (pDevice->bUpdateBBVGA) { + BBvSetShortSlotTime(pDevice); + BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); + BBvUpdatePreEDThreshold(pDevice, true); + } + pMgmt->uScanChannel++; + + while (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel) && + pMgmt->uScanChannel <= pDevice->byMaxChannel ){ + pMgmt->uScanChannel++; + } + + if (pMgmt->uScanChannel > pDevice->byMaxChannel) { + // Set Baseband to be not sensitive and rescan + pDevice->eCommandState = WLAN_CMD_SCAN_END; + + } + if ((pMgmt->b11hEnable == false) || + (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) { + s_vProbeChannel(pDevice); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, 100); + return; + } else { + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, WCMD_PASSIVE_SCAN_TIME); + return; + } + + } + + break; + + case WLAN_CMD_SCAN_END: + + // Set Baseband's sensitivity back. + if (pDevice->byBBType != pDevice->byScanBBType) { + pDevice->byBBType = pDevice->byScanBBType; + CARDvSetBSSMode(pDevice); + } + + if (pDevice->bUpdateBBVGA) { + BBvSetShortSlotTime(pDevice); + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); + BBvUpdatePreEDThreshold(pDevice, false); + } + + // Set channel back + vAdHocBeaconRestart(pDevice); + // Set channel back + CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel); + // Set Filter + if (pMgmt->bCurrBSSIDFilterOn) { + MACvRegBitsOn(pDevice, MAC_REG_RCR, RCR_BSSID); + pDevice->byRxMode |= RCR_BSSID; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel); + pMgmt->uScanChannel = 0; + pMgmt->eScanState = WMAC_NO_SCANNING; + pDevice->bStopDataPkt = false; + + /*send scan event to wpa_Supplicant*/ + PRINT_K("wireless_send_event--->SIOCGIWSCAN(scan done)\n"); + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL); + + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_DISASSOCIATE_START : + pDevice->byReAssocCount = 0; + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState != WMAC_STATE_ASSOC)) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } else { + + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = false; + pDevice->bWPASuppWextEnabled = false; + pDevice->fWPA_Authened = false; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send Disassociation Packet..\n"); + // reason = 8 : disassoc because sta has left + vMgrDisassocBeginSta((void *) pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + (8), + &Status); + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + // unlock command busy + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + pItemSSID->len = 0; + memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->sNodeDBTable[0].bActive = false; +// pDevice->bBeaconBufReady = false; + } + netif_stop_queue(pDevice->dev); + if (pDevice->bNeedRadioOFF == true) + CARDbRadioPowerOff(pDevice); + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_SSID_START: + + pDevice->byReAssocCount = 0; + if (pDevice->bRadioOff == true) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + + memcpy(pMgmt->abyAdHocSSID,pMgmt->abyDesireSSID, + ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN); + + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: desire ssid = %s\n", pItemSSID->abySSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID); + + if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSID->len =%d\n",pItemSSID->len); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSIDCurr->len = %d\n",pItemSSIDCurr->len); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" desire ssid = %s\n", pItemSSID->abySSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" curr ssid = %s\n", pItemSSIDCurr->abySSID); + } + + if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)&& (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { + + if (pItemSSID->len == pItemSSIDCurr->len) { + if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + } + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + } + // set initial state + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + PSvDisablePowerSaving((void *) pDevice); + BSSvClearNodeDBTable(pDevice, 0); + vMgrJoinBSSBegin((void *) pDevice, &Status); + // if Infra mode + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) { + // Call mgr to begin the deauthentication + // reason = (3) because sta has left ESS + if (pMgmt->eCurrState >= WMAC_STATE_AUTH) { + vMgrDeAuthenBeginSta((void *)pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + (3), + &Status); + } + // Call mgr to begin the authentication + vMgrAuthenBeginSta((void *) pDevice, pMgmt, &Status); + if (Status == CMD_STATUS_SUCCESS) { + pDevice->byLinkWaitCount = 0; + pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT; + vCommandTimerWait((void *) pDevice, AUTHENTICATE_TIMEOUT); + spin_unlock_irq(&pDevice->lock); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Set eCommandState = WLAN_AUTHENTICATE_WAIT\n"); + return; + } + } + // if Adhoc mode + else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + pMgmt->sNodeDBTable[0].bActive = true; + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + } + else { + // start own IBSS + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "CreateOwn IBSS by CurrMode = IBSS_STA\n"); + vMgrCreateOwnIBSS((void *) pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS){ + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "WLAN_CMD_IBSS_CREATE fail!\n"); + } + BSSvAddMulticastNode(pDevice); + } + s_bClearBSSID_SCAN(pDevice); + } + // if SSID not found + else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) { + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA || + pMgmt->eConfigMode == WMAC_CONFIG_AUTO) { + // start own IBSS + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "CreateOwn IBSS by CurrMode = STANDBY\n"); + vMgrCreateOwnIBSS((void *) pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS){ + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "WLAN_CMD_IBSS_CREATE fail!\n"); + } + BSSvAddMulticastNode(pDevice); + s_bClearBSSID_SCAN(pDevice); +/* + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + s_bClearBSSID_SCAN(pDevice); +*/ + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n"); + // if(pDevice->bWPASuppWextEnabled == true) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + } + } + s_bCommandComplete(pDevice); + break; + + case WLAN_AUTHENTICATE_WAIT : + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_AUTHENTICATE_WAIT\n"); + if (pMgmt->eCurrState == WMAC_STATE_AUTH) { + pDevice->byLinkWaitCount = 0; + // Call mgr to begin the association + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_AUTH\n"); + vMgrAssocBeginSta((void *) pDevice, pMgmt, &Status); + if (Status == CMD_STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState = WLAN_ASSOCIATE_WAIT\n"); + pDevice->byLinkWaitCount = 0; + pDevice->eCommandState = WLAN_ASSOCIATE_WAIT; + vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT); + spin_unlock_irq(&pDevice->lock); + return; + } + } + else if(pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { + printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n"); + } + else if(pDevice->byLinkWaitCount <= 4){ //mike add:wait another 2 sec if authenticated_frame delay! + pDevice->byLinkWaitCount ++; + printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n",pDevice->byLinkWaitCount); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, AUTHENTICATE_TIMEOUT/2); + return; + } + pDevice->byLinkWaitCount = 0; + + s_bCommandComplete(pDevice); + break; + + case WLAN_ASSOCIATE_WAIT : + if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_ASSOC\n"); + if (pDevice->ePSMode != WMAC_POWER_CAM) { + PSvEnablePowerSaving((void *) pDevice, + pMgmt->wListenInterval); + } +/* + if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA) { + KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID); + } +*/ + pDevice->byLinkWaitCount = 0; + pDevice->byReAssocCount = 0; + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + s_bClearBSSID_SCAN(pDevice); + + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + + if(pDevice->IsTxDataTrigger != false) { //TxDataTimer is not triggered at the first time + // printk("Re-initial TxDataTimer****\n"); + del_timer(&pDevice->sTimerTxData); + init_timer(&pDevice->sTimerTxData); + pDevice->sTimerTxData.data = (unsigned long) pDevice; + pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData; + pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback + pDevice->fTxDataInSleep = false; + pDevice->nTxDataTimeCout = 0; + } + else { + // printk("mike:-->First time trigger TimerTxData InSleep\n"); + } + pDevice->IsTxDataTrigger = true; + add_timer(&pDevice->sTimerTxData); + + } + else if(pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { + printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n"); + } + else if(pDevice->byLinkWaitCount <= 4){ //mike add:wait another 2 sec if associated_frame delay! + pDevice->byLinkWaitCount ++; + printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n",pDevice->byLinkWaitCount); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT/2); + return; + } + pDevice->byLinkWaitCount = 0; + + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_AP_MODE_START : + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n"); + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + del_timer(&pMgmt->sTimerSecondCallback); + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + if (pDevice->bEnableHostWEP == true) + BSSvClearNodeDBTable(pDevice, 1); + else + BSSvClearNodeDBTable(pDevice, 0); + pDevice->uAssocCount = 0; + pMgmt->eCurrState = WMAC_STATE_IDLE; + pDevice->bFixRate = false; + + vMgrCreateOwnIBSS((void *) pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "vMgrCreateOwnIBSS fail!\n"); + } + // always turn off unicast bit + MACvRegBitsOff(pDevice, MAC_REG_RCR, RCR_UNICAST); + pDevice->byRxMode &= ~RCR_UNICAST; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode ); + BSSvAddMulticastNode(pDevice); + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + add_timer(&pMgmt->sTimerSecondCallback); + } + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_TX_PSPACKET_START : + // DTIM Multicast tx + if (pMgmt->sNodeDBTable[0].bRxPSPoll) { + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) { + if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) { + pMgmt->abyPSTxMap[0] &= ~byMask[0]; + pDevice->bMoreData = false; + } + else { + pDevice->bMoreData = true; + } + + if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail \n"); + } + + pMgmt->sNodeDBTable[0].wEnQueueCnt--; + } + } + + // PS nodes tx + for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive && + pMgmt->sNodeDBTable[ii].bRxPSPoll) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d Enqueu Cnt= %d\n", + ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt); + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) { + if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) { + // clear tx map + pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= + ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; + pDevice->bMoreData = false; + } + else { + pDevice->bMoreData = true; + } + + if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb) != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail \n"); + } + + pMgmt->sNodeDBTable[ii].wEnQueueCnt--; + // check if sta ps enable, wait next pspoll + // if sta ps disable, send all pending buffers. + if (pMgmt->sNodeDBTable[ii].bPSEnable) + break; + } + if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) { + // clear tx map + pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= + ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear \n", ii); + } + pMgmt->sNodeDBTable[ii].bRxPSPoll = false; + } + } + + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_RADIO_START: + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_RADIO_START\n"); + // if (pDevice->bRadioCmd == true) + // CARDbRadioPowerOn(pDevice); + // else + // CARDbRadioPowerOff(pDevice); + + { + int ntStatus = STATUS_SUCCESS; + u8 byTmp; + + ntStatus = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + MAC_REG_GPIOCTL1, + MESSAGE_REQUEST_MACREG, + 1, + &byTmp); + + if ( ntStatus != STATUS_SUCCESS ) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + if ( (byTmp & GPIO3_DATA) == 0 ) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_OFF........................\n"); + // Old commands are useless. + // empty command Q + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + //0415pDevice->bCmdRunning = false; + pDevice->bCmdClear = true; + pDevice->bStopTx0Pkt = false; + pDevice->bStopDataPkt = true; + + pDevice->byKeyIndex = 0; + pDevice->bTransmitKey = false; + spin_unlock_irq(&pDevice->lock); + KeyvInitTable(pDevice,&pDevice->sKey); + spin_lock_irq(&pDevice->lock); + pMgmt->byCSSPK = KEY_CTL_NONE; + pMgmt->byCSSGK = KEY_CTL_NONE; + + if (pDevice->bLinkPass == true) { + // reason = 8 : disassoc because sta has left + vMgrDisassocBeginSta((void *) pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + (8), + &Status); + pDevice->bLinkPass = false; + // unlock command busy + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->sNodeDBTable[0].bActive = false; + // if(pDevice->bWPASuppWextEnabled == true) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + } + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = false; + pDevice->bWPASuppWextEnabled = false; + //clear current SSID + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + pItemSSID->len = 0; + memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); + //clear desired SSID + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSID->len = 0; + memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); + + netif_stop_queue(pDevice->dev); + CARDbRadioPowerOff(pDevice); + MACvRegBitsOn(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD); + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_OFF); + pDevice->bHWRadioOff = true; + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_RADIO_START_ON........................\n"); + pDevice->bHWRadioOff = false; + CARDbRadioPowerOn(pDevice); + MACvRegBitsOff(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD); + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_ON); + } + } + + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_CHANGE_BBSENSITIVITY_START: + + pDevice->bStopDataPkt = true; + pDevice->byBBVGACurrent = pDevice->byBBVGANew; + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change sensitivity pDevice->byBBVGACurrent = %x\n", pDevice->byBBVGACurrent); + pDevice->bStopDataPkt = false; + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_TBTT_WAKEUP_START: + PSbIsNextTBTTWakeUp(pDevice); + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_BECON_SEND_START: + bMgrPrepareBeaconToSend(pDevice, pMgmt); + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_SETPOWER_START: + + RFbSetPower(pDevice, pDevice->wCurrentRate, pMgmt->uCurrChannel); + + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_CHANGE_ANTENNA_START: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Change from Antenna%d to", (int)pDevice->dwRxAntennaSel); + if ( pDevice->dwRxAntennaSel == 0) { + pDevice->dwRxAntennaSel=1; + if (pDevice->bTxRxAntInv == true) + BBvSetAntennaMode(pDevice, ANT_RXA); + else + BBvSetAntennaMode(pDevice, ANT_RXB); + } else { + pDevice->dwRxAntennaSel=0; + if (pDevice->bTxRxAntInv == true) + BBvSetAntennaMode(pDevice, ANT_RXB); + else + BBvSetAntennaMode(pDevice, ANT_RXA); + } + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_REMOVE_ALLKEY_START: + KeybRemoveAllKey(pDevice, &(pDevice->sKey), pDevice->abyBSSID); + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_MAC_DISPOWERSAVING_START: + ControlvReadByte (pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData); + if ( (byData & PSCTL_PS) != 0 ) { + // disable power saving hw function + CONTROLnsRequestOut(pDevice, + MESSAGE_TYPE_DISABLE_PS, + 0, + 0, + 0, + NULL + ); + } + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_11H_CHSW_START: + CARDbSetMediaChannel(pDevice, pDevice->byNewChannel); + pDevice->bChannelSwitch = false; + pMgmt->uCurrChannel = pDevice->byNewChannel; + pDevice->bStopDataPkt = false; + s_bCommandComplete(pDevice); + break; + + default: + s_bCommandComplete(pDevice); + break; + } //switch + + spin_unlock_irq(&pDevice->lock); + return; +} + +static int s_bCommandComplete(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PWLAN_IE_SSID pSSID; + int bRadioCmd = false; + int bForceSCAN = true; + + pDevice->eCommandState = WLAN_CMD_IDLE; + if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) { + //Command Queue Empty + pDevice->bCmdRunning = false; + return true; + } + else { + pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd; + pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID; + bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd; + bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN; + ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE); + pDevice->cbFreeCmdQueue++; + pDevice->bCmdRunning = true; + switch ( pDevice->eCommand ) { + case WLAN_CMD_BSSID_SCAN: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_BSSID_SCAN\n"); + pDevice->eCommandState = WLAN_CMD_SCAN_START; + pMgmt->uScanChannel = 0; + if (pSSID->len != 0) { + memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + } else { + memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + } +/* + if ((bForceSCAN == false) && (pDevice->bLinkPass == true)) { + if ((pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) && + ( !memcmp(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, pSSID->len))) { + pDevice->eCommandState = WLAN_CMD_IDLE; + } + } +*/ + break; + case WLAN_CMD_SSID: + pDevice->eCommandState = WLAN_CMD_SSID_START; + if (pSSID->len > WLAN_SSID_MAXLEN) + pSSID->len = WLAN_SSID_MAXLEN; + if (pSSID->len != 0) + memcpy(pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_SSID_START\n"); + break; + case WLAN_CMD_DISASSOCIATE: + pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START; + break; + case WLAN_CMD_RX_PSPOLL: + pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START; + break; + case WLAN_CMD_RUN_AP: + pDevice->eCommandState = WLAN_CMD_AP_MODE_START; + break; + case WLAN_CMD_RADIO: + pDevice->eCommandState = WLAN_CMD_RADIO_START; + pDevice->bRadioCmd = bRadioCmd; + break; + case WLAN_CMD_CHANGE_BBSENSITIVITY: + pDevice->eCommandState = WLAN_CMD_CHANGE_BBSENSITIVITY_START; + break; + + case WLAN_CMD_TBTT_WAKEUP: + pDevice->eCommandState = WLAN_CMD_TBTT_WAKEUP_START; + break; + + case WLAN_CMD_BECON_SEND: + pDevice->eCommandState = WLAN_CMD_BECON_SEND_START; + break; + + case WLAN_CMD_SETPOWER: + pDevice->eCommandState = WLAN_CMD_SETPOWER_START; + break; + + case WLAN_CMD_CHANGE_ANTENNA: + pDevice->eCommandState = WLAN_CMD_CHANGE_ANTENNA_START; + break; + + case WLAN_CMD_REMOVE_ALLKEY: + pDevice->eCommandState = WLAN_CMD_REMOVE_ALLKEY_START; + break; + + case WLAN_CMD_MAC_DISPOWERSAVING: + pDevice->eCommandState = WLAN_CMD_MAC_DISPOWERSAVING_START; + break; + + case WLAN_CMD_11H_CHSW: + pDevice->eCommandState = WLAN_CMD_11H_CHSW_START; + break; + + default: + break; + + } + vCommandTimerWait(pDevice, 0); + } + + return true; +} + +int bScheduleCommand(struct vnt_private *pDevice, + CMD_CODE eCommand, u8 *pbyItem0) +{ + + if (pDevice->cbFreeCmdQueue == 0) { + return (false); + } + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand; + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true; + memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + if (pbyItem0 != NULL) { + switch (eCommand) { + case WLAN_CMD_BSSID_SCAN: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false; + memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, + pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + break; + + case WLAN_CMD_SSID: + memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, + pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + break; + + case WLAN_CMD_DISASSOCIATE: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0); + break; +/* + case WLAN_CMD_DEAUTH: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((u16 *)pbyItem0); + break; +*/ + + case WLAN_CMD_RADIO: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0); + break; + + default: + break; + } + } + + ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE); + pDevice->cbFreeCmdQueue--; + + if (pDevice->bCmdRunning == false) { + s_bCommandComplete(pDevice); + } + else { + } + return (true); + +} + +/* + * Description: + * Clear BSSID_SCAN cmd in CMD Queue + * + * Parameters: + * In: + * hDeviceContext - Pointer to the adapter + * eCommand - Command + * Out: + * none + * + * Return Value: true if success; otherwise false + * + */ +static int s_bClearBSSID_SCAN(struct vnt_private *pDevice) +{ + unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx; + unsigned int ii; + + if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) { + for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii ++) { + if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN) + pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE; + ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE); + if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx) + break; + } + } + return true; +} + +//mike add:reset command timer +void vResetCommandTimer(struct vnt_private *pDevice) +{ + + //delete timer + del_timer(&pDevice->sTimerCommand); + //init timer + init_timer(&pDevice->sTimerCommand); + pDevice->sTimerCommand.data = (unsigned long)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; + pDevice->sTimerCommand.expires = RUN_AT(HZ); + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + pDevice->eCommandState = WLAN_CMD_IDLE; + pDevice->bCmdRunning = false; + pDevice->bCmdClear = false; +} + +void BSSvSecondTxData(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + pDevice->nTxDataTimeCout++; + + if (pDevice->nTxDataTimeCout < 4) { //don't tx data if timer less than 40s + // printk("mike:%s-->no data Tx not exceed the desired Time as %d\n",__FUNCTION__, + // (int)pDevice->nTxDataTimeCout); + pDevice->sTimerTxData.expires = RUN_AT(10 * HZ); //10s callback + add_timer(&pDevice->sTimerTxData); + return; + } + + spin_lock_irq(&pDevice->lock); + //is wap_supplicant running successful OR only open && sharekey mode! + if (((pDevice->bLinkPass == true) && + (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) || //open && sharekey linking + (pDevice->fWPA_Authened == true)) { //wpa linking + // printk("mike:%s-->InSleep Tx Data Procedure\n",__FUNCTION__); + pDevice->fTxDataInSleep = true; + PSbSendNullPacket(pDevice); //send null packet + pDevice->fTxDataInSleep = false; + } + spin_unlock_irq(&pDevice->lock); + + pDevice->sTimerTxData.expires = RUN_AT(10 * HZ); //10s callback + add_timer(&pDevice->sTimerTxData); +} diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h new file mode 100644 index 00000000..db8b4cf7 --- /dev/null +++ b/drivers/staging/vt6656/wcmd.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: wcmd.h + * + * Purpose: Handles the management command interface functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + */ + +#ifndef __WCMD_H__ +#define __WCMD_H__ + +#include "80211hdr.h" +#include "80211mgr.h" + +#define AUTHENTICATE_TIMEOUT 1000 //ms +#define ASSOCIATE_TIMEOUT 1000 //ms + +// Command code +typedef enum tagCMD_CODE { + WLAN_CMD_BSSID_SCAN, + WLAN_CMD_SSID, + WLAN_CMD_DISASSOCIATE, + WLAN_CMD_DEAUTH, + WLAN_CMD_RX_PSPOLL, + WLAN_CMD_RADIO, + WLAN_CMD_CHANGE_BBSENSITIVITY, + WLAN_CMD_SETPOWER, + WLAN_CMD_TBTT_WAKEUP, + WLAN_CMD_BECON_SEND, + WLAN_CMD_CHANGE_ANTENNA, + WLAN_CMD_REMOVE_ALLKEY, + WLAN_CMD_MAC_DISPOWERSAVING, + WLAN_CMD_11H_CHSW, + WLAN_CMD_RUN_AP +} CMD_CODE, *PCMD_CODE; + +#define CMD_Q_SIZE 32 + +typedef enum tagCMD_STATUS { + + CMD_STATUS_SUCCESS = 0, + CMD_STATUS_FAILURE, + CMD_STATUS_RESOURCES, + CMD_STATUS_TIMEOUT, + CMD_STATUS_PENDING + +} CMD_STATUS, *PCMD_STATUS; + +typedef struct tagCMD_ITEM { + CMD_CODE eCmd; + u8 abyCmdDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + bool bNeedRadioOFF; + bool bRadioCmd; + bool bForceSCAN; + u16 wDeAuthenReason; +} CMD_ITEM, *PCMD_ITEM; + +// Command state +typedef enum tagCMD_STATE { + WLAN_CMD_SCAN_START, + WLAN_CMD_SCAN_END, + WLAN_CMD_DISASSOCIATE_START, + WLAN_CMD_DEAUTHEN_START, + WLAN_CMD_SSID_START, + WLAN_AUTHENTICATE_WAIT, + WLAN_ASSOCIATE_WAIT, + WLAN_DISASSOCIATE_WAIT, + WLAN_CMD_TX_PSPACKET_START, + WLAN_CMD_RADIO_START, + WLAN_CMD_CHANGE_BBSENSITIVITY_START, + WLAN_CMD_SETPOWER_START, + WLAN_CMD_AP_MODE_START, + WLAN_CMD_TBTT_WAKEUP_START, + WLAN_CMD_BECON_SEND_START, + WLAN_CMD_CHANGE_ANTENNA_START, + WLAN_CMD_REMOVE_ALLKEY_START, + WLAN_CMD_MAC_DISPOWERSAVING_START, + WLAN_CMD_11H_CHSW_START, + WLAN_CMD_IDLE +} CMD_STATE, *PCMD_STATE; + +struct vnt_private; + +void vResetCommandTimer(struct vnt_private *); + +int bScheduleCommand(struct vnt_private *, CMD_CODE eCommand, u8 *pbyItem0); + +void vRunCommand(struct vnt_private *); + +/* +void +WCMDvCommandThread( + void * Context + ); +*/ + +void BSSvSecondTxData(struct vnt_private *); + +#endif /* __WCMD_H__ */ diff --git a/drivers/staging/vt6656/wctl.c b/drivers/staging/vt6656/wctl.c new file mode 100644 index 00000000..47a655db --- /dev/null +++ b/drivers/staging/vt6656/wctl.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: wctl.c + * + * Purpose: handle WMAC duplicate filter & defragment + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + * Functions: + * WCTLbIsDuplicate - Test if duplicate packet + * WCTLuSearchDFCB - Search DeFragment Control Database + * WCTLuInsertDFCB - Insert DeFragment Control Database + * WCTLbHandleFragment - Handle received fragment packet + * + * Revision History: + * + */ + +#include "wctl.h" +#include "device.h" +#include "card.h" +#include "tmacro.h" + +// static int msglevel =MSG_LEVEL_INFO; + +/* + * Description: + * Scan Rx cache. Return true if packet is duplicate, else + * inserts in receive cache and returns false. + * + * Parameters: + * In: + * pCache - Receive packets history + * pMACHeader - 802.11 MAC Header of received packet + * Out: + * none + * + * Return Value: true if packet duplicate; otherwise false + * + */ + +bool WCTLbIsDuplicate (PSCache pCache, struct ieee80211_hdr *pMACHeader) +{ + unsigned int uIndex; + unsigned int ii; + PSCacheEntry pCacheEntry; + + if (IS_FC_RETRY(pMACHeader)) { + + uIndex = pCache->uInPtr; + for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) { + pCacheEntry = &(pCache->asCacheEntry[uIndex]); + if ((pCacheEntry->wFmSequence == pMACHeader->seq_ctrl) && + (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]), + &(pMACHeader->addr2[0]))) && + (LOBYTE(pCacheEntry->wFrameCtl) == LOBYTE(pMACHeader->frame_control)) + ) { + /* Duplicate match */ + return true; + } + ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH); + } + } + /* Not found in cache - insert */ + pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr]; + pCacheEntry->wFmSequence = pMACHeader->seq_ctrl; + memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->addr2[0]), ETH_ALEN); + pCacheEntry->wFrameCtl = pMACHeader->frame_control; + ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH); + return false; +} + +/* + * Description: + * Found if sequence number of received fragment packet in Defragment Database + * + * Parameters: + * In: + * pDevice - Pointer to adapter + * pMACHeader - 802.11 MAC Header of received packet + * Out: + * none + * + * Return Value: index number in Defragment Database + * + */ + +unsigned int WCTLuSearchDFCB(struct vnt_private *pDevice, + struct ieee80211_hdr *pMACHeader) +{ + unsigned int ii; + + for (ii = 0; ii < pDevice->cbDFCB; ii++) { + if ((pDevice->sRxDFCB[ii].bInUse == true) && + (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]), + &(pMACHeader->addr2[0])))) { + return ii; + } + } + return pDevice->cbDFCB; +} + +/* + * Description: + * Insert received fragment packet in Defragment Database + * + * Parameters: + * In: + * pDevice - Pointer to adapter + * pMACHeader - 802.11 MAC Header of received packet + * Out: + * none + * + * Return Value: index number in Defragment Database + * + */ +unsigned int WCTLuInsertDFCB(struct vnt_private *pDevice, + struct ieee80211_hdr *pMACHeader) +{ + unsigned int ii; + + if (pDevice->cbFreeDFCB == 0) + return(pDevice->cbDFCB); + for (ii = 0; ii < pDevice->cbDFCB; ii++) { + if (pDevice->sRxDFCB[ii].bInUse == false) { + pDevice->cbFreeDFCB--; + pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime; + pDevice->sRxDFCB[ii].bInUse = true; + pDevice->sRxDFCB[ii].wSequence = (pMACHeader->seq_ctrl >> 4); + pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->seq_ctrl & 0x000F); + memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]), + &(pMACHeader->addr2[0]), + ETH_ALEN); + return(ii); + } + } + return(pDevice->cbDFCB); +} + +/* + * Description: + * Handle received fragment packet + * + * Parameters: + * In: + * pDevice - Pointer to adapter + * pMACHeader - 802.11 MAC Header of received packet + * cbFrameLength - Frame length + * bWEP - is WEP packet + * Out: + * none + * + * Return Value: true if it is valid fragment packet and we have resource to defragment; otherwise false + * + */ +bool WCTLbHandleFragment(struct vnt_private *pDevice, struct ieee80211_hdr *pMACHeader, unsigned int cbFrameLength, bool bWEP, bool bExtIV) +{ + unsigned int uHeaderSize; + + if (bWEP == true) { + uHeaderSize = 28; + if (bExtIV) + // ExtIV + uHeaderSize +=4; + } + else { + uHeaderSize = 24; + } + + if (IS_FIRST_FRAGMENT_PKT(pMACHeader)) { + pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader); + if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) { + // duplicate, we must flush previous DCB + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime; + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->seq_ctrl >> 4); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->seq_ctrl & 0x000F); + } + else { + pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader); + if (pDevice->uCurrentDFCBIdx == pDevice->cbDFCB) { + return(false); + } + } + // reserve 8 byte to match MAC RX Buffer + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (u8 *) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 8); +// pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (u8 *) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4); + memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength; + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength; + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++; + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx); + return(false); + } + else { + pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader); + if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) { + if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->seq_ctrl >> 4)) && + (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->seq_ctrl & 0x000F)) && + ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) { + + memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((u8 *) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize)); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++; + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Second pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx); + } + else { + // seq error or frag # error flush DFCB + pDevice->cbFreeDFCB++; + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false; + return(false); + } + } + else { + return(false); + } + if (IS_LAST_FRAGMENT_PKT(pMACHeader)) { + //enq defragcontrolblock + pDevice->cbFreeDFCB++; + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false; + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx); + return(true); + } + return(false); + } +} + diff --git a/drivers/staging/vt6656/wctl.h b/drivers/staging/vt6656/wctl.h new file mode 100644 index 00000000..14cb4117 --- /dev/null +++ b/drivers/staging/vt6656/wctl.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: wctl.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + */ + +#ifndef __WCTL_H__ +#define __WCTL_H__ + +#include "tether.h" +#include "device.h" + +#define IS_TYPE_DATA(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & TYPE_802_11_MASK) == TYPE_802_11_DATA) + +#define IS_TYPE_MGMT(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & TYPE_802_11_MASK) == TYPE_802_11_MGMT) + +#define IS_TYPE_CONTROL(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & TYPE_802_11_MASK) == TYPE_802_11_CTL) + +#define IS_FC_MOREDATA(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_MOREDATA) == FC_MOREDATA) + +#define IS_FC_POWERMGT(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_POWERMGT) == FC_POWERMGT) + +#define IS_FC_RETRY(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_RETRY) == FC_RETRY) + +#define IS_FC_WEP(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_WEP) == FC_WEP) + +#ifdef __BIG_ENDIAN + +#define IS_FRAGMENT_PKT(pMACHeader) \ + (((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_MOREFRAG) != 0) | \ + ((((struct ieee80211_hdr *) pMACHeader)->seq_ctrl & 0x0F00) != 0)) + +#define IS_FIRST_FRAGMENT_PKT(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->seq_ctrl & 0x0F00) == 0) + +#else + +#define IS_FRAGMENT_PKT(pMACHeader) \ + (((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_MOREFRAG) != 0) | \ + ((((struct ieee80211_hdr *) pMACHeader)->seq_ctrl & 0x000F) != 0)) + +#define IS_FIRST_FRAGMENT_PKT(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->seq_ctrl & 0x000F) == 0) + +#endif//#ifdef __BIG_ENDIAN + +#define IS_LAST_FRAGMENT_PKT(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & FC_MOREFRAG) == 0) + +#define IS_CTL_PSPOLL(pMACHeader) \ + ((((struct ieee80211_hdr *) pMACHeader)->frame_control & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) + +#define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) { \ + if ((uVar) >= ((uModulo) - 1)) \ + (uVar) = 0; \ + else \ + (uVar)++; \ +} + +bool WCTLbIsDuplicate(PSCache pCache, struct ieee80211_hdr *pMACHeader); +bool WCTLbHandleFragment(struct vnt_private *, struct ieee80211_hdr *pMACHeader, unsigned int cbFrameLength, bool bWEP, bool bExtIV); +unsigned int WCTLuSearchDFCB(struct vnt_private *, struct ieee80211_hdr *pMACHeader); +unsigned int WCTLuInsertDFCB(struct vnt_private *, struct ieee80211_hdr *pMACHeader); + +#endif /* __WCTL_H__ */ diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c new file mode 100644 index 00000000..6d1ff5ee --- /dev/null +++ b/drivers/staging/vt6656/wmgr.c @@ -0,0 +1,4408 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: wmgr.c + * + * Purpose: Handles the 802.11 management functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + * Functions: + * nsMgrObjectInitial - Initialize Management Objet data structure + * vMgrObjectReset - Reset Management Object data structure + * vMgrAssocBeginSta - Start associate function + * vMgrReAssocBeginSta - Start reassociate function + * vMgrDisassocBeginSta - Start disassociate function + * s_vMgrRxAssocRequest - Handle Rcv associate_request + * s_vMgrRxAssocResponse - Handle Rcv associate_response + * vMrgAuthenBeginSta - Start authentication function + * vMgrDeAuthenDeginSta - Start deauthentication function + * s_vMgrRxAuthentication - Handle Rcv authentication + * s_vMgrRxAuthenSequence_1 - Handle Rcv authentication sequence 1 + * s_vMgrRxAuthenSequence_2 - Handle Rcv authentication sequence 2 + * s_vMgrRxAuthenSequence_3 - Handle Rcv authentication sequence 3 + * s_vMgrRxAuthenSequence_4 - Handle Rcv authentication sequence 4 + * s_vMgrRxDisassociation - Handle Rcv disassociation + * s_vMgrRxBeacon - Handle Rcv Beacon + * vMgrCreateOwnIBSS - Create ad_hoc IBSS or AP BSS + * vMgrJoinBSSBegin - Join BSS function + * s_vMgrSynchBSS - Synch & adopt BSS parameters + * s_MgrMakeBeacon - Create Baecon frame + * s_MgrMakeProbeResponse - Create Probe Response frame + * s_MgrMakeAssocRequest - Create Associate Request frame + * s_MgrMakeReAssocRequest - Create ReAssociate Request frame + * s_vMgrRxProbeResponse - Handle Rcv probe_response + * s_vMrgRxProbeRequest - Handle Rcv probe_request + * bMgrPrepareBeaconToSend - Prepare Beacon frame + * s_vMgrLogStatus - Log 802.11 Status + * vMgrRxManagePacket - Rcv management frame dispatch function + * s_vMgrFormatTIM- Assembler TIM field of beacon + * vMgrTimerInit- Initial 1-sec and command call back funtions + * + * Revision History: + * + */ + +#include "tmacro.h" +#include "desc.h" +#include "device.h" +#include "card.h" +#include "80211hdr.h" +#include "80211mgr.h" +#include "wmgr.h" +#include "wcmd.h" +#include "mac.h" +#include "bssdb.h" +#include "power.h" +#include "datarate.h" +#include "baseband.h" +#include "rxtx.h" +#include "wpa.h" +#include "rf.h" +#include "iowpa.h" +#include "control.h" +#include "rndis.h" + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +static int ChannelExceedZoneType(struct vnt_private *, u8 byCurrChannel); + +/* Association/diassociation functions */ +static struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *, + struct vnt_manager *pMgmt, u8 *pDAddr, u16 wCurrCapInfo, + u16 wListenInterval, PWLAN_IE_SSID pCurrSSID, + PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates); + +static void s_vMgrRxAssocRequest(struct vnt_private *, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket, + u32 uNodeIndex); + +static struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *, + struct vnt_manager *pMgmt, u8 *pDAddr, u16 wCurrCapInfo, + u16 wListenInterval, PWLAN_IE_SSID pCurrSSID, + PWLAN_IE_SUPP_RATES pCurrRates, PWLAN_IE_SUPP_RATES pCurrExtSuppRates); + +static void s_vMgrRxAssocResponse(struct vnt_private *, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket, + int bReAssocType); + +static void s_vMgrRxDisassociation(struct vnt_private *, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket); + +/* Authentication/deauthen functions */ +static void s_vMgrRxAuthenSequence_1(struct vnt_private *, + struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame); + +static void s_vMgrRxAuthenSequence_2(struct vnt_private *, + struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame); + +static void s_vMgrRxAuthenSequence_3(struct vnt_private *, + struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame); + +static void s_vMgrRxAuthenSequence_4(struct vnt_private *, + struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame); + +static void s_vMgrRxAuthentication(struct vnt_private *, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket); + +static void s_vMgrRxDeauthentication(struct vnt_private *, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket); + +/* Scan functions +* probe request/response functions */ + +static void s_vMgrRxProbeRequest(struct vnt_private *, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket); + +static void s_vMgrRxProbeResponse(struct vnt_private *, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket); + +/* beacon functions */ +static void s_vMgrRxBeacon(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket, + int bInScan); + +static void s_vMgrFormatTIM(struct vnt_manager *pMgmt, PWLAN_IE_TIM pTIM); + +static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wCurrBeaconPeriod, + u32 uCurrChannel, u16 wCurrATIMWinodw, PWLAN_IE_SSID pCurrSSID, + u8 *pCurrBSSID, PWLAN_IE_SUPP_RATES pCurrSuppRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates); + +/* Association response */ +static struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *, + struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wAssocStatus, + u16 wAssocAID, u8 *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates); + +/* ReAssociation response */ +static struct vnt_tx_mgmt *s_MgrMakeReAssocResponse(struct vnt_private *, + struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wAssocStatus, + u16 wAssocAID, u8 *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates); + +/* Probe response */ +static struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *, + struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wCurrBeaconPeriod, + u32 uCurrChannel, u16 wCurrATIMWinodw, u8 *pDstAddr, + PWLAN_IE_SSID pCurrSSID, u8 *pCurrBSSID, + PWLAN_IE_SUPP_RATES pCurrSuppRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates, u8 byPHYType); + +/* received status */ +static void s_vMgrLogStatus(struct vnt_manager *pMgmt, u16 wStatus); + +static void s_vMgrSynchBSS(struct vnt_private *, u32 uBSSMode, + PKnownBSS pCurr, PCMD_STATUS pStatus); + +static bool +s_bCipherMatch ( + PKnownBSS pBSSNode, + NDIS_802_11_ENCRYPTION_STATUS EncStatus, + u8 * pbyCCSPK, + u8 * pbyCCSGK + ); + +static void Encyption_Rebuild(struct vnt_private *, PKnownBSS pCurr); + +/*+ + * + * Routine Description: + * Allocates and initializes the Management object. + * + * Return Value: + * Ndis_staus. + * +-*/ + +void vMgrObjectInit(struct vnt_private *pDevice) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + int ii; + + pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0]; + pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0]; + pMgmt->uCurrChannel = pDevice->uChannel; + for (ii = 0; ii < WLAN_BSSID_LEN; ii++) + pMgmt->abyDesireBSSID[ii] = 0xFF; + + pMgmt->sAssocInfo.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + //memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN +1); + pMgmt->byCSSPK = KEY_CTL_NONE; + pMgmt->byCSSGK = KEY_CTL_NONE; + pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI; + BSSvClearBSSList((void *) pDevice, false); + + init_timer(&pMgmt->sTimerSecondCallback); + pMgmt->sTimerSecondCallback.data = (unsigned long)pDevice; + pMgmt->sTimerSecondCallback.function = (TimerFunction)BSSvSecondCallBack; + pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ); + + init_timer(&pDevice->sTimerCommand); + pDevice->sTimerCommand.data = (unsigned long)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; + pDevice->sTimerCommand.expires = RUN_AT(HZ); + + init_timer(&pDevice->sTimerTxData); + pDevice->sTimerTxData.data = (unsigned long)pDevice; + pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData; + pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback + pDevice->fTxDataInSleep = false; + pDevice->IsTxDataTrigger = false; + pDevice->nTxDataTimeCout = 0; + + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + pDevice->eCommandState = WLAN_CMD_IDLE; + pDevice->bCmdRunning = false; + pDevice->bCmdClear = false; + + return; +} + +/*+ + * + * Routine Description: + * Start the station association procedure. Namely, send an + * association request frame to the AP. + * + * Return Value: + * None. + * +-*/ + +void vMgrAssocBeginSta(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, PCMD_STATUS pStatus) +{ + struct vnt_tx_mgmt *pTxPacket; + + pMgmt->wCurrCapInfo = 0; + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1); + if (pDevice->bEncryptionEnable) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1); + } + // always allow receive short preamble + //if (pDevice->byPreambleType == 1) { + // pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + //} + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + if (pMgmt->wListenInterval == 0) + pMgmt->wListenInterval = 1; // at least one. + + // ERP Phy (802.11g) should support short preamble. + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + if (pDevice->bShortSlotTime == true) + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1); + + } else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) { + if (pDevice->byPreambleType == 1) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + } + } + if (pMgmt->b11hEnable == true) + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1); + + // build an assocreq frame and send it + pTxPacket = s_MgrMakeAssocRequest + ( + pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + pMgmt->wCurrCapInfo, + pMgmt->wListenInterval, + (PWLAN_IE_SSID)pMgmt->abyCurrSSID, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + + if (pTxPacket != NULL ){ + // send the frame + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus == CMD_STATUS_PENDING) { + pMgmt->eCurrState = WMAC_STATE_ASSOCPENDING; + *pStatus = CMD_STATUS_SUCCESS; + } + } + else + *pStatus = CMD_STATUS_RESOURCES; + + return ; +} + +/*+ + * + * Routine Description: + * Start the station re-association procedure. + * + * Return Value: + * None. + * +-*/ + +void vMgrReAssocBeginSta(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, PCMD_STATUS pStatus) +{ + struct vnt_tx_mgmt *pTxPacket; + + pMgmt->wCurrCapInfo = 0; + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1); + if (pDevice->bEncryptionEnable) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1); + } + + //if (pDevice->byPreambleType == 1) { + // pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + //} + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + + if (pMgmt->wListenInterval == 0) + pMgmt->wListenInterval = 1; // at least one. + + // ERP Phy (802.11g) should support short preamble. + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + if (pDevice->bShortSlotTime == true) + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1); + + } else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) { + if (pDevice->byPreambleType == 1) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + } + } + if (pMgmt->b11hEnable == true) + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1); + + pTxPacket = s_MgrMakeReAssocRequest + ( + pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + pMgmt->wCurrCapInfo, + pMgmt->wListenInterval, + (PWLAN_IE_SSID)pMgmt->abyCurrSSID, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + + if (pTxPacket != NULL ){ + // send the frame + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Reassociation tx failed.\n"); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Reassociation tx sending.\n"); + } + } + + return ; +} + +/*+ + * + * Routine Description: + * Send an dis-association request frame to the AP. + * + * Return Value: + * None. + * +-*/ + +void vMgrDisassocBeginSta(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u8 *abyDestAddress, u16 wReason, + PCMD_STATUS pStatus) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + WLAN_FR_DISASSOC sFrame; + + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_DISASSOC_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + + // Setup the sFrame structure + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_DISASSOC_FR_MAXLEN; + + // format fixed field frame structure + vMgrEncodeDisassociation(&sFrame); + + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DISASSOC) + )); + + memcpy( sFrame.pHdr->sA3.abyAddr1, abyDestAddress, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + // Set reason code + *(sFrame.pwReason) = cpu_to_le16(wReason); + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + // send the frame + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus == CMD_STATUS_PENDING) { + pMgmt->eCurrState = WMAC_STATE_IDLE; + *pStatus = CMD_STATUS_SUCCESS; + } + + return; +} + +/*+ + * + * Routine Description:(AP function) + * Handle incoming station association request frames. + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxAssocRequest(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket, + u32 uNodeIndex) +{ + WLAN_FR_ASSOCREQ sFrame; + CMD_STATUS Status; + struct vnt_tx_mgmt *pTxPacket; + u16 wAssocStatus = 0; + u16 wAssocAID = 0; + u32 uRateLen = WLAN_RATES_MAXLEN; + u8 abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + u8 abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + + if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) + return; + // node index not found + if (!uNodeIndex) + return; + + //check if node is authenticated + //decode the frame + memset(&sFrame, 0, sizeof(WLAN_FR_ASSOCREQ)); + memset(abyCurrSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + memset(abyCurrExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + + vMgrDecodeAssocRequest(&sFrame); + + if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC; + pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = cpu_to_le16(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = cpu_to_le16(*sFrame.pwListenInterval); + pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = + WLAN_GET_FC_PWRMGT(sFrame.pHdr->sA3.wFrameCtl) ? true : false; + // Todo: check sta basic rate, if ap can't support, set status code + if (pDevice->byBBType == BB_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES; + abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrSuppRates, + uRateLen); + abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES; + if (pDevice->byBBType == BB_TYPE_11G) { + abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pExtSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates, + uRateLen); + } else { + abyCurrExtSuppRates[1] = 0; + } + + RATEvParseMaxRate((void *)pDevice, + (PWLAN_IE_SUPP_RATES)abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates, + false, // do not change our basic rate + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate) + ); + + // set max tx rate + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; + // Todo: check sta preamble, if ap can't support, set status code + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = + WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = + WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wAID = (u16)uNodeIndex; + wAssocStatus = WLAN_MGMT_STATUS_SUCCESS; + wAssocAID = (u16)uNodeIndex; + // check if ERP support + if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M) + pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true; + + if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate <= RATE_11M) { + // B only STA join + pDevice->bProtectMode = true; + pDevice->bNonERPPresent = true; + } + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == false) { + pDevice->bBarkerPreambleMd = true; + } + + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Associate AID= %d \n", wAssocAID); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n", + sFrame.pHdr->sA3.abyAddr2[0], + sFrame.pHdr->sA3.abyAddr2[1], + sFrame.pHdr->sA3.abyAddr2[2], + sFrame.pHdr->sA3.abyAddr2[3], + sFrame.pHdr->sA3.abyAddr2[4], + sFrame.pHdr->sA3.abyAddr2[5] + ) ; + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Max Support rate = %d \n", + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate); + } + + // assoc response reply.. + pTxPacket = s_MgrMakeAssocResponse + ( + pDevice, + pMgmt, + pMgmt->wCurrCapInfo, + wAssocStatus, + wAssocAID, + sFrame.pHdr->sA3.abyAddr2, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + if (pTxPacket != NULL ){ + + if (pDevice->bEnableHostapd) { + return; + } + /* send the frame */ + Status = csMgmt_xmit(pDevice, pTxPacket); + if (Status != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Assoc response tx failed\n"); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Assoc response tx sending..\n"); + } + + } + + return; +} + +/*+ + * + * Description:(AP function) + * Handle incoming station re-association request frames. + * + * Parameters: + * In: + * pMgmt - Management Object structure + * pRxPacket - Received Packet + * Out: + * none + * + * Return Value: None. + * +-*/ + +static void s_vMgrRxReAssocRequest(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket, + u32 uNodeIndex) +{ + WLAN_FR_REASSOCREQ sFrame; + CMD_STATUS Status; + struct vnt_tx_mgmt *pTxPacket; + u16 wAssocStatus = 0; + u16 wAssocAID = 0; + u32 uRateLen = WLAN_RATES_MAXLEN; + u8 abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + u8 abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + + if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) + return; + // node index not found + if (!uNodeIndex) + return; + //check if node is authenticated + //decode the frame + memset(&sFrame, 0, sizeof(WLAN_FR_REASSOCREQ)); + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + vMgrDecodeReassocRequest(&sFrame); + + if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC; + pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = cpu_to_le16(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = cpu_to_le16(*sFrame.pwListenInterval); + pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = + WLAN_GET_FC_PWRMGT(sFrame.pHdr->sA3.wFrameCtl) ? true : false; + // Todo: check sta basic rate, if ap can't support, set status code + + if (pDevice->byBBType == BB_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + + abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES; + abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrSuppRates, + uRateLen); + abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES; + if (pDevice->byBBType == BB_TYPE_11G) { + abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pExtSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates, + uRateLen); + } else { + abyCurrExtSuppRates[1] = 0; + } + + RATEvParseMaxRate((void *)pDevice, + (PWLAN_IE_SUPP_RATES)abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates, + false, // do not change our basic rate + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate) + ); + + // set max tx rate + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; + // Todo: check sta preamble, if ap can't support, set status code + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = + WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = + WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wAID = (u16)uNodeIndex; + wAssocStatus = WLAN_MGMT_STATUS_SUCCESS; + wAssocAID = (u16)uNodeIndex; + + // if suppurt ERP + if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M) + pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true; + + if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate <= RATE_11M) { + // B only STA join + pDevice->bProtectMode = true; + pDevice->bNonERPPresent = true; + } + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == false) { + pDevice->bBarkerPreambleMd = true; + } + + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Rx ReAssociate AID= %d \n", wAssocAID); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n", + sFrame.pHdr->sA3.abyAddr2[0], + sFrame.pHdr->sA3.abyAddr2[1], + sFrame.pHdr->sA3.abyAddr2[2], + sFrame.pHdr->sA3.abyAddr2[3], + sFrame.pHdr->sA3.abyAddr2[4], + sFrame.pHdr->sA3.abyAddr2[5] + ) ; + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Max Support rate = %d \n", + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate); + + } + + // assoc response reply.. + pTxPacket = s_MgrMakeReAssocResponse + ( + pDevice, + pMgmt, + pMgmt->wCurrCapInfo, + wAssocStatus, + wAssocAID, + sFrame.pHdr->sA3.abyAddr2, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + + if (pTxPacket != NULL ){ + /* send the frame */ + if (pDevice->bEnableHostapd) { + return; + } + Status = csMgmt_xmit(pDevice, pTxPacket); + if (Status != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:ReAssoc response tx failed\n"); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:ReAssoc response tx sending..\n"); + } + } + return; +} + +/*+ + * + * Routine Description: + * Handle incoming association response frames. + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxAssocResponse(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket, + int bReAssocType) +{ + WLAN_FR_ASSOCRESP sFrame; + PWLAN_IE_SSID pItemSSID; + u8 *pbyIEs; + + if (pMgmt->eCurrState == WMAC_STATE_ASSOCPENDING || + pMgmt->eCurrState == WMAC_STATE_ASSOC) { + + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + // decode the frame + vMgrDecodeAssocResponse(&sFrame); + if ((sFrame.pwCapInfo == NULL) + || (sFrame.pwStatus == NULL) + || (sFrame.pwAid == NULL) + || (sFrame.pSuppRates == NULL)) { + DBG_PORT80(0xCC); + return; + } + + pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.Capabilities = *(sFrame.pwCapInfo); + pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.StatusCode = *(sFrame.pwStatus); + pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.AssociationId = *(sFrame.pwAid); + pMgmt->sAssocInfo.AssocInfo.AvailableResponseFixedIEs |= 0x07; + + pMgmt->sAssocInfo.AssocInfo.ResponseIELength = sFrame.len - 24 - 6; + pMgmt->sAssocInfo.AssocInfo.OffsetResponseIEs = pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs + pMgmt->sAssocInfo.AssocInfo.RequestIELength; + pbyIEs = pMgmt->sAssocInfo.abyIEs; + pbyIEs += pMgmt->sAssocInfo.AssocInfo.RequestIELength; + memcpy(pbyIEs, (sFrame.pBuf + 24 +6), pMgmt->sAssocInfo.AssocInfo.ResponseIELength); + + // save values and set current BSS state + if (cpu_to_le16((*(sFrame.pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){ + // set AID + pMgmt->wCurrAID = cpu_to_le16((*(sFrame.pwAid))); + if ( (pMgmt->wCurrAID >> 14) != (BIT0 | BIT1) ) + { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "AID from AP, has two msb clear.\n"); + } + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Association Successful, AID=%d.\n", pMgmt->wCurrAID & ~(BIT14|BIT15)); + pMgmt->eCurrState = WMAC_STATE_ASSOC; + BSSvUpdateAPNode((void *) pDevice, + sFrame.pwCapInfo, + sFrame.pSuppRates, + sFrame.pExtSuppRates); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Link with AP(SSID): %s\n", pItemSSID->abySSID); + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + + //if(pDevice->bWPASuppWextEnabled == true) + { + u8 buf[512]; + size_t len; + union iwreq_data wrqu; + int we_event; + + memset(buf, 0, 512); + + len = pMgmt->sAssocInfo.AssocInfo.RequestIELength; + if(len) { + memcpy(buf, pMgmt->sAssocInfo.abyIEs, len); + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.data.length = len; + we_event = IWEVASSOCREQIE; + PRINT_K("wireless_send_event--->IWEVASSOCREQIE\n"); + wireless_send_event(pDevice->dev, we_event, &wrqu, buf); + } + + memset(buf, 0, 512); + len = pMgmt->sAssocInfo.AssocInfo.ResponseIELength; + + if(len) { + memcpy(buf, pbyIEs, len); + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.data.length = len; + we_event = IWEVASSOCRESPIE; + PRINT_K("wireless_send_event--->IWEVASSOCRESPIE\n"); + wireless_send_event(pDevice->dev, we_event, &wrqu, buf); + } + + memset(&wrqu, 0, sizeof (wrqu)); + memcpy(wrqu.ap_addr.sa_data, &pMgmt->abyCurrBSSID[0], ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(associated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + + } + + } + else { + if (bReAssocType) { + pMgmt->eCurrState = WMAC_STATE_IDLE; + } + else { + // jump back to the auth state and indicate the error + pMgmt->eCurrState = WMAC_STATE_AUTH; + } + s_vMgrLogStatus(pMgmt,cpu_to_le16((*(sFrame.pwStatus)))); + } + + } + +//need clear flags related to Networkmanager + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = false; + pDevice->bWPASuppWextEnabled = false; + +if(pMgmt->eCurrState == WMAC_STATE_ASSOC) + timer_expire(pDevice->sTimerCommand, 0); + + return; +} + +/*+ + * + * Routine Description: + * Start the station authentication procedure. Namely, send an + * authentication frame to the AP. + * + * Return Value: + * None. + * +-*/ + +void vMgrAuthenBeginSta(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, PCMD_STATUS pStatus) +{ + WLAN_FR_AUTHEN sFrame; + struct vnt_tx_mgmt *pTxPacket = + (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_AUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_AUTHEN_FR_MAXLEN; + vMgrEncodeAuthen(&sFrame); + /* insert values */ + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + if (pMgmt->bShareKeyAlgorithm) + *(sFrame.pwAuthAlgorithm) = cpu_to_le16(WLAN_AUTH_ALG_SHAREDKEY); + else + *(sFrame.pwAuthAlgorithm) = cpu_to_le16(WLAN_AUTH_ALG_OPENSYSTEM); + + *(sFrame.pwAuthSequence) = cpu_to_le16(1); + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus == CMD_STATUS_PENDING){ + pMgmt->eCurrState = WMAC_STATE_AUTHPENDING; + *pStatus = CMD_STATUS_SUCCESS; + } + + return ; +} + +/*+ + * + * Routine Description: + * Start the station(AP) deauthentication procedure. Namely, send an + * deauthentication frame to the AP or Sta. + * + * Return Value: + * None. + * +-*/ + +void vMgrDeAuthenBeginSta(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u8 *abyDestAddress, u16 wReason, + PCMD_STATUS pStatus) +{ + WLAN_FR_DEAUTHEN sFrame; + struct vnt_tx_mgmt *pTxPacket = + (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_DEAUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_DEAUTHEN_FR_MAXLEN; + vMgrEncodeDeauthen(&sFrame); + /* insert values */ + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DEAUTHEN) + )); + + memcpy( sFrame.pHdr->sA3.abyAddr1, abyDestAddress, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + *(sFrame.pwReason) = cpu_to_le16(wReason); // deauthen. bcs left BSS + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus == CMD_STATUS_PENDING){ + *pStatus = CMD_STATUS_SUCCESS; + } + + return ; +} + +/*+ + * + * Routine Description: + * Handle incoming authentication frames. + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxAuthentication(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket) +{ + WLAN_FR_AUTHEN sFrame; + + // we better be an AP or a STA in AUTHPENDING otherwise ignore + if (!(pMgmt->eCurrMode == WMAC_MODE_ESS_AP || + pMgmt->eCurrState == WMAC_STATE_AUTHPENDING)) { + return; + } + + // decode the frame + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + vMgrDecodeAuthen(&sFrame); + switch (cpu_to_le16((*(sFrame.pwAuthSequence )))){ + case 1: + //AP funciton + s_vMgrRxAuthenSequence_1(pDevice,pMgmt, &sFrame); + break; + case 2: + s_vMgrRxAuthenSequence_2(pDevice, pMgmt, &sFrame); + break; + case 3: + //AP funciton + s_vMgrRxAuthenSequence_3(pDevice, pMgmt, &sFrame); + break; + case 4: + s_vMgrRxAuthenSequence_4(pDevice, pMgmt, &sFrame); + break; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Auth Sequence error, seq = %d\n", + cpu_to_le16((*(sFrame.pwAuthSequence)))); + break; + } + return; +} + +/*+ + * + * Routine Description: + * Handles incoming authen frames with sequence 1. Currently + * assumes we're an AP. So far, no one appears to use authentication + * in Ad-Hoc mode. + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxAuthenSequence_1(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + u32 uNodeIndex; + WLAN_FR_AUTHEN sFrame; + PSKeyItem pTransmitKey; + + /* Insert a Node entry */ + if (!BSSbIsSTAInNodeDB(pDevice, pFrame->pHdr->sA3.abyAddr2, + &uNodeIndex)) { + BSSvCreateOneNode(pDevice, &uNodeIndex); + memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, + pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN); + } + + if (pMgmt->bShareKeyAlgorithm) { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_KNOWN; + pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence = 1; + } + else { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_AUTH; + } + + // send auth reply + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_AUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_AUTHEN_FR_MAXLEN; + // format buffer structure + vMgrEncodeAuthen(&sFrame); + // insert values + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)| + WLAN_SET_FC_ISWEP(0) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm); + *(sFrame.pwAuthSequence) = cpu_to_le16(2); + + if (cpu_to_le16(*(pFrame->pwAuthAlgorithm)) == WLAN_AUTH_ALG_SHAREDKEY) { + if (pMgmt->bShareKeyAlgorithm) + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS); + else + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG); + } + else { + if (pMgmt->bShareKeyAlgorithm) + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG); + else + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS); + } + + if (pMgmt->bShareKeyAlgorithm && + (cpu_to_le16(*(sFrame.pwStatus)) == WLAN_MGMT_STATUS_SUCCESS)) { + + sFrame.pChallenge = (PWLAN_IE_CHALLENGE)(sFrame.pBuf + sFrame.len); + sFrame.len += WLAN_CHALLENGE_IE_LEN; + sFrame.pChallenge->byElementID = WLAN_EID_CHALLENGE; + sFrame.pChallenge->len = WLAN_CHALLENGE_LEN; + memset(pMgmt->abyChallenge, 0, WLAN_CHALLENGE_LEN); + // get group key + if(KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, GROUP_KEY, &pTransmitKey) == true) { + rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength+3); + rc4_encrypt(&pDevice->SBox, pMgmt->abyChallenge, pMgmt->abyChallenge, WLAN_CHALLENGE_LEN); + } + memcpy(sFrame.pChallenge->abyChallenge, pMgmt->abyChallenge , WLAN_CHALLENGE_LEN); + } + + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + // send the frame + if (pDevice->bEnableHostapd) { + return; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_1 tx.. \n"); + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_1 tx failed.\n"); + } + return; +} + +/*+ + * + * Routine Description: + * Handles incoming auth frames with sequence number 2. Currently + * assumes we're a station. + * + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxAuthenSequence_2(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame) +{ + WLAN_FR_AUTHEN sFrame; + struct vnt_tx_mgmt *pTxPacket = NULL; + + switch (cpu_to_le16((*(pFrame->pwAuthAlgorithm)))) + { + case WLAN_AUTH_ALG_OPENSYSTEM: + if ( cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){ + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Successful.\n"); + pMgmt->eCurrState = WMAC_STATE_AUTH; + timer_expire(pDevice->sTimerCommand, 0); + } + else { + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Failed.\n"); + s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus)))); + pMgmt->eCurrState = WMAC_STATE_IDLE; + } + if (pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT) { + /* spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, 0); + spin_lock_irq(&pDevice->lock); */ + } + break; + + case WLAN_AUTH_ALG_SHAREDKEY: + + if (cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS) { + pTxPacket = (struct vnt_tx_mgmt *) + pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_AUTHEN_FR_MAXLEN); + pTxPacket->p80211Header + = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_AUTHEN_FR_MAXLEN; + // format buffer structure + vMgrEncodeAuthen(&sFrame); + // insert values + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)| + WLAN_SET_FC_ISWEP(1) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm); + *(sFrame.pwAuthSequence) = cpu_to_le16(3); + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS); + sFrame.pChallenge = (PWLAN_IE_CHALLENGE)(sFrame.pBuf + sFrame.len); + sFrame.len += WLAN_CHALLENGE_IE_LEN; + sFrame.pChallenge->byElementID = WLAN_EID_CHALLENGE; + sFrame.pChallenge->len = WLAN_CHALLENGE_LEN; + memcpy( sFrame.pChallenge->abyChallenge, pFrame->pChallenge->abyChallenge, WLAN_CHALLENGE_LEN); + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + // send the frame + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Auth_reply sequence_2 tx failed.\n"); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Auth_reply sequence_2 tx ...\n"); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:rx Auth_reply sequence_2 status error ...\n"); + if ( pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT ) { + /* spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, 0); + spin_lock_irq(&pDevice->lock); */ + } + s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus)))); + } + break; + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt: rx auth.seq = 2 unknown AuthAlgorithm=%d\n", cpu_to_le16((*(pFrame->pwAuthAlgorithm)))); + break; + } + return; +} + +/*+ + * + * Routine Description: + * Handles incoming authen frames with sequence 3. Currently + * assumes we're an AP. This function assumes the frame has + * already been successfully decrypted. + * + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxAuthenSequence_3(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + u32 uStatusCode = 0 ; + u32 uNodeIndex = 0; + WLAN_FR_AUTHEN sFrame; + + if (!WLAN_GET_FC_ISWEP(pFrame->pHdr->sA3.wFrameCtl)) { + uStatusCode = WLAN_MGMT_STATUS_CHALLENGE_FAIL; + goto reply; + } + if (BSSbIsSTAInNodeDB(pDevice, pFrame->pHdr->sA3.abyAddr2, &uNodeIndex)) { + if (pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence != 1) { + uStatusCode = WLAN_MGMT_STATUS_RX_AUTH_NOSEQ; + goto reply; + } + if (memcmp(pMgmt->abyChallenge, pFrame->pChallenge->abyChallenge, WLAN_CHALLENGE_LEN) != 0) { + uStatusCode = WLAN_MGMT_STATUS_CHALLENGE_FAIL; + goto reply; + } + } + else { + uStatusCode = WLAN_MGMT_STATUS_UNSPEC_FAILURE; + goto reply; + } + + if (uNodeIndex) { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_AUTH; + pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence = 0; + } + uStatusCode = WLAN_MGMT_STATUS_SUCCESS; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Challenge text check ok..\n"); + +reply: + // send auth reply + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_AUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_AUTHEN_FR_MAXLEN; + // format buffer structure + vMgrEncodeAuthen(&sFrame); + /* insert values */ + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)| + WLAN_SET_FC_ISWEP(0) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm); + *(sFrame.pwAuthSequence) = cpu_to_le16(4); + *(sFrame.pwStatus) = cpu_to_le16(uStatusCode); + + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + // send the frame + if (pDevice->bEnableHostapd) { + return; + } + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_4 tx failed.\n"); + } + return; + +} + +/*+ + * + * Routine Description: + * Handles incoming authen frames with sequence 4 + * + * + * Return Value: + * None. + * +-*/ +static void s_vMgrRxAuthenSequence_4(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, PWLAN_FR_AUTHEN pFrame) +{ + + if ( cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){ + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Successful.\n"); + pMgmt->eCurrState = WMAC_STATE_AUTH; + timer_expire(pDevice->sTimerCommand, 0); + } + else{ + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Failed.\n"); + s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus))) ); + pMgmt->eCurrState = WMAC_STATE_IDLE; + } + + if ( pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT ) { + /* spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((void *) pDevice, 0); + spin_lock_irq(&pDevice->lock); */ + } +} + +/*+ + * + * Routine Description: + * Handles incoming disassociation frames + * + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxDisassociation(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket) +{ + WLAN_FR_DISASSOC sFrame; + u32 uNodeIndex = 0; + CMD_STATUS CmdStatus; + + if ( pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){ + // if is acting an AP.. + // a STA is leaving this BSS.. + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + if (BSSbIsSTAInNodeDB(pDevice, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) { + BSSvRemoveOneNode(pDevice, uNodeIndex); + } + else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx disassoc, sta not found\n"); + } + } + else if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ){ + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + vMgrDecodeDisassociation(&sFrame); + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP disassociated me, reason=%d.\n", cpu_to_le16(*(sFrame.pwReason))); + + pDevice->fWPA_Authened = false; + + //TODO: do something let upper layer know or + //try to send associate packet again because of inactivity timeout + if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { + pDevice->bLinkPass = false; + pMgmt->sNodeDBTable[0].bActive = false; + pDevice->byReAssocCount = 0; + pMgmt->eCurrState = WMAC_STATE_AUTH; // jump back to the auth state! + pDevice->eCommandState = WLAN_ASSOCIATE_WAIT; + vMgrReAssocBeginSta(pDevice, pMgmt, &CmdStatus); + if(CmdStatus == CMD_STATUS_PENDING) { + pDevice->byReAssocCount ++; + return; //mike add: you'll retry for many times, so it cann't be regarded as disconnected! + } + } + + // if(pDevice->bWPASuppWextEnabled == true) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + } + /* else, ignore it */ + + return; +} + +/*+ + * + * Routine Description: + * Handles incoming deauthentication frames + * + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxDeauthentication(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket) +{ + WLAN_FR_DEAUTHEN sFrame; + u32 uNodeIndex = 0; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){ + //Todo: + // if is acting an AP.. + // a STA is leaving this BSS.. + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + if (BSSbIsSTAInNodeDB(pDevice, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) { + BSSvRemoveOneNode(pDevice, uNodeIndex); + } + else { + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Rx deauth, sta not found\n"); + } + } + else { + if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ) { + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + vMgrDecodeDeauthen(&sFrame); + pDevice->fWPA_Authened = false; + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason)))); + // TODO: update BSS list for specific BSSID if pre-authentication case + if (!compare_ether_addr(sFrame.pHdr->sA3.abyAddr3, + pMgmt->abyCurrBSSID)) { + if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) { + pMgmt->sNodeDBTable[0].bActive = false; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = false; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW); + } + } + + // if(pDevice->bWPASuppWextEnabled == true) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + PRINT_K("wireless_send_event--->SIOCGIWAP(disauthen)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + + } + /* else, ignore it. TODO: IBSS authentication service + would be implemented here */ + }; + return; +} + +/*+ + * + * Routine Description: + * check if current channel is match ZoneType. + *for USA:1~11; + * Japan:1~13; + * Europe:1~13 + * Return Value: + * True:exceed; + * False:normal case +-*/ +static int ChannelExceedZoneType(struct vnt_private *pDevice, u8 byCurrChannel) +{ + int exceed = false; + + switch(pDevice->byZoneType) { + case 0x00: //USA:1~11 + if((byCurrChannel<1) ||(byCurrChannel>11)) + exceed = true; + break; + case 0x01: //Japan:1~13 + case 0x02: //Europe:1~13 + if((byCurrChannel<1) ||(byCurrChannel>13)) + exceed = true; + break; + default: //reserve for other zonetype + break; + } + + return exceed; +} + +/*+ + * + * Routine Description: + * Handles and analysis incoming beacon frames. + * + * + * Return Value: + * None. + * +-*/ + +static void s_vMgrRxBeacon(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket, + int bInScan) +{ + PKnownBSS pBSSList; + WLAN_FR_BEACON sFrame; + u64 qwTSFOffset; + int bIsBSSIDEqual = false; + int bIsSSIDEqual = false; + int bTSFLargeDiff = false; + int bTSFOffsetPostive = false; + int bUpdateTSF = false; + int bIsAPBeacon = false; + int bIsChannelEqual = false; + u32 uLocateByteIndex; + u8 byTIMBitOn = 0; + u16 wAIDNumber = 0; + u32 uNodeIndex; + u64 qwTimestamp, qwLocalTSF; + u64 qwCurrTSF; + u16 wStartIndex = 0; + u16 wAIDIndex = 0; + u8 byCurrChannel = pRxPacket->byRxChannel; + ERPObject sERP; + u32 uRateLen = WLAN_RATES_MAXLEN; + int bChannelHit = false; + u8 byOldPreambleType; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) + return; + + memset(&sFrame, 0, sizeof(WLAN_FR_BEACON)); + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + + // decode the beacon frame + vMgrDecodeBeacon(&sFrame); + + if ((sFrame.pwBeaconInterval == NULL) + || (sFrame.pwCapInfo == NULL) + || (sFrame.pSSID == NULL) + || (sFrame.pSuppRates == NULL)) { + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx beacon frame error\n"); + return; + } + + if( byCurrChannel > CB_MAX_CHANNEL_24G ) + { + if (sFrame.pDSParms != NULL) { + if (byCurrChannel == RFaby11aChannelIndex[sFrame.pDSParms->byCurrChannel-1]) + bChannelHit = true; + byCurrChannel = RFaby11aChannelIndex[sFrame.pDSParms->byCurrChannel-1]; + } else { + bChannelHit = true; + } + + } else { + if (sFrame.pDSParms != NULL) { + if (byCurrChannel == sFrame.pDSParms->byCurrChannel) + bChannelHit = true; + byCurrChannel = sFrame.pDSParms->byCurrChannel; + } else { + bChannelHit = true; + } + } + +if(ChannelExceedZoneType(pDevice,byCurrChannel)==true) + return; + + if (sFrame.pERP != NULL) { + sERP.byERP = sFrame.pERP->byContext; + sERP.bERPExist = true; + + } else { + sERP.bERPExist = false; + sERP.byERP = 0; + } + + pBSSList = BSSpAddrIsInBSSList((void *) pDevice, + sFrame.pHdr->sA3.abyAddr3, + sFrame.pSSID); + if (pBSSList == NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Beacon/insert: RxChannel = : %d\n", byCurrChannel); + BSSbInsertToBSSList((void *) pDevice, + sFrame.pHdr->sA3.abyAddr3, + *sFrame.pqwTimestamp, + *sFrame.pwBeaconInterval, + *sFrame.pwCapInfo, + byCurrChannel, + sFrame.pSSID, + sFrame.pSuppRates, + sFrame.pExtSuppRates, + &sERP, + sFrame.pRSN, + sFrame.pRSNWPA, + sFrame.pIE_Country, + sFrame.pIE_Quiet, + sFrame.len - WLAN_HDR_ADDR3_LEN, + sFrame.pHdr->sA4.abyAddr4, // payload of beacon + (void *) pRxPacket); + } + else { +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"update bcn: RxChannel = : %d\n", byCurrChannel); + BSSbUpdateToBSSList((void *) pDevice, + *sFrame.pqwTimestamp, + *sFrame.pwBeaconInterval, + *sFrame.pwCapInfo, + byCurrChannel, + bChannelHit, + sFrame.pSSID, + sFrame.pSuppRates, + sFrame.pExtSuppRates, + &sERP, + sFrame.pRSN, + sFrame.pRSNWPA, + sFrame.pIE_Country, + sFrame.pIE_Quiet, + pBSSList, + sFrame.len - WLAN_HDR_ADDR3_LEN, + sFrame.pHdr->sA4.abyAddr4, // payload of probresponse + (void *) pRxPacket); + + } + + if (bInScan) { + return; + } + + if(byCurrChannel == (u8)pMgmt->uCurrChannel) + bIsChannelEqual = true; + + if (bIsChannelEqual && (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { + + // if rx beacon without ERP field + if (sERP.bERPExist) { + if (WLAN_GET_ERP_USE_PROTECTION(sERP.byERP)){ + pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1); + pDevice->wUseProtectCntDown = USE_PROTECT_PERIOD; + } + } + else { + pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1); + pDevice->wUseProtectCntDown = USE_PROTECT_PERIOD; + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + if(!WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo)) + pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1); + if(!sERP.bERPExist) + pDevice->byERPFlag |= WLAN_SET_ERP_NONERP_PRESENT(1); + } + } + + // check if BSSID the same + if (memcmp(sFrame.pHdr->sA3.abyAddr3, + pMgmt->abyCurrBSSID, + WLAN_BSSID_LEN) == 0) { + + bIsBSSIDEqual = true; + pDevice->uCurrRSSI = pRxPacket->uRSSI; + pDevice->byCurrSQ = pRxPacket->bySQ; + if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) { + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BCN:Wake Count= [%d]\n", pMgmt->wCountToWakeUp); + } + } + // check if SSID the same + if (sFrame.pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) { + if (memcmp(sFrame.pSSID->abySSID, + ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, + sFrame.pSSID->len + ) == 0) { + bIsSSIDEqual = true; + } + } + + if ((WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo)== true) && + (bIsBSSIDEqual == true) && + (bIsSSIDEqual == true) && + (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + // add state check to prevent reconnect fail since we'll receive Beacon + + bIsAPBeacon = true; + if (pBSSList != NULL) { + + // Sync ERP field + if ((pBSSList->sERP.bERPExist == true) && (pDevice->byBBType == BB_TYPE_11G)) { + if ((pBSSList->sERP.byERP & WLAN_EID_ERP_USE_PROTECTION) != pDevice->bProtectMode) {//0000 0010 + pDevice->bProtectMode = (pBSSList->sERP.byERP & WLAN_EID_ERP_USE_PROTECTION); + if (pDevice->bProtectMode) { + MACvEnableProtectMD(pDevice); + } else { + MACvDisableProtectMD(pDevice); + } + vUpdateIFS(pDevice); + } + if ((pBSSList->sERP.byERP & WLAN_EID_ERP_NONERP_PRESENT) != pDevice->bNonERPPresent) {//0000 0001 + pDevice->bNonERPPresent = (pBSSList->sERP.byERP & WLAN_EID_ERP_USE_PROTECTION); + } + if ((pBSSList->sERP.byERP & WLAN_EID_ERP_BARKER_MODE) != pDevice->bBarkerPreambleMd) {//0000 0100 + pDevice->bBarkerPreambleMd = (pBSSList->sERP.byERP & WLAN_EID_ERP_BARKER_MODE); + //BarkerPreambleMd has higher priority than shortPreamble bit in Cap + if (pDevice->bBarkerPreambleMd) { + MACvEnableBarkerPreambleMd(pDevice); + } else { + MACvDisableBarkerPreambleMd(pDevice); + } + } + } + // Sync Short Slot Time + if (WLAN_GET_CAP_INFO_SHORTSLOTTIME(pBSSList->wCapInfo) != pDevice->bShortSlotTime) { + bool bShortSlotTime; + + bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(pBSSList->wCapInfo); + //DBG_PRN_WLAN05(("Set Short Slot Time: %d\n", pDevice->bShortSlotTime)); + //Kyle check if it is OK to set G. + if (pDevice->byBBType == BB_TYPE_11A) { + bShortSlotTime = true; + } + else if (pDevice->byBBType == BB_TYPE_11B) { + bShortSlotTime = false; + } + if (bShortSlotTime != pDevice->bShortSlotTime) { + pDevice->bShortSlotTime = bShortSlotTime; + BBvSetShortSlotTime(pDevice); + vUpdateIFS(pDevice); + } + } + + // + // Preamble may change dynamically + // + byOldPreambleType = pDevice->byPreambleType; + if (WLAN_GET_CAP_INFO_SHORTPREAMBLE(pBSSList->wCapInfo)) { + pDevice->byPreambleType = pDevice->byShortPreamble; + } + else { + pDevice->byPreambleType = 0; + } + if (pDevice->byPreambleType != byOldPreambleType) + CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType); + // + // Basic Rate Set may change dynamically + // + if (pBSSList->eNetworkTypeInUse == PHY_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pBSSList->abySuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + uRateLen); + pMgmt->abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pBSSList->abyExtSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + uRateLen); + RATEvParseMaxRate((void *)pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + true, + &(pMgmt->sNodeDBTable[0].wMaxBasicRate), + &(pMgmt->sNodeDBTable[0].wMaxSuppRate), + &(pMgmt->sNodeDBTable[0].wSuppRate), + &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate) + ); + + } + } + +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Beacon 2 \n"); + // check if CF field exisit + if (WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo)) { + if (sFrame.pCFParms->wCFPDurRemaining > 0) { + // TODO: deal with CFP period to set NAV + } + } + + qwTimestamp = cpu_to_le64(*sFrame.pqwTimestamp); + qwLocalTSF = pRxPacket->qwLocalTSF; + + // check if beacon TSF larger or small than our local TSF + if (qwTimestamp >= qwLocalTSF) + bTSFOffsetPostive = true; + else + bTSFOffsetPostive = false; + + if (bTSFOffsetPostive) { + qwTSFOffset = CARDqGetTSFOffset(pRxPacket->byRxRate, (qwTimestamp), (qwLocalTSF)); + } + else { + qwTSFOffset = CARDqGetTSFOffset(pRxPacket->byRxRate, (qwLocalTSF), (qwTimestamp)); + } + + if (qwTSFOffset > TRIVIAL_SYNC_DIFFERENCE) + bTSFLargeDiff = true; + + // if infra mode + if (bIsAPBeacon == true) { + + // Infra mode: Local TSF always follow AP's TSF if Difference huge. + if (bTSFLargeDiff) + bUpdateTSF = true; + + if ((pDevice->bEnablePSMode == true) && (sFrame.pTIM)) { + + /* deal with DTIM, analysis TIM */ + pMgmt->bMulticastTIM = WLAN_MGMT_IS_MULTICAST_TIM(sFrame.pTIM->byBitMapCtl) ? true : false ; + pMgmt->byDTIMCount = sFrame.pTIM->byDTIMCount; + pMgmt->byDTIMPeriod = sFrame.pTIM->byDTIMPeriod; + wAIDNumber = pMgmt->wCurrAID & ~(BIT14|BIT15); + + // check if AID in TIM field bit on + // wStartIndex = N1 + wStartIndex = WLAN_MGMT_GET_TIM_OFFSET(sFrame.pTIM->byBitMapCtl) << 1; + // AIDIndex = N2 + wAIDIndex = (wAIDNumber >> 3); + if ((wAIDNumber > 0) && (wAIDIndex >= wStartIndex)) { + uLocateByteIndex = wAIDIndex - wStartIndex; + // len = byDTIMCount + byDTIMPeriod + byDTIMPeriod + byVirtBitMap[0~250] + if (sFrame.pTIM->len >= (uLocateByteIndex + 4)) { + byTIMBitOn = (0x01) << ((wAIDNumber) % 8); + pMgmt->bInTIM = sFrame.pTIM->byVirtBitMap[uLocateByteIndex] & byTIMBitOn ? true : false; + } + else { + pMgmt->bInTIM = false; + }; + } + else { + pMgmt->bInTIM = false; + }; + + if (pMgmt->bInTIM || + (pMgmt->bMulticastTIM && (pMgmt->byDTIMCount == 0))) { + pMgmt->bInTIMWake = true; + /* send out ps-poll packet */ + if (pMgmt->bInTIM) + PSvSendPSPOLL(pDevice); + + } + else { + pMgmt->bInTIMWake = false; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Not In TIM..\n"); + if (pDevice->bPWBitOn == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Send Null Packet\n"); + if (PSbSendNullPacket(pDevice)) + pDevice->bPWBitOn = true; + } + if(PSbConsiderPowerDown(pDevice, false, false)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Power down now...\n"); + } + } + + } + + } + // if adhoc mode + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && !bIsAPBeacon && bIsChannelEqual) { + if (bIsBSSIDEqual) { + // Use sNodeDBTable[0].uInActiveCount as IBSS beacons received count. + if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + + // adhoc mode:TSF updated only when beacon larger then local TSF + if (bTSFLargeDiff && bTSFOffsetPostive && + (pMgmt->eCurrState == WMAC_STATE_JOINTED)) + bUpdateTSF = true; + + // During dpc, already in spinlocked. + if (BSSbIsSTAInNodeDB(pDevice, sFrame.pHdr->sA3.abyAddr2, &uNodeIndex)) { + + // Update the STA, (Technically the Beacons of all the IBSS nodes + // should be identical, but that's not happening in practice. + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + WLAN_RATES_MAXLEN_11B); + RATEvParseMaxRate((void *)pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + NULL, + true, + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate) + ); + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].uInActiveCount = 0; + } + else { + /* Todo, initial Node content */ + BSSvCreateOneNode(pDevice, &uNodeIndex); + + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + WLAN_RATES_MAXLEN_11B); + RATEvParseMaxRate((void *)pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + NULL, + true, + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate) + ); + + memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, sFrame.pHdr->sA3.abyAddr2, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; +/* + pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo); + if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M) + pMgmt->sNodeDBTable[uNodeIndex].bERPExist = true; +*/ + } + + // if other stations jointed, indicate connect to upper layer.. + if (pMgmt->eCurrState == WMAC_STATE_STARTED) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Current IBSS State: [Started]........to: [Jointed] \n"); + pMgmt->eCurrState = WMAC_STATE_JOINTED; + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + pMgmt->sNodeDBTable[0].bActive = true; + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + + } + } + else if (bIsSSIDEqual) { + + // See other adhoc sta with the same SSID but BSSID is different. + // adpot this vars only when TSF larger then us. + if (bTSFLargeDiff && bTSFOffsetPostive) { + // we don't support ATIM under adhoc mode + // if ( sFrame.pIBSSParms->wATIMWindow == 0) { + // adpot this vars + // TODO: check sFrame cap if privacy on, and support rate syn + memcpy(pMgmt->abyCurrBSSID, sFrame.pHdr->sA3.abyAddr3, WLAN_BSSID_LEN); + memcpy(pDevice->abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + pMgmt->wCurrATIMWindow = cpu_to_le16(sFrame.pIBSSParms->wATIMWindow); + pMgmt->wCurrBeaconPeriod = cpu_to_le16(*sFrame.pwBeaconInterval); + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + WLAN_RATES_MAXLEN_11B); + // set HW beacon interval and re-synchronizing.... + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rejoining to Other Adhoc group with same SSID........\n"); + + MACvWriteBeaconInterval(pDevice, pMgmt->wCurrBeaconPeriod); + CARDvAdjustTSF(pDevice, pRxPacket->byRxRate, qwTimestamp, pRxPacket->qwLocalTSF); + CARDvUpdateNextTBTT(pDevice, qwTimestamp, pMgmt->wCurrBeaconPeriod); + + // Turn off bssid filter to avoid filter others adhoc station which bssid is different. + MACvWriteBSSIDAddress(pDevice, pMgmt->abyCurrBSSID); + + byOldPreambleType = pDevice->byPreambleType; + if (WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo)) { + pDevice->byPreambleType = pDevice->byShortPreamble; + } + else { + pDevice->byPreambleType = 0; + } + if (pDevice->byPreambleType != byOldPreambleType) + CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType); + + // MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID); + // set highest basic rate + // s_vSetHighestBasicRate(pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates); + // Prepare beacon frame + bMgrPrepareBeaconToSend((void *) pDevice, pMgmt); + // } + } + } + } + // endian issue ??? + // Update TSF + if (bUpdateTSF) { + CARDbGetCurrentTSF(pDevice, &qwCurrTSF); + CARDvAdjustTSF(pDevice, pRxPacket->byRxRate, qwTimestamp , pRxPacket->qwLocalTSF); + CARDbGetCurrentTSF(pDevice, &qwCurrTSF); + CARDvUpdateNextTBTT(pDevice, qwTimestamp, pMgmt->wCurrBeaconPeriod); + } + + return; +} + +/*+ + * + * Routine Description: + * Instructs the hw to create a bss using the supplied + * attributes. Note that this implementation only supports Ad-Hoc + * BSS creation. + * + * + * Return Value: + * CMD_STATUS + * +-*/ + +void vMgrCreateOwnIBSS(struct vnt_private *pDevice, PCMD_STATUS pStatus) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u16 wMaxBasicRate; + u16 wMaxSuppRate; + u8 byTopCCKBasicRate; + u8 byTopOFDMBasicRate; + u64 qwCurrTSF = 0; + int ii; + u8 abyRATE[] = {0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, 0x0C, + 0x12, 0x18, 0x60}; + u8 abyCCK_RATE[] = {0x82, 0x84, 0x8B, 0x96}; + u8 abyOFDM_RATE[] = {0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + u16 wSuppRate; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create Basic Service Set .......\n"); + + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) && + (pDevice->eEncryptionStatus != Ndis802_11Encryption2Enabled) && + (pDevice->eEncryptionStatus != Ndis802_11Encryption3Enabled)) { + // encryption mode error + *pStatus = CMD_STATUS_FAILURE; + return; + } + } + + pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES; + pMgmt->abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES; + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + pMgmt->eCurrentPHYMode = pMgmt->byAPBBType; + } else { + if (pDevice->byBBType == BB_TYPE_11G) + pMgmt->eCurrentPHYMode = PHY_TYPE_11G; + if (pDevice->byBBType == BB_TYPE_11B) + pMgmt->eCurrentPHYMode = PHY_TYPE_11B; + if (pDevice->byBBType == BB_TYPE_11A) + pMgmt->eCurrentPHYMode = PHY_TYPE_11A; + } + + if (pMgmt->eCurrentPHYMode != PHY_TYPE_11A) { + pMgmt->abyCurrSuppRates[1] = WLAN_RATES_MAXLEN_11B; + pMgmt->abyCurrExtSuppRates[1] = 0; + for (ii = 0; ii < 4; ii++) + pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii]; + } else { + pMgmt->abyCurrSuppRates[1] = 8; + pMgmt->abyCurrExtSuppRates[1] = 0; + for (ii = 0; ii < 8; ii++) + pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii]; + } + + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { + pMgmt->abyCurrSuppRates[1] = 8; + pMgmt->abyCurrExtSuppRates[1] = 4; + for (ii = 0; ii < 4; ii++) + pMgmt->abyCurrSuppRates[2+ii] = abyCCK_RATE[ii]; + for (ii = 4; ii < 8; ii++) + pMgmt->abyCurrSuppRates[2+ii] = abyOFDM_RATE[ii-4]; + for (ii = 0; ii < 4; ii++) + pMgmt->abyCurrExtSuppRates[2+ii] = abyOFDM_RATE[ii+4]; + } + + // Disable Protect Mode + pDevice->bProtectMode = 0; + MACvDisableProtectMD(pDevice); + + pDevice->bBarkerPreambleMd = 0; + MACvDisableBarkerPreambleMd(pDevice); + + // Kyle Test 2003.11.04 + + // set HW beacon interval + if (pMgmt->wIBSSBeaconPeriod == 0) + pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI; + MACvWriteBeaconInterval(pDevice, pMgmt->wIBSSBeaconPeriod); + + CARDbGetCurrentTSF(pDevice, &qwCurrTSF); + // clear TSF counter + CARDbClearCurrentTSF(pDevice); + + // enable TSF counter + MACvRegBitsOn(pDevice,MAC_REG_TFTCTL,TFTCTL_TSFCNTREN); + // set Next TBTT + CARDvSetFirstNextTBTT(pDevice, pMgmt->wIBSSBeaconPeriod); + + pMgmt->uIBSSChannel = pDevice->uChannel; + + if (pMgmt->uIBSSChannel == 0) + pMgmt->uIBSSChannel = DEFAULT_IBSS_CHANNEL; + + // set channel and clear NAV + CARDbSetMediaChannel(pDevice, pMgmt->uIBSSChannel); + pMgmt->uCurrChannel = pMgmt->uIBSSChannel; + + pDevice->byPreambleType = pDevice->byShortPreamble; + + // set basic rate + + RATEvParseMaxRate((void *)pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, true, + &wMaxBasicRate, &wMaxSuppRate, &wSuppRate, + &byTopCCKBasicRate, &byTopOFDMBasicRate); + + if (pDevice->byBBType == BB_TYPE_11A) { + pDevice->bShortSlotTime = true; + } else { + pDevice->bShortSlotTime = false; + } + BBvSetShortSlotTime(pDevice); + // vUpdateIFS() use pDevice->bShortSlotTime as parameter so it must be called + // after setting ShortSlotTime. + // CARDvSetBSSMode call vUpdateIFS() + CARDvSetBSSMode(pDevice); + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + MACvRegBitsOn(pDevice, MAC_REG_HOSTCR, HOSTCR_AP); + pMgmt->eCurrMode = WMAC_MODE_ESS_AP; + } + + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { + MACvRegBitsOn(pDevice, MAC_REG_HOSTCR, HOSTCR_ADHOC); + pMgmt->eCurrMode = WMAC_MODE_IBSS_STA; + } + + // Adopt pre-configured IBSS vars to current vars + pMgmt->eCurrState = WMAC_STATE_STARTED; + pMgmt->wCurrBeaconPeriod = pMgmt->wIBSSBeaconPeriod; + pMgmt->uCurrChannel = pMgmt->uIBSSChannel; + pMgmt->wCurrATIMWindow = pMgmt->wIBSSATIMWindow; + pDevice->uCurrRSSI = 0; + pDevice->byCurrSQ = 0; + + memcpy(pMgmt->abyDesireSSID,pMgmt->abyAdHocSSID, + ((PWLAN_IE_SSID)pMgmt->abyAdHocSSID)->len + WLAN_IEHDR_LEN); + + memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memcpy(pMgmt->abyCurrSSID, + pMgmt->abyDesireSSID, + ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN + ); + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + // AP mode BSSID = MAC addr + memcpy(pMgmt->abyCurrBSSID, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:" + "%pM\n", pMgmt->abyCurrBSSID); + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + + // BSSID selected must be randomized as spec 11.1.3 + pMgmt->abyCurrBSSID[5] = (u8)(qwCurrTSF & 0x000000ff); + pMgmt->abyCurrBSSID[4] = (u8)((qwCurrTSF & 0x0000ff00) >> 8); + pMgmt->abyCurrBSSID[3] = (u8)((qwCurrTSF & 0x00ff0000) >> 16); + pMgmt->abyCurrBSSID[2] = (u8)((qwCurrTSF & 0x00000ff0) >> 4); + pMgmt->abyCurrBSSID[1] = (u8)((qwCurrTSF & 0x000ff000) >> 12); + pMgmt->abyCurrBSSID[0] = (u8)((qwCurrTSF & 0x0ff00000) >> 20); + pMgmt->abyCurrBSSID[5] ^= pMgmt->abyMACAddr[0]; + pMgmt->abyCurrBSSID[4] ^= pMgmt->abyMACAddr[1]; + pMgmt->abyCurrBSSID[3] ^= pMgmt->abyMACAddr[2]; + pMgmt->abyCurrBSSID[2] ^= pMgmt->abyMACAddr[3]; + pMgmt->abyCurrBSSID[1] ^= pMgmt->abyMACAddr[4]; + pMgmt->abyCurrBSSID[0] ^= pMgmt->abyMACAddr[5]; + pMgmt->abyCurrBSSID[0] &= ~IEEE_ADDR_GROUP; + pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL; + + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:" + "%pM\n", pMgmt->abyCurrBSSID); + } + + // set BSSID filter + MACvWriteBSSIDAddress(pDevice, pMgmt->abyCurrBSSID); + memcpy(pDevice->abyBSSID, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + + MACvRegBitsOn(pDevice, MAC_REG_RCR, RCR_BSSID); + pDevice->byRxMode |= RCR_BSSID; + pMgmt->bCurrBSSIDFilterOn = true; + + // Set Capability Info + pMgmt->wCurrCapInfo = 0; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1); + pMgmt->byDTIMPeriod = DEFAULT_DTIM_PERIOD; + pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1; + pDevice->eOPMode = OP_MODE_AP; + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_IBSS(1); + pDevice->eOPMode = OP_MODE_ADHOC; + } + + if (pDevice->bEncryptionEnable) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1); + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + pMgmt->byCSSPK = KEY_CTL_CCMP; + pMgmt->byCSSGK = KEY_CTL_CCMP; + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + pMgmt->byCSSPK = KEY_CTL_TKIP; + pMgmt->byCSSGK = KEY_CTL_TKIP; + } else { + pMgmt->byCSSPK = KEY_CTL_NONE; + pMgmt->byCSSGK = KEY_CTL_WEP; + } + } else { + pMgmt->byCSSPK = KEY_CTL_WEP; + pMgmt->byCSSGK = KEY_CTL_WEP; + } + } + + pMgmt->byERPContext = 0; + + if (pDevice->byPreambleType == 1) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + } else { + pMgmt->wCurrCapInfo &= (~WLAN_SET_CAP_INFO_SHORTPREAMBLE(1)); + } + + pMgmt->eCurrState = WMAC_STATE_STARTED; + // Prepare beacon to send + if (bMgrPrepareBeaconToSend((void *) pDevice, pMgmt)) + *pStatus = CMD_STATUS_SUCCESS; + + return; +} + +/*+ + * + * Routine Description: + * Instructs wmac to join a bss using the supplied attributes. + * The arguments may the BSSID or SSID and the rest of the + * attributes are obtained from the scan result of known bss list. + * + * + * Return Value: + * None. + * +-*/ + +void vMgrJoinBSSBegin(struct vnt_private *pDevice, PCMD_STATUS pStatus) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + PKnownBSS pCurr = NULL; + int ii, uu; + PWLAN_IE_SUPP_RATES pItemRates = NULL; + PWLAN_IE_SUPP_RATES pItemExtRates = NULL; + PWLAN_IE_SSID pItemSSID; + u32 uRateLen = WLAN_RATES_MAXLEN; + u16 wMaxBasicRate = RATE_1M; + u16 wMaxSuppRate = RATE_1M; + u16 wSuppRate; + u8 byTopCCKBasicRate = RATE_1M; + u8 byTopOFDMBasicRate = RATE_1M; + u8 bShortSlotTime = false; + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + if (pMgmt->sBSSList[ii].bActive == true) + break; + } + + if (ii == MAX_BSS_NUM) { + *pStatus = CMD_STATUS_RESOURCES; + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "BSS finding:BSS list is empty.\n"); + return; + } + + // memset(pMgmt->abyDesireBSSID, 0, WLAN_BSSID_LEN); + // Search known BSS list for prefer BSSID or SSID + + pCurr = BSSpSearchBSSList(pDevice, + pMgmt->abyDesireBSSID, + pMgmt->abyDesireSSID, + pDevice->eConfigPHYMode + ); + + if (pCurr == NULL){ + *pStatus = CMD_STATUS_RESOURCES; + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Scanning [%s] not found, disconnected !\n", pItemSSID->abySSID); + return; + } + + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP(BSS) finding:Found a AP(BSS)..\n"); + + if (WLAN_GET_CAP_INFO_ESS(cpu_to_le16(pCurr->wCapInfo))){ + + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) { + /* + if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No match RSN info. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No match RSN info. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } + } +*/ + } + + //if(pDevice->bWPASuppWextEnabled == true) + Encyption_Rebuild(pDevice, pCurr); + + // Infrastructure BSS + s_vMgrSynchBSS(pDevice, + WMAC_MODE_ESS_STA, + pCurr, + pStatus + ); + + if (*pStatus == CMD_STATUS_SUCCESS){ + + // Adopt this BSS state vars in Mgmt Object + pMgmt->uCurrChannel = pCurr->uChannel; + + memset(pMgmt->abyCurrSuppRates, 0 , WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + memset(pMgmt->abyCurrExtSuppRates, 0 , WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + + if (pCurr->eNetworkTypeInUse == PHY_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + + pItemRates = (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates; + pItemExtRates = (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates; + + // Parse Support Rate IE + pItemRates->byElementID = WLAN_EID_SUPP_RATES; + pItemRates->len = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates, + pItemRates, + uRateLen); + + // Parse Extension Support Rate IE + pItemExtRates->byElementID = WLAN_EID_EXTSUPP_RATES; + pItemExtRates->len = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abyExtSuppRates, + pItemExtRates, + uRateLen); + // Stuffing Rate IE + if ((pItemExtRates->len > 0) && (pItemRates->len < 8)) { + for (ii = 0; ii < (unsigned int) (8 - pItemRates->len); ) { + pItemRates->abyRates[pItemRates->len + ii] = + pItemExtRates->abyRates[ii]; + ii++; + if (pItemExtRates->len <= ii) + break; + } + pItemRates->len += (u8)ii; + if (pItemExtRates->len - ii > 0) { + pItemExtRates->len -= (u8)ii; + for (uu = 0; uu < pItemExtRates->len; uu ++) { + pItemExtRates->abyRates[uu] = pItemExtRates->abyRates[uu + ii]; + } + } else { + pItemExtRates->len = 0; + } + } + + RATEvParseMaxRate((void *)pDevice, pItemRates, pItemExtRates, true, + &wMaxBasicRate, &wMaxSuppRate, &wSuppRate, + &byTopCCKBasicRate, &byTopOFDMBasicRate); + vUpdateIFS(pDevice); + // TODO: deal with if wCapInfo the privacy is on, but station WEP is off + // TODO: deal with if wCapInfo the PS-Pollable is on. + pMgmt->wCurrBeaconPeriod = pCurr->wBeaconInterval; + memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); + memcpy(pMgmt->abyCurrSSID, pCurr->abySSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + + pMgmt->eCurrMode = WMAC_MODE_ESS_STA; + + pMgmt->eCurrState = WMAC_STATE_JOINTED; + // Adopt BSS state in Adapter Device Object + pDevice->eOPMode = OP_MODE_INFRASTRUCTURE; + memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); + + // Add current BSS to Candidate list + // This should only work for WPA2 BSS, and WPA2 BSS check must be done before. + if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { + bool bResult = bAdd_PMKID_Candidate((void *) pDevice, + pMgmt->abyCurrBSSID, + &pCurr->sRSNCapObj); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate: 1(%d)\n", bResult); + if (bResult == false) { + vFlush_PMKID_Candidate((void *) pDevice); + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO "vFlush_PMKID_Candidate: 4\n"); + bAdd_PMKID_Candidate((void *) pDevice, + pMgmt->abyCurrBSSID, + &pCurr->sRSNCapObj); + } + } + + // Preamble type auto-switch: if AP can receive short-preamble cap, + // we can turn on too. + if (WLAN_GET_CAP_INFO_SHORTPREAMBLE(pCurr->wCapInfo)) { + pDevice->byPreambleType = pDevice->byShortPreamble; + } + else { + pDevice->byPreambleType = 0; + } + // Change PreambleType must set RSPINF again + CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join ESS\n"); + + if (pCurr->eNetworkTypeInUse == PHY_TYPE_11G) { + + if ((pCurr->sERP.byERP & WLAN_EID_ERP_USE_PROTECTION) != pDevice->bProtectMode) {//0000 0010 + pDevice->bProtectMode = (pCurr->sERP.byERP & WLAN_EID_ERP_USE_PROTECTION); + if (pDevice->bProtectMode) { + MACvEnableProtectMD(pDevice); + } else { + MACvDisableProtectMD(pDevice); + } + vUpdateIFS(pDevice); + } + if ((pCurr->sERP.byERP & WLAN_EID_ERP_NONERP_PRESENT) != pDevice->bNonERPPresent) {//0000 0001 + pDevice->bNonERPPresent = (pCurr->sERP.byERP & WLAN_EID_ERP_USE_PROTECTION); + } + if ((pCurr->sERP.byERP & WLAN_EID_ERP_BARKER_MODE) != pDevice->bBarkerPreambleMd) {//0000 0100 + pDevice->bBarkerPreambleMd = (pCurr->sERP.byERP & WLAN_EID_ERP_BARKER_MODE); + //BarkerPreambleMd has higher priority than shortPreamble bit in Cap + if (pDevice->bBarkerPreambleMd) { + MACvEnableBarkerPreambleMd(pDevice); + } else { + MACvDisableBarkerPreambleMd(pDevice); + } + } + } + //DBG_PRN_WLAN05(("wCapInfo: %X\n", pCurr->wCapInfo)); + if (WLAN_GET_CAP_INFO_SHORTSLOTTIME(pCurr->wCapInfo) != pDevice->bShortSlotTime) { + if (pDevice->byBBType == BB_TYPE_11A) { + bShortSlotTime = true; + } + else if (pDevice->byBBType == BB_TYPE_11B) { + bShortSlotTime = false; + } + else { + bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(pCurr->wCapInfo); + } + //DBG_PRN_WLAN05(("Set Short Slot Time: %d\n", pDevice->bShortSlotTime)); + if (bShortSlotTime != pDevice->bShortSlotTime) { + pDevice->bShortSlotTime = bShortSlotTime; + BBvSetShortSlotTime(pDevice); + vUpdateIFS(pDevice); + } + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"End of Join AP -- A/B/G Action\n"); + } + else { + pMgmt->eCurrState = WMAC_STATE_IDLE; + }; + + } + else { + // ad-hoc mode BSS + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + + if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { +/* + if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == false) { + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } +*/ + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { +/* + if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == false) { + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } +*/ + } else { + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } + } + + s_vMgrSynchBSS(pDevice, + WMAC_MODE_IBSS_STA, + pCurr, + pStatus + ); + + if (*pStatus == CMD_STATUS_SUCCESS){ + // Adopt this BSS state vars in Mgmt Object + // TODO: check if CapInfo privacy on, but we don't.. + pMgmt->uCurrChannel = pCurr->uChannel; + + // Parse Support Rate IE + pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES; + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + WLAN_RATES_MAXLEN_11B); + // set basic rate + RATEvParseMaxRate((void *)pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + NULL, true, &wMaxBasicRate, &wMaxSuppRate, &wSuppRate, + &byTopCCKBasicRate, &byTopOFDMBasicRate); + vUpdateIFS(pDevice); + pMgmt->wCurrCapInfo = pCurr->wCapInfo; + pMgmt->wCurrBeaconPeriod = pCurr->wBeaconInterval; + memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN); + memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); + memcpy(pMgmt->abyCurrSSID, pCurr->abySSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN); +// pMgmt->wCurrATIMWindow = pCurr->wATIMWindow; + pMgmt->eCurrMode = WMAC_MODE_IBSS_STA; + pMgmt->eCurrState = WMAC_STATE_STARTED; + // Adopt BSS state in Adapter Device Object + pDevice->eOPMode = OP_MODE_ADHOC; + pDevice->bLinkPass = true; + ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER); + memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%pM\n", + pMgmt->abyCurrBSSID); + // Preamble type auto-switch: if AP can receive short-preamble cap, + // and if registry setting is short preamble we can turn on too. + + if (WLAN_GET_CAP_INFO_SHORTPREAMBLE(pCurr->wCapInfo)) { + pDevice->byPreambleType = pDevice->byShortPreamble; + } + else { + pDevice->byPreambleType = 0; + } + // Change PreambleType must set RSPINF again + CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType); + + // Prepare beacon + bMgrPrepareBeaconToSend((void *) pDevice, pMgmt); + } + else { + pMgmt->eCurrState = WMAC_STATE_IDLE; + }; + }; + return; +} + +/*+ + * + * Routine Description: + * Set HW to synchronize a specific BSS from known BSS list. + * + * + * Return Value: + * PCM_STATUS + * +-*/ +static void s_vMgrSynchBSS(struct vnt_private *pDevice, u32 uBSSMode, + PKnownBSS pCurr, PCMD_STATUS pStatus) +{ + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u8 abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, + 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C}; + /* 1M, 2M, 5M, 11M, 18M, 24M, 36M, 54M*/ + u8 abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, + 4, 0x0C, 0x12, 0x18, 0x60}; + /* 6M, 9M, 12M, 48M*/ + u8 abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, + 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + u8 abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, + 4, 0x02, 0x04, 0x0B, 0x16}; + + *pStatus = CMD_STATUS_FAILURE; + + if (s_bCipherMatch(pCurr, + pDevice->eEncryptionStatus, + &(pMgmt->byCSSPK), + &(pMgmt->byCSSGK)) == false) { + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "s_bCipherMatch Fail .......\n"); + return; + } + + pMgmt->pCurrBSS = pCurr; + + // if previous mode is IBSS. + if(pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + MACvRegBitsOff(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); + } + + // Init the BSS informations + pDevice->bCCK = true; + pDevice->bProtectMode = false; + MACvDisableProtectMD(pDevice); + pDevice->bBarkerPreambleMd = false; + MACvDisableBarkerPreambleMd(pDevice); + pDevice->bNonERPPresent = false; + pDevice->byPreambleType = 0; + pDevice->wBasicRate = 0; + // Set Basic Rate + CARDbAddBasicRate((void *)pDevice, RATE_1M); + + // calculate TSF offset + // TSF Offset = Received Timestamp TSF - Marked Local's TSF + CARDvAdjustTSF(pDevice, pCurr->byRxRate, pCurr->qwBSSTimestamp, pCurr->qwLocalTSF); + + // set HW beacon interval + MACvWriteBeaconInterval(pDevice, pCurr->wBeaconInterval); + + // set Next TBTT + // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval + CARDvSetFirstNextTBTT(pDevice, pCurr->wBeaconInterval); + + // set BSSID + MACvWriteBSSIDAddress(pDevice, pCurr->abyBSSID); + + memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, 6); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = " + "%pM\n", pMgmt->abyCurrBSSID); + + if (pCurr->eNetworkTypeInUse == PHY_TYPE_11A) { + if ((pDevice->eConfigPHYMode == PHY_TYPE_11A) || + (pDevice->eConfigPHYMode == PHY_TYPE_AUTO)) { + pDevice->byBBType = BB_TYPE_11A; + pMgmt->eCurrentPHYMode = PHY_TYPE_11A; + pDevice->bShortSlotTime = true; + BBvSetShortSlotTime(pDevice); + CARDvSetBSSMode(pDevice); + } else { + return; + } + } else if (pCurr->eNetworkTypeInUse == PHY_TYPE_11B) { + if ((pDevice->eConfigPHYMode == PHY_TYPE_11B) || + (pDevice->eConfigPHYMode == PHY_TYPE_11G) || + (pDevice->eConfigPHYMode == PHY_TYPE_AUTO)) { + pDevice->byBBType = BB_TYPE_11B; + pMgmt->eCurrentPHYMode = PHY_TYPE_11B; + pDevice->bShortSlotTime = false; + BBvSetShortSlotTime(pDevice); + CARDvSetBSSMode(pDevice); + } else { + return; + } + } else { + if ((pDevice->eConfigPHYMode == PHY_TYPE_11G) || + (pDevice->eConfigPHYMode == PHY_TYPE_AUTO)) { + pDevice->byBBType = BB_TYPE_11G; + pMgmt->eCurrentPHYMode = PHY_TYPE_11G; + pDevice->bShortSlotTime = true; + BBvSetShortSlotTime(pDevice); + CARDvSetBSSMode(pDevice); + } else if (pDevice->eConfigPHYMode == PHY_TYPE_11B) { + pDevice->byBBType = BB_TYPE_11B; + pDevice->bShortSlotTime = false; + BBvSetShortSlotTime(pDevice); + CARDvSetBSSMode(pDevice); + } else { + return; + } + } + + if (uBSSMode == WMAC_MODE_ESS_STA) { + MACvRegBitsOff(pDevice, MAC_REG_HOSTCR, HOSTCR_ADHOC); + MACvRegBitsOn(pDevice, MAC_REG_RCR, RCR_BSSID); + pDevice->byRxMode |= RCR_BSSID; + pMgmt->bCurrBSSIDFilterOn = true; + } + + // set channel and clear NAV + CARDbSetMediaChannel(pDevice, pCurr->uChannel); + pMgmt->uCurrChannel = pCurr->uChannel; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Channel [%d]\n", pCurr->uChannel); + + if ((pDevice->bUpdateBBVGA) && + (pDevice->byBBVGACurrent != pDevice->abyBBVGA[0])) { + pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); + BBvSetShortSlotTime(pDevice); + } + // + // Notes: + // 1. In Ad-hoc mode : check if received others beacon as jointed indication, + // otherwise we will start own IBSS. + // 2. In Infra mode : Supposed we already synchronized with AP right now. + + if (uBSSMode == WMAC_MODE_IBSS_STA) { + MACvRegBitsOn(pDevice, MAC_REG_HOSTCR, HOSTCR_ADHOC); + MACvRegBitsOn(pDevice, MAC_REG_RCR, RCR_BSSID); + pDevice->byRxMode |= RCR_BSSID; + pMgmt->bCurrBSSIDFilterOn = true; + } + + if (pDevice->byBBType == BB_TYPE_11A) { + memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesA[0], sizeof(abyCurrSuppRatesA)); + pMgmt->abyCurrExtSuppRates[1] = 0; + } else if (pDevice->byBBType == BB_TYPE_11B) { + memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesB[0], sizeof(abyCurrSuppRatesB)); + pMgmt->abyCurrExtSuppRates[1] = 0; + } else { + memcpy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesG[0], sizeof(abyCurrSuppRatesG)); + memcpy(pMgmt->abyCurrExtSuppRates, &abyCurrExtSuppRatesG[0], sizeof(abyCurrExtSuppRatesG)); + } + pMgmt->byERPContext = pCurr->sERP.byERP; + + *pStatus = CMD_STATUS_SUCCESS; + + return; +}; + +static void Encyption_Rebuild(struct vnt_private *pDevice, PKnownBSS pCurr) + { + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { + if (pCurr->bWPAValid == true) { /*WPA-PSK */ + pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; + if(pCurr->abyPKType[0] == WPA_TKIP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; //TKIP + PRINT_K("Encyption_Rebuild--->ssid reset config to [WPAPSK-TKIP]\n"); + } + else if(pCurr->abyPKType[0] == WPA_AESCCMP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; //AES + PRINT_K("Encyption_Rebuild--->ssid reset config to [WPAPSK-AES]\n"); + } + } + else if(pCurr->bWPA2Valid == true) { //WPA2-PSK + pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; + if(pCurr->abyCSSPK[0] == WLAN_11i_CSS_TKIP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; //TKIP + PRINT_K("Encyption_Rebuild--->ssid reset config to [WPA2PSK-TKIP]\n"); + } + else if(pCurr->abyCSSPK[0] == WLAN_11i_CSS_CCMP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; //AES + PRINT_K("Encyption_Rebuild--->ssid reset config to [WPA2PSK-AES]\n"); + } + } + } + // } + return; + } + +/*+ + * + * Routine Description: + * Format TIM field + * + * + * Return Value: + * void + * +-*/ + +static void s_vMgrFormatTIM(struct vnt_manager *pMgmt, PWLAN_IE_TIM pTIM) +{ + u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + u8 byMap; + int ii, jj; + int bStartFound = false; + int bMulticast = false; + u16 wStartIndex = 0; + u16 wEndIndex = 0; + + // Find size of partial virtual bitmap + for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) { + byMap = pMgmt->abyPSTxMap[ii]; + if (!ii) { + // Mask out the broadcast bit which is indicated separately. + bMulticast = (byMap & byMask[0]) != 0; + if(bMulticast) { + pMgmt->sNodeDBTable[0].bRxPSPoll = true; + } + byMap = 0; + } + if (byMap) { + if (!bStartFound) { + bStartFound = true; + wStartIndex = (u16)ii; + } + wEndIndex = (u16)ii; + } + } + + // Round start index down to nearest even number + wStartIndex &= ~BIT0; + + // Round end index up to nearest even number + wEndIndex = ((wEndIndex + 1) & ~BIT0); + + // Size of element payload + + pTIM->len = 3 + (wEndIndex - wStartIndex) + 1; + + // Fill in the Fixed parts of the TIM + pTIM->byDTIMCount = pMgmt->byDTIMCount; + pTIM->byDTIMPeriod = pMgmt->byDTIMPeriod; + pTIM->byBitMapCtl = (bMulticast ? TIM_MULTICAST_MASK : 0) | + (((wStartIndex >> 1) << 1) & TIM_BITMAPOFFSET_MASK); + + // Append variable part of TIM + + for (ii = wStartIndex, jj =0 ; ii <= wEndIndex; ii++, jj++) { + pTIM->byVirtBitMap[jj] = pMgmt->abyPSTxMap[ii]; + } + + // Aid = 0 don't used. + pTIM->byVirtBitMap[0] &= ~BIT0; +} + +/*+ + * + * Routine Description: + * Constructs an Beacon frame( Ad-hoc mode) + * + * + * Return Value: + * PTR to frame; or NULL on allocation failure + * +-*/ + +static struct vnt_tx_mgmt *s_MgrMakeBeacon(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wCurrBeaconPeriod, + u32 uCurrChannel, u16 wCurrATIMWinodw, PWLAN_IE_SSID pCurrSSID, + u8 *pCurrBSSID, PWLAN_IE_SUPP_RATES pCurrSuppRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + WLAN_FR_BEACON sFrame; + u8 abyBroadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + /* prepare beacon frame */ + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_BEACON_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + // Setup the sFrame structure. + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_BEACON_FR_MAXLEN; + vMgrEncodeBeacon(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_BEACON) + )); + + if (pDevice->bEnablePSMode) { + sFrame.pHdr->sA3.wFrameCtl |= cpu_to_le16((u16)WLAN_SET_FC_PWRMGT(1)); + } + + memcpy( sFrame.pHdr->sA3.abyAddr1, abyBroadcastAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pCurrBSSID, WLAN_BSSID_LEN); + *sFrame.pwBeaconInterval = cpu_to_le16(wCurrBeaconPeriod); + *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo); + // Copy SSID + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, + pCurrSSID, + ((PWLAN_IE_SSID)pCurrSSID)->len + WLAN_IEHDR_LEN + ); + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, + pCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + // DS parameter + if (pDevice->byBBType != BB_TYPE_11A) { + sFrame.pDSParms = (PWLAN_IE_DS_PARMS)(sFrame.pBuf + sFrame.len); + sFrame.len += (1) + WLAN_IEHDR_LEN; + sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS; + sFrame.pDSParms->len = 1; + sFrame.pDSParms->byCurrChannel = (u8)uCurrChannel; + } + // TIM field + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + sFrame.pTIM = (PWLAN_IE_TIM)(sFrame.pBuf + sFrame.len); + sFrame.pTIM->byElementID = WLAN_EID_TIM; + s_vMgrFormatTIM(pMgmt, sFrame.pTIM); + sFrame.len += (WLAN_IEHDR_LEN + sFrame.pTIM->len); + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + + // IBSS parameter + sFrame.pIBSSParms = (PWLAN_IE_IBSS_PARMS)(sFrame.pBuf + sFrame.len); + sFrame.len += (2) + WLAN_IEHDR_LEN; + sFrame.pIBSSParms->byElementID = WLAN_EID_IBSS_PARMS; + sFrame.pIBSSParms->len = 2; + sFrame.pIBSSParms->wATIMWindow = wCurrATIMWinodw; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + /* RSN parameter */ + sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len); + sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA; + sFrame.pRSNWPA->len = 12; + sFrame.pRSNWPA->abyOUI[0] = 0x00; + sFrame.pRSNWPA->abyOUI[1] = 0x50; + sFrame.pRSNWPA->abyOUI[2] = 0xf2; + sFrame.pRSNWPA->abyOUI[3] = 0x01; + sFrame.pRSNWPA->wVersion = 1; + sFrame.pRSNWPA->abyMulticast[0] = 0x00; + sFrame.pRSNWPA->abyMulticast[1] = 0x50; + sFrame.pRSNWPA->abyMulticast[2] = 0xf2; + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) + sFrame.pRSNWPA->abyMulticast[3] = 0x04;//AES + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) + sFrame.pRSNWPA->abyMulticast[3] = 0x02;//TKIP + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) + sFrame.pRSNWPA->abyMulticast[3] = 0x01;//WEP40 + else + sFrame.pRSNWPA->abyMulticast[3] = 0x00;//NONE + + // Pairwise Key Cipher Suite + sFrame.pRSNWPA->wPKCount = 0; + // Auth Key Management Suite + *((u16 *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; + sFrame.pRSNWPA->len +=2; + + // RSN Capabilites + *((u16 *)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; + sFrame.pRSNWPA->len +=2; + sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + } + } + + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { + sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len); + sFrame.len += 1 + WLAN_IEHDR_LEN; + sFrame.pERP->byElementID = WLAN_EID_ERP; + sFrame.pERP->len = 1; + sFrame.pERP->byContext = 0; + if (pDevice->bProtectMode == true) + sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION; + if (pDevice->bNonERPPresent == true) + sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT; + if (pDevice->bBarkerPreambleMd == true) + sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE; + } + if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, + pCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + // hostapd wpa/wpa2 IE + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == true)) { + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + if (pMgmt->wWPAIELen != 0) { + sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); + memcpy(sFrame.pRSN, pMgmt->abyWPAIE, pMgmt->wWPAIELen); + sFrame.len += pMgmt->wWPAIELen; + } + } + } + + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + +/*+ + * + * Routine Description: + * Constructs an Prob-response frame + * + * + * Return Value: + * PTR to frame; or NULL on allocation failure + * +-*/ + +struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wCurrBeaconPeriod, + u32 uCurrChannel, u16 wCurrATIMWinodw, u8 *pDstAddr, + PWLAN_IE_SSID pCurrSSID, u8 *pCurrBSSID, + PWLAN_IE_SUPP_RATES pCurrSuppRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates, u8 byPHYType) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + WLAN_FR_PROBERESP sFrame; + + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_PROBERESP_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + // Setup the sFrame structure. + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_PROBERESP_FR_MAXLEN; + vMgrEncodeProbeResponse(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBERESP) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pCurrBSSID, WLAN_BSSID_LEN); + *sFrame.pwBeaconInterval = cpu_to_le16(wCurrBeaconPeriod); + *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo); + + if (byPHYType == BB_TYPE_11B) { + *sFrame.pwCapInfo &= cpu_to_le16((u16)~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1))); + } + + // Copy SSID + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, + pCurrSSID, + ((PWLAN_IE_SSID)pCurrSSID)->len + WLAN_IEHDR_LEN + ); + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, + pCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + + // DS parameter + if (pDevice->byBBType != BB_TYPE_11A) { + sFrame.pDSParms = (PWLAN_IE_DS_PARMS)(sFrame.pBuf + sFrame.len); + sFrame.len += (1) + WLAN_IEHDR_LEN; + sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS; + sFrame.pDSParms->len = 1; + sFrame.pDSParms->byCurrChannel = (u8)uCurrChannel; + } + + if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) { + // IBSS parameter + sFrame.pIBSSParms = (PWLAN_IE_IBSS_PARMS)(sFrame.pBuf + sFrame.len); + sFrame.len += (2) + WLAN_IEHDR_LEN; + sFrame.pIBSSParms->byElementID = WLAN_EID_IBSS_PARMS; + sFrame.pIBSSParms->len = 2; + sFrame.pIBSSParms->wATIMWindow = 0; + } + if (pDevice->byBBType == BB_TYPE_11G) { + sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len); + sFrame.len += 1 + WLAN_IEHDR_LEN; + sFrame.pERP->byElementID = WLAN_EID_ERP; + sFrame.pERP->len = 1; + sFrame.pERP->byContext = 0; + if (pDevice->bProtectMode == true) + sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION; + if (pDevice->bNonERPPresent == true) + sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT; + if (pDevice->bBarkerPreambleMd == true) + sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE; + } + + if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, + pCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + + // hostapd wpa/wpa2 IE + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == true)) { + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + if (pMgmt->wWPAIELen != 0) { + sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); + memcpy(sFrame.pRSN, pMgmt->abyWPAIE, pMgmt->wWPAIELen); + sFrame.len += pMgmt->wWPAIELen; + } + } + } + + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + +/*+ + * + * Routine Description: + * Constructs an association request frame + * + * + * Return Value: + * A ptr to frame or NULL on allocation failue + * +-*/ + +struct vnt_tx_mgmt *s_MgrMakeAssocRequest(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u8 *pDAddr, u16 wCurrCapInfo, + u16 wListenInterval, + PWLAN_IE_SSID pCurrSSID, + PWLAN_IE_SUPP_RATES pCurrRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + WLAN_FR_ASSOCREQ sFrame; + u8 *pbyIEs; + u8 *pbyRSN; + + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_ASSOCREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + // Setup the sFrame structure. + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_ASSOCREQ_FR_MAXLEN; + // format fixed field frame structure + vMgrEncodeAssocRequest(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ASSOCREQ) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + // Set the capability and listen interval + *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo); + *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval); + + // sFrame.len point to end of fixed field + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrSSID->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN); + + pMgmt->sAssocInfo.AssocInfo.RequestIELength = pCurrSSID->len + WLAN_IEHDR_LEN; + pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + pbyIEs = pMgmt->sAssocInfo.abyIEs; + memcpy(pbyIEs, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN); + pbyIEs += pCurrSSID->len + WLAN_IEHDR_LEN; + + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + if ((pDevice->byBBType == BB_TYPE_11B) && (pCurrRates->len > 4)) + sFrame.len += 4 + WLAN_IEHDR_LEN; + else + sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + + // Copy the extension rate set + if ((pDevice->byBBType == BB_TYPE_11G) && (pCurrExtSuppRates->len > 0)) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); + } + + pMgmt->sAssocInfo.AssocInfo.RequestIELength += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN; + + if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) && + (pMgmt->pCurrBSS != NULL)) { + /* WPA IE */ + sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len); + sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA; + sFrame.pRSNWPA->len = 16; + sFrame.pRSNWPA->abyOUI[0] = 0x00; + sFrame.pRSNWPA->abyOUI[1] = 0x50; + sFrame.pRSNWPA->abyOUI[2] = 0xf2; + sFrame.pRSNWPA->abyOUI[3] = 0x01; + sFrame.pRSNWPA->wVersion = 1; + //Group Key Cipher Suite + sFrame.pRSNWPA->abyMulticast[0] = 0x00; + sFrame.pRSNWPA->abyMulticast[1] = 0x50; + sFrame.pRSNWPA->abyMulticast[2] = 0xf2; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + sFrame.pRSNWPA->abyMulticast[3] = pMgmt->pCurrBSS->byGKType; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + sFrame.pRSNWPA->abyMulticast[3] = WPA_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + sFrame.pRSNWPA->abyMulticast[3] = WPA_AESCCMP; + } else { + sFrame.pRSNWPA->abyMulticast[3] = WPA_NONE; + } + // Pairwise Key Cipher Suite + sFrame.pRSNWPA->wPKCount = 1; + sFrame.pRSNWPA->PKSList[0].abyOUI[0] = 0x00; + sFrame.pRSNWPA->PKSList[0].abyOUI[1] = 0x50; + sFrame.pRSNWPA->PKSList[0].abyOUI[2] = 0xf2; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_AESCCMP; + } else { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE; + } + // Auth Key Management Suite + pbyRSN = (u8 *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len); + *pbyRSN++=0x01; + *pbyRSN++=0x00; + *pbyRSN++=0x00; + + *pbyRSN++=0x50; + *pbyRSN++=0xf2; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) { + *pbyRSN++=WPA_AUTH_PSK; + } + else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA) { + *pbyRSN++=WPA_AUTH_IEEE802_1X; + } + else { + *pbyRSN++=WPA_NONE; + } + + sFrame.pRSNWPA->len +=6; + + // RSN Capabilites + + *pbyRSN++=0x00; + *pbyRSN++=0x00; + sFrame.pRSNWPA->len +=2; + + sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION + pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + memcpy(pbyIEs, sFrame.pRSNWPA, sFrame.pRSNWPA->len + WLAN_IEHDR_LEN); + pbyIEs += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + + } else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && + (pMgmt->pCurrBSS != NULL)) { + unsigned int ii; + u16 * pwPMKID; + + // WPA IE + sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); + sFrame.pRSN->byElementID = WLAN_EID_RSN; + sFrame.pRSN->len = 6; //Version(2)+GK(4) + sFrame.pRSN->wVersion = 1; + //Group Key Cipher Suite + sFrame.pRSN->abyRSN[0] = 0x00; + sFrame.pRSN->abyRSN[1] = 0x0F; + sFrame.pRSN->abyRSN[2] = 0xAC; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + sFrame.pRSN->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_CCMP; + } else { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_UNKNOWN; + } + + // Pairwise Key Cipher Suite + sFrame.pRSN->abyRSN[4] = 1; + sFrame.pRSN->abyRSN[5] = 0; + sFrame.pRSN->abyRSN[6] = 0x00; + sFrame.pRSN->abyRSN[7] = 0x0F; + sFrame.pRSN->abyRSN[8] = 0xAC; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_CCMP; + } else if (pMgmt->byCSSPK == KEY_CTL_NONE) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_USE_GROUP; + } else { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_UNKNOWN; + } + sFrame.pRSN->len += 6; + + // Auth Key Management Suite + sFrame.pRSN->abyRSN[10] = 1; + sFrame.pRSN->abyRSN[11] = 0; + sFrame.pRSN->abyRSN[12] = 0x00; + sFrame.pRSN->abyRSN[13] = 0x0F; + sFrame.pRSN->abyRSN[14] = 0xAC; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_PSK; + } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_802_1X; + } else { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN; + } + sFrame.pRSN->len +=6; + + // RSN Capabilites + if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) { + memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); + } else { + sFrame.pRSN->abyRSN[16] = 0; + sFrame.pRSN->abyRSN[17] = 0; + } + sFrame.pRSN->len +=2; + + if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { + // RSN PMKID + pbyRSN = &sFrame.pRSN->abyRSN[18]; + pwPMKID = (u16 *)pbyRSN; // Point to PMKID count + *pwPMKID = 0; // Initialize PMKID count + pbyRSN += 2; // Point to PMKID list + for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) { + if (!memcmp(&pDevice->gsPMKID.BSSIDInfo[ii].BSSID[0], + pMgmt->abyCurrBSSID, + ETH_ALEN)) { + (*pwPMKID)++; + memcpy(pbyRSN, + pDevice->gsPMKID.BSSIDInfo[ii].PMKID, + 16); + pbyRSN += 16; + } + } + if (*pwPMKID != 0) { + sFrame.pRSN->len += (2 + (*pwPMKID)*16); + } + } + + sFrame.len += sFrame.pRSN->len + WLAN_IEHDR_LEN; + // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION + pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSN->len + WLAN_IEHDR_LEN; + memcpy(pbyIEs, sFrame.pRSN, sFrame.pRSN->len + WLAN_IEHDR_LEN); + pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN; + } + + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + return pTxPacket; +} + +/*+ + * + * Routine Description: + * Constructs an re-association request frame + * + * + * Return Value: + * A ptr to frame or NULL on allocation failure + * +-*/ + +struct vnt_tx_mgmt *s_MgrMakeReAssocRequest(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u8 *pDAddr, u16 wCurrCapInfo, + u16 wListenInterval, PWLAN_IE_SSID pCurrSSID, + PWLAN_IE_SUPP_RATES pCurrRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + WLAN_FR_REASSOCREQ sFrame; + u8 *pbyIEs; + u8 *pbyRSN; + + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_REASSOCREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + /* Setup the sFrame structure. */ + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_REASSOCREQ_FR_MAXLEN; + + // format fixed field frame structure + vMgrEncodeReassocRequest(&sFrame); + + /* Setup the header */ + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_REASSOCREQ) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + /* Set the capability and listen interval */ + *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo); + *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval); + + memcpy(sFrame.pAddrCurrAP, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + /* Copy the SSID */ + /* sFrame.len point to end of fixed field */ + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrSSID->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN); + + pMgmt->sAssocInfo.AssocInfo.RequestIELength = pCurrSSID->len + WLAN_IEHDR_LEN; + pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + pbyIEs = pMgmt->sAssocInfo.abyIEs; + memcpy(pbyIEs, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN); + pbyIEs += pCurrSSID->len + WLAN_IEHDR_LEN; + + /* Copy the rate set */ + /* sFrame.len point to end of SSID */ + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + + // Copy the extension rate set + if ((pMgmt->eCurrentPHYMode == PHY_TYPE_11G) && (pCurrExtSuppRates->len > 0)) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); + } + + pMgmt->sAssocInfo.AssocInfo.RequestIELength += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN; + + if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) && + (pMgmt->pCurrBSS != NULL)) { + /* WPA IE */ + sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len); + sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA; + sFrame.pRSNWPA->len = 16; + sFrame.pRSNWPA->abyOUI[0] = 0x00; + sFrame.pRSNWPA->abyOUI[1] = 0x50; + sFrame.pRSNWPA->abyOUI[2] = 0xf2; + sFrame.pRSNWPA->abyOUI[3] = 0x01; + sFrame.pRSNWPA->wVersion = 1; + //Group Key Cipher Suite + sFrame.pRSNWPA->abyMulticast[0] = 0x00; + sFrame.pRSNWPA->abyMulticast[1] = 0x50; + sFrame.pRSNWPA->abyMulticast[2] = 0xf2; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + sFrame.pRSNWPA->abyMulticast[3] = pMgmt->pCurrBSS->byGKType; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + sFrame.pRSNWPA->abyMulticast[3] = WPA_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + sFrame.pRSNWPA->abyMulticast[3] = WPA_AESCCMP; + } else { + sFrame.pRSNWPA->abyMulticast[3] = WPA_NONE; + } + // Pairwise Key Cipher Suite + sFrame.pRSNWPA->wPKCount = 1; + sFrame.pRSNWPA->PKSList[0].abyOUI[0] = 0x00; + sFrame.pRSNWPA->PKSList[0].abyOUI[1] = 0x50; + sFrame.pRSNWPA->PKSList[0].abyOUI[2] = 0xf2; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_AESCCMP; + } else { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE; + } + // Auth Key Management Suite + pbyRSN = (u8 *)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len); + *pbyRSN++=0x01; + *pbyRSN++=0x00; + *pbyRSN++=0x00; + + *pbyRSN++=0x50; + *pbyRSN++=0xf2; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) { + *pbyRSN++=WPA_AUTH_PSK; + } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA) { + *pbyRSN++=WPA_AUTH_IEEE802_1X; + } else { + *pbyRSN++=WPA_NONE; + } + + sFrame.pRSNWPA->len +=6; + + // RSN Capabilites + *pbyRSN++=0x00; + *pbyRSN++=0x00; + sFrame.pRSNWPA->len +=2; + + sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION + pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + memcpy(pbyIEs, sFrame.pRSNWPA, sFrame.pRSNWPA->len + WLAN_IEHDR_LEN); + pbyIEs += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + + } else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && + (pMgmt->pCurrBSS != NULL)) { + unsigned int ii; + u16 * pwPMKID; + + /* WPA IE */ + sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); + sFrame.pRSN->byElementID = WLAN_EID_RSN; + sFrame.pRSN->len = 6; //Version(2)+GK(4) + sFrame.pRSN->wVersion = 1; + //Group Key Cipher Suite + sFrame.pRSN->abyRSN[0] = 0x00; + sFrame.pRSN->abyRSN[1] = 0x0F; + sFrame.pRSN->abyRSN[2] = 0xAC; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + sFrame.pRSN->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_CCMP; + } else { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_UNKNOWN; + } + + // Pairwise Key Cipher Suite + sFrame.pRSN->abyRSN[4] = 1; + sFrame.pRSN->abyRSN[5] = 0; + sFrame.pRSN->abyRSN[6] = 0x00; + sFrame.pRSN->abyRSN[7] = 0x0F; + sFrame.pRSN->abyRSN[8] = 0xAC; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_CCMP; + } else if (pMgmt->byCSSPK == KEY_CTL_NONE) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_USE_GROUP; + } else { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_UNKNOWN; + } + sFrame.pRSN->len += 6; + + // Auth Key Management Suite + sFrame.pRSN->abyRSN[10] = 1; + sFrame.pRSN->abyRSN[11] = 0; + sFrame.pRSN->abyRSN[12] = 0x00; + sFrame.pRSN->abyRSN[13] = 0x0F; + sFrame.pRSN->abyRSN[14] = 0xAC; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_PSK; + } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_802_1X; + } else { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN; + } + sFrame.pRSN->len +=6; + + // RSN Capabilites + if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) { + memcpy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); + } else { + sFrame.pRSN->abyRSN[16] = 0; + sFrame.pRSN->abyRSN[17] = 0; + } + sFrame.pRSN->len +=2; + + if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == true) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { + // RSN PMKID + pbyRSN = &sFrame.pRSN->abyRSN[18]; + pwPMKID = (u16 *)pbyRSN; // Point to PMKID count + *pwPMKID = 0; // Initialize PMKID count + pbyRSN += 2; // Point to PMKID list + for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) { + if (!memcmp(&pDevice->gsPMKID.BSSIDInfo[ii].BSSID[0], + pMgmt->abyCurrBSSID, + ETH_ALEN)) { + (*pwPMKID)++; + memcpy(pbyRSN, + pDevice->gsPMKID.BSSIDInfo[ii].PMKID, + 16); + pbyRSN += 16; + } + } + if (*pwPMKID != 0) { + sFrame.pRSN->len += (2 + (*pwPMKID)*16); + } + } + + sFrame.len += sFrame.pRSN->len + WLAN_IEHDR_LEN; + // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION + pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSN->len + WLAN_IEHDR_LEN; + memcpy(pbyIEs, sFrame.pRSN, sFrame.pRSN->len + WLAN_IEHDR_LEN); + pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN; + } + + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + +/*+ + * + * Routine Description: + * Constructs an assoc-response frame + * + * + * Return Value: + * PTR to frame; or NULL on allocation failure + * +-*/ + +struct vnt_tx_mgmt *s_MgrMakeAssocResponse(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wAssocStatus, + u16 wAssocAID, u8 *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + WLAN_FR_ASSOCRESP sFrame; + + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_ASSOCREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + // Setup the sFrame structure + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN; + vMgrEncodeAssocResponse(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ASSOCRESP) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo); + *sFrame.pwStatus = cpu_to_le16(wAssocStatus); + *sFrame.pwAid = cpu_to_le16((u16)(wAssocAID | BIT14 | BIT15)); + + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, + pCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + + if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, + pCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + +/*+ + * + * Routine Description: + * Constructs an reassoc-response frame + * + * + * Return Value: + * PTR to frame; or NULL on allocation failure + * +-*/ + +struct vnt_tx_mgmt *s_MgrMakeReAssocResponse(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, u16 wCurrCapInfo, u16 wAssocStatus, + u16 wAssocAID, u8 *pDstAddr, PWLAN_IE_SUPP_RATES pCurrSuppRates, + PWLAN_IE_SUPP_RATES pCurrExtSuppRates) +{ + struct vnt_tx_mgmt *pTxPacket = NULL; + WLAN_FR_REASSOCRESP sFrame; + + pTxPacket = (struct vnt_tx_mgmt *)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(struct vnt_tx_mgmt) + + WLAN_ASSOCREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((u8 *)pTxPacket + + sizeof(struct vnt_tx_mgmt)); + // Setup the sFrame structure + sFrame.pBuf = (u8 *)pTxPacket->p80211Header; + sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN; + vMgrEncodeReassocResponse(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_REASSOCRESP) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo); + *sFrame.pwStatus = cpu_to_le16(wAssocStatus); + *sFrame.pwAid = cpu_to_le16((u16)(wAssocAID | BIT14 | BIT15)); + + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, + pCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + + if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, + pCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + +/*+ + * + * Routine Description: + * Handles probe response management frames. + * + * + * Return Value: + * none. + * +-*/ + +static void s_vMgrRxProbeResponse(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket) +{ + PKnownBSS pBSSList = NULL; + WLAN_FR_PROBERESP sFrame; + u8 byCurrChannel = pRxPacket->byRxChannel; + ERPObject sERP; + int bChannelHit = true; + + memset(&sFrame, 0, sizeof(WLAN_FR_PROBERESP)); + // decode the frame + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + vMgrDecodeProbeResponse(&sFrame); + + if ((sFrame.pqwTimestamp == NULL) + || (sFrame.pwBeaconInterval == NULL) + || (sFrame.pwCapInfo == NULL) + || (sFrame.pSSID == NULL) + || (sFrame.pSuppRates == NULL)) { + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe resp:Fail addr:[%p]\n", + pRxPacket->p80211Header); + DBG_PORT80(0xCC); + return; + } + + if(sFrame.pSSID->len == 0) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx Probe resp: SSID len = 0 \n"); + + //{{ RobertYu:20050201, 11a byCurrChannel != sFrame.pDSParms->byCurrChannel mapping + if( byCurrChannel > CB_MAX_CHANNEL_24G ) + { + if (sFrame.pDSParms) { + if (byCurrChannel == + RFaby11aChannelIndex[sFrame.pDSParms->byCurrChannel-1]) + bChannelHit = true; + byCurrChannel = + RFaby11aChannelIndex[sFrame.pDSParms->byCurrChannel-1]; + } else { + bChannelHit = true; + } + } else { + if (sFrame.pDSParms) { + if (byCurrChannel == sFrame.pDSParms->byCurrChannel) + bChannelHit = true; + byCurrChannel = sFrame.pDSParms->byCurrChannel; + } else { + bChannelHit = true; + } + } + //RobertYu:20050201 + +if(ChannelExceedZoneType(pDevice,byCurrChannel)==true) + return; + + if (sFrame.pERP) { + sERP.byERP = sFrame.pERP->byContext; + sERP.bERPExist = true; + } else { + sERP.bERPExist = false; + sERP.byERP = 0; + } + + // update or insert the bss + pBSSList = BSSpAddrIsInBSSList((void *) pDevice, + sFrame.pHdr->sA3.abyAddr3, + sFrame.pSSID); + if (pBSSList) { + BSSbUpdateToBSSList((void *) pDevice, + *sFrame.pqwTimestamp, + *sFrame.pwBeaconInterval, + *sFrame.pwCapInfo, + byCurrChannel, + bChannelHit, + sFrame.pSSID, + sFrame.pSuppRates, + sFrame.pExtSuppRates, + &sERP, + sFrame.pRSN, + sFrame.pRSNWPA, + sFrame.pIE_Country, + sFrame.pIE_Quiet, + pBSSList, + sFrame.len - WLAN_HDR_ADDR3_LEN, + /* payload of probresponse */ + sFrame.pHdr->sA4.abyAddr4, + (void *) pRxPacket); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Probe resp/insert: RxChannel = : %d\n", byCurrChannel); + BSSbInsertToBSSList((void *) pDevice, + sFrame.pHdr->sA3.abyAddr3, + *sFrame.pqwTimestamp, + *sFrame.pwBeaconInterval, + *sFrame.pwCapInfo, + byCurrChannel, + sFrame.pSSID, + sFrame.pSuppRates, + sFrame.pExtSuppRates, + &sERP, + sFrame.pRSN, + sFrame.pRSNWPA, + sFrame.pIE_Country, + sFrame.pIE_Quiet, + sFrame.len - WLAN_HDR_ADDR3_LEN, + sFrame.pHdr->sA4.abyAddr4, /* payload of beacon */ + (void *) pRxPacket); + } + return; + +} + +/*+ + * + * Routine Description:(AP)or(Ad-hoc STA) + * Handles probe request management frames. + * + * + * Return Value: + * none. + * +-*/ + +static void s_vMgrRxProbeRequest(struct vnt_private *pDevice, + struct vnt_manager *pMgmt, struct vnt_rx_mgmt *pRxPacket) +{ + WLAN_FR_PROBEREQ sFrame; + CMD_STATUS Status; + struct vnt_tx_mgmt *pTxPacket; + u8 byPHYType = BB_TYPE_11B; + + // STA in Ad-hoc mode: when latest TBTT beacon transmit success, + // STA have to response this request. + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && pDevice->bBeaconSent)) { + + memset(&sFrame, 0, sizeof(WLAN_FR_PROBEREQ)); + // decode the frame + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (u8 *)pRxPacket->p80211Header; + vMgrDecodeProbeRequest(&sFrame); +/* + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%pM\n", + sFrame.pHdr->sA3.abyAddr2); +*/ + if (sFrame.pSSID->len != 0) { + if (sFrame.pSSID->len != ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) + return; + if (memcmp(sFrame.pSSID->abySSID, + ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, + ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) != 0) { + return; + } + } + + if ((sFrame.pSuppRates->len > 4) || (sFrame.pExtSuppRates != NULL)) { + byPHYType = BB_TYPE_11G; + } + + // Probe response reply.. + pTxPacket = s_MgrMakeProbeResponse + ( + pDevice, + pMgmt, + pMgmt->wCurrCapInfo, + pMgmt->wCurrBeaconPeriod, + pMgmt->uCurrChannel, + 0, + sFrame.pHdr->sA3.abyAddr2, + (PWLAN_IE_SSID)pMgmt->abyCurrSSID, + (u8 *)pMgmt->abyCurrBSSID, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + byPHYType + ); + if (pTxPacket != NULL ){ + /* send the frame */ + Status = csMgmt_xmit(pDevice, pTxPacket); + if (Status != CMD_STATUS_PENDING) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Probe response tx failed\n"); + } + else { +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Probe response tx sending..\n"); + } + } + } + + return; +} + +/*+ + * + * Routine Description: + * + * Entry point for the reception and handling of 802.11 management + * frames. Makes a determination of the frame type and then calls + * the appropriate function. + * + * + * Return Value: + * none. + * +-*/ + +void vMgrRxManagePacket(struct vnt_private *pDevice, struct vnt_manager *pMgmt, + struct vnt_rx_mgmt *pRxPacket) +{ + int bInScan = false; + u32 uNodeIndex = 0; + NODE_STATE eNodeState = 0; + CMD_STATUS Status; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (BSSbIsSTAInNodeDB(pDevice, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) + eNodeState = pMgmt->sNodeDBTable[uNodeIndex].eNodeState; + } + + switch( WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) ){ + + case WLAN_FSTYPE_ASSOCREQ: + // Frame Clase = 2 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocreq\n"); + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && + (eNodeState < NODE_AUTH)) { + // send deauth notification + // reason = (6) class 2 received from nonauth sta + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + pRxPacket->p80211Header->sA3.abyAddr2, + (6), + &Status + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 1\n"); + } + else { + s_vMgrRxAssocRequest(pDevice, pMgmt, pRxPacket, uNodeIndex); + } + break; + + case WLAN_FSTYPE_ASSOCRESP: + // Frame Clase = 2 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocresp1\n"); + s_vMgrRxAssocResponse(pDevice, pMgmt, pRxPacket, false); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocresp2\n"); + break; + + case WLAN_FSTYPE_REASSOCREQ: + // Frame Clase = 2 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx reassocreq\n"); + // Todo: reassoc + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && + (eNodeState < NODE_AUTH)) { + // send deauth notification + // reason = (6) class 2 received from nonauth sta + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + pRxPacket->p80211Header->sA3.abyAddr2, + (6), + &Status + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 2\n"); + + } + s_vMgrRxReAssocRequest(pDevice, pMgmt, pRxPacket, uNodeIndex); + break; + + case WLAN_FSTYPE_REASSOCRESP: + // Frame Clase = 2 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx reassocresp\n"); + s_vMgrRxAssocResponse(pDevice, pMgmt, pRxPacket, true); + break; + + case WLAN_FSTYPE_PROBEREQ: + // Frame Clase = 0 + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx probereq\n"); + s_vMgrRxProbeRequest(pDevice, pMgmt, pRxPacket); + break; + + case WLAN_FSTYPE_PROBERESP: + // Frame Clase = 0 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx proberesp\n"); + + s_vMgrRxProbeResponse(pDevice, pMgmt, pRxPacket); + break; + + case WLAN_FSTYPE_BEACON: + // Frame Clase = 0 + //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx beacon\n"); + if (pMgmt->eScanState != WMAC_NO_SCANNING) { + bInScan = true; + } + s_vMgrRxBeacon(pDevice, pMgmt, pRxPacket, bInScan); + break; + + case WLAN_FSTYPE_ATIM: + // Frame Clase = 1 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx atim\n"); + break; + + case WLAN_FSTYPE_DISASSOC: + // Frame Clase = 2 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx disassoc\n"); + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && + (eNodeState < NODE_AUTH)) { + // send deauth notification + // reason = (6) class 2 received from nonauth sta + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + pRxPacket->p80211Header->sA3.abyAddr2, + (6), + &Status + ); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 3\n"); + } + s_vMgrRxDisassociation(pDevice, pMgmt, pRxPacket); + break; + + case WLAN_FSTYPE_AUTHEN: + // Frame Clase = 1 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx authen\n"); + s_vMgrRxAuthentication(pDevice, pMgmt, pRxPacket); + break; + + case WLAN_FSTYPE_DEAUTHEN: + // Frame Clase = 1 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx deauthen\n"); + s_vMgrRxDeauthentication(pDevice, pMgmt, pRxPacket); + break; + + default: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx unknown mgmt\n"); + } + + return; +} + +/*+ + * + * Routine Description: + * + * + * Prepare beacon to send + * + * Return Value: + * true if success; false if failed. + * +-*/ +int bMgrPrepareBeaconToSend(struct vnt_private *pDevice, + struct vnt_manager *pMgmt) +{ + struct vnt_tx_mgmt *pTxPacket; + +// pDevice->bBeaconBufReady = false; + if (pDevice->bEncryptionEnable || pDevice->bEnable8021x){ + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1); + } + else { + pMgmt->wCurrCapInfo &= ~WLAN_SET_CAP_INFO_PRIVACY(1); + } + pTxPacket = s_MgrMakeBeacon + ( + pDevice, + pMgmt, + pMgmt->wCurrCapInfo, + pMgmt->wCurrBeaconPeriod, + pMgmt->uCurrChannel, + pMgmt->wCurrATIMWindow, //0, + (PWLAN_IE_SSID)pMgmt->abyCurrSSID, + (u8 *)pMgmt->abyCurrBSSID, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (pMgmt->abyCurrBSSID[0] == 0)) + return false; + + csBeacon_xmit(pDevice, pTxPacket); + MACvRegBitsOn(pDevice, MAC_REG_TCR, TCR_AUTOBCNTX); + + return true; +} + +/*+ + * + * Routine Description: + * + * Log a warning message based on the contents of the Status + * Code field of an 802.11 management frame. Defines are + * derived from 802.11-1997 SPEC. + * + * Return Value: + * none. + * +-*/ +static void s_vMgrLogStatus(struct vnt_manager *pMgmt, u16 wStatus) +{ + switch( wStatus ){ + case WLAN_MGMT_STATUS_UNSPEC_FAILURE: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Unspecified error.\n"); + break; + case WLAN_MGMT_STATUS_CAPS_UNSUPPORTED: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Can't support all requested capabilities.\n"); + break; + case WLAN_MGMT_STATUS_REASSOC_NO_ASSOC: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Reassoc denied, can't confirm original Association.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, undefine in spec\n"); + break; + case WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Peer doesn't support authen algorithm.\n"); + break; + case WLAN_MGMT_STATUS_RX_AUTH_NOSEQ: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen frame received out of sequence.\n"); + break; + case WLAN_MGMT_STATUS_CHALLENGE_FAIL: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen rejected, challenge failure.\n"); + break; + case WLAN_MGMT_STATUS_AUTH_TIMEOUT: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen rejected, timeout waiting for next frame.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, AP too busy.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_RATES: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we haven't enough basic rates.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_SHORTPREAMBLE: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support short preamble.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_PBCC: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support PBCC.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_AGILITY: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support channel agility.\n"); + break; + default: + DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Unknown status code %d.\n", wStatus); + break; + } +} + +/* + * + * Description: + * Add BSSID in PMKID Candidate list. + * + * Parameters: + * In: + * hDeviceContext - device structure point + * pbyBSSID - BSSID address for adding + * wRSNCap - BSS's RSN capability + * Out: + * none + * + * Return Value: none. + * +-*/ + +int bAdd_PMKID_Candidate(struct vnt_private *pDevice, u8 *pbyBSSID, + PSRSNCapObject psRSNCapObj) +{ + PPMKID_CANDIDATE pCandidateList; + int ii = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates); + + if ((pDevice == NULL) || (pbyBSSID == NULL) || (psRSNCapObj == NULL)) + return false; + + if (pDevice->gsPMKIDCandidate.NumCandidates >= MAX_PMKIDLIST) + return false; + + // Update Old Candidate + for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) { + pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii]; + if (!memcmp(pCandidateList->BSSID, pbyBSSID, ETH_ALEN)) { + if ((psRSNCapObj->bRSNCapExist == true) + && (psRSNCapObj->wRSNCap & BIT0)) { + pCandidateList->Flags |= + NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; + } else { + pCandidateList->Flags &= + ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); + } + return true; + } + } + + // New Candidate + pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates]; + if ((psRSNCapObj->bRSNCapExist == true) && (psRSNCapObj->wRSNCap & BIT0)) { + pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; + } else { + pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); + } + memcpy(pCandidateList->BSSID, pbyBSSID, ETH_ALEN); + pDevice->gsPMKIDCandidate.NumCandidates++; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"NumCandidates:%d\n", (int)pDevice->gsPMKIDCandidate.NumCandidates); + return true; +} + +/* + * + * Description: + * Flush PMKID Candidate list. + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ + +void vFlush_PMKID_Candidate(struct vnt_private *pDevice) +{ + if (pDevice == NULL) + return; + + memset(&pDevice->gsPMKIDCandidate, 0, sizeof(SPMKIDCandidateEvent)); + + return; +} + +static bool +s_bCipherMatch ( + PKnownBSS pBSSNode, + NDIS_802_11_ENCRYPTION_STATUS EncStatus, + u8 * pbyCCSPK, + u8 * pbyCCSGK + ) +{ + u8 byMulticastCipher = KEY_CTL_INVALID; + u8 byCipherMask = 0x00; + int i; + + if (pBSSNode == NULL) + return false; + + // check cap. of BSS + if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && + (EncStatus == Ndis802_11Encryption1Enabled)) { + // default is WEP only + byMulticastCipher = KEY_CTL_WEP; + } + + if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && + (pBSSNode->bWPA2Valid == true) && + + ((EncStatus == Ndis802_11Encryption3Enabled) || + (EncStatus == Ndis802_11Encryption2Enabled))) { + //WPA2 + // check Group Key Cipher + if ((pBSSNode->byCSSGK == WLAN_11i_CSS_WEP40) || + (pBSSNode->byCSSGK == WLAN_11i_CSS_WEP104)) { + byMulticastCipher = KEY_CTL_WEP; + } else if (pBSSNode->byCSSGK == WLAN_11i_CSS_TKIP) { + byMulticastCipher = KEY_CTL_TKIP; + } else if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) { + byMulticastCipher = KEY_CTL_CCMP; + } else { + byMulticastCipher = KEY_CTL_INVALID; + } + + /* check Pairwise Key Cipher */ + for (i = 0; i < pBSSNode->wCSSPKCount; i++) { + if ((pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP40) || + (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP104)) { + /* this should not happen as defined 802.11i */ + byCipherMask |= 0x01; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_TKIP) { + byCipherMask |= 0x02; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_CCMP) { + byCipherMask |= 0x04; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_USE_GROUP) { + /* use group key only ignore all others */ + byCipherMask = 0; + i = pBSSNode->wCSSPKCount; + } + } + + } else if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && + (pBSSNode->bWPAValid == true) && + ((EncStatus == Ndis802_11Encryption2Enabled) || (EncStatus == Ndis802_11Encryption3Enabled))) { + //WPA + // check Group Key Cipher + if ((pBSSNode->byGKType == WPA_WEP40) || + (pBSSNode->byGKType == WPA_WEP104)) { + byMulticastCipher = KEY_CTL_WEP; + } else if (pBSSNode->byGKType == WPA_TKIP) { + byMulticastCipher = KEY_CTL_TKIP; + } else if (pBSSNode->byGKType == WPA_AESCCMP) { + byMulticastCipher = KEY_CTL_CCMP; + } else { + byMulticastCipher = KEY_CTL_INVALID; + } + + /* check Pairwise Key Cipher */ + for (i = 0; i < pBSSNode->wPKCount; i++) { + if (pBSSNode->abyPKType[i] == WPA_TKIP) { + byCipherMask |= 0x02; + } else if (pBSSNode->abyPKType[i] == WPA_AESCCMP) { + byCipherMask |= 0x04; + } else if (pBSSNode->abyPKType[i] == WPA_NONE) { + /* use group key only ignore all others */ + byCipherMask = 0; + i = pBSSNode->wPKCount; + } + } + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%d, %d, %d, %d, EncStatus:%d\n", + byMulticastCipher, byCipherMask, pBSSNode->bWPAValid, pBSSNode->bWPA2Valid, EncStatus); + + // mask our cap. with BSS + if (EncStatus == Ndis802_11Encryption1Enabled) { + + // For supporting Cisco migration mode, don't care pairwise key cipher + //if ((byMulticastCipher == KEY_CTL_WEP) && + // (byCipherMask == 0)) { + if ((byMulticastCipher == KEY_CTL_WEP) && + (byCipherMask == 0)) { + *pbyCCSGK = KEY_CTL_WEP; + *pbyCCSPK = KEY_CTL_NONE; + return true; + } else { + return false; + } + + } else if (EncStatus == Ndis802_11Encryption2Enabled) { + if ((byMulticastCipher == KEY_CTL_TKIP) && + (byCipherMask == 0)) { + *pbyCCSGK = KEY_CTL_TKIP; + *pbyCCSPK = KEY_CTL_NONE; + return true; + } else if ((byMulticastCipher == KEY_CTL_WEP) && + ((byCipherMask & 0x02) != 0)) { + *pbyCCSGK = KEY_CTL_WEP; + *pbyCCSPK = KEY_CTL_TKIP; + return true; + } else if ((byMulticastCipher == KEY_CTL_TKIP) && + ((byCipherMask & 0x02) != 0)) { + *pbyCCSGK = KEY_CTL_TKIP; + *pbyCCSPK = KEY_CTL_TKIP; + return true; + } else { + return false; + } + } else if (EncStatus == Ndis802_11Encryption3Enabled) { + if ((byMulticastCipher == KEY_CTL_CCMP) && + (byCipherMask == 0)) { + // When CCMP is enable, "Use group cipher suite" shall not be a valid option. + return false; + } else if ((byMulticastCipher == KEY_CTL_WEP) && + ((byCipherMask & 0x04) != 0)) { + *pbyCCSGK = KEY_CTL_WEP; + *pbyCCSPK = KEY_CTL_CCMP; + return true; + } else if ((byMulticastCipher == KEY_CTL_TKIP) && + ((byCipherMask & 0x04) != 0)) { + *pbyCCSGK = KEY_CTL_TKIP; + *pbyCCSPK = KEY_CTL_CCMP; + return true; + } else if ((byMulticastCipher == KEY_CTL_CCMP) && + ((byCipherMask & 0x04) != 0)) { + *pbyCCSGK = KEY_CTL_CCMP; + *pbyCCSPK = KEY_CTL_CCMP; + return true; + } else { + return false; + } + } + return true; +} + diff --git a/drivers/staging/vt6656/wmgr.h b/drivers/staging/vt6656/wmgr.h new file mode 100644 index 00000000..5424c7f8 --- /dev/null +++ b/drivers/staging/vt6656/wmgr.h @@ -0,0 +1,400 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: wmgr.h + * + * Purpose: + * + * Author: lyndon chen + * + * Date: Jan 2, 2003 + * + * Functions: + * + * Revision History: + * + */ + +#ifndef __WMGR_H__ +#define __WMGR_H__ + +#include "80211mgr.h" +#include "80211hdr.h" +#include "wcmd.h" +#include "bssdb.h" +#include "wpa2.h" +#include "card.h" + +// Scan time +#define PROBE_DELAY 100 // (us) +#define SWITCH_CHANNEL_DELAY 200 // (us) +#define WLAN_SCAN_MINITIME 25 // (ms) +#define WLAN_SCAN_MAXTIME 100 // (ms) +#define TRIVIAL_SYNC_DIFFERENCE 0 // (us) +#define DEFAULT_IBSS_BI 100 // (ms) + +#define WCMD_ACTIVE_SCAN_TIME 20 //(ms) +#define WCMD_PASSIVE_SCAN_TIME 100 //(ms) + +#define DEFAULT_MSDU_LIFETIME 512 // ms +#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 // 64us + +#define DEFAULT_MGN_LIFETIME 8 // ms +#define DEFAULT_MGN_LIFETIME_RES_64us 125 // 64us + +#define MAKE_BEACON_RESERVED 10 //(us) + +#define TIM_MULTICAST_MASK 0x01 +#define TIM_BITMAPOFFSET_MASK 0xFE +#define DEFAULT_DTIM_PERIOD 1 + +#define AP_LONG_RETRY_LIMIT 4 + +#define DEFAULT_IBSS_CHANNEL 6 //2.4G + +//mike define: make timer to expire after desired times +#define timer_expire(timer, next_tick) mod_timer(&timer, RUN_AT(next_tick)) + +typedef void (*TimerFunction)(unsigned long); + +//+++ NDIS related + +typedef u8 NDIS_802_11_MAC_ADDRESS[ETH_ALEN]; +typedef struct _NDIS_802_11_AI_REQFI +{ + u16 Capabilities; + u16 ListenInterval; + NDIS_802_11_MAC_ADDRESS CurrentAPAddress; +} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; + +typedef struct _NDIS_802_11_AI_RESFI +{ + u16 Capabilities; + u16 StatusCode; + u16 AssociationId; +} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; + +typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION +{ + u32 Length; + u16 AvailableRequestFixedIEs; + NDIS_802_11_AI_REQFI RequestFixedIEs; + u32 RequestIELength; + u32 OffsetRequestIEs; + u16 AvailableResponseFixedIEs; + NDIS_802_11_AI_RESFI ResponseFixedIEs; + u32 ResponseIELength; + u32 OffsetResponseIEs; +} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; + +typedef struct tagSAssocInfo { + NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; + u8 abyIEs[WLAN_BEACON_FR_MAXLEN+WLAN_BEACON_FR_MAXLEN]; + /* store ReqIEs set by OID_802_11_ASSOCIATION_INFORMATION */ + u32 RequestIELength; + u8 abyReqIEs[WLAN_BEACON_FR_MAXLEN]; +} SAssocInfo, *PSAssocInfo; + +typedef enum tagWMAC_AUTHENTICATION_MODE { + + WMAC_AUTH_OPEN, + WMAC_AUTH_SHAREKEY, + WMAC_AUTH_AUTO, + WMAC_AUTH_WPA, + WMAC_AUTH_WPAPSK, + WMAC_AUTH_WPANONE, + WMAC_AUTH_WPA2, + WMAC_AUTH_WPA2PSK, + WMAC_AUTH_MAX // Not a real mode, defined as upper bound +} WMAC_AUTHENTICATION_MODE, *PWMAC_AUTHENTICATION_MODE; + +// Pre-configured Mode (from XP) + +typedef enum tagWMAC_CONFIG_MODE { + WMAC_CONFIG_ESS_STA, + WMAC_CONFIG_IBSS_STA, + WMAC_CONFIG_AUTO, + WMAC_CONFIG_AP + +} WMAC_CONFIG_MODE, *PWMAC_CONFIG_MODE; + +typedef enum tagWMAC_SCAN_TYPE { + + WMAC_SCAN_ACTIVE, + WMAC_SCAN_PASSIVE, + WMAC_SCAN_HYBRID + +} WMAC_SCAN_TYPE, *PWMAC_SCAN_TYPE; + +typedef enum tagWMAC_SCAN_STATE { + + WMAC_NO_SCANNING, + WMAC_IS_SCANNING, + WMAC_IS_PROBEPENDING + +} WMAC_SCAN_STATE, *PWMAC_SCAN_STATE; + +// Notes: +// Basic Service Set state explained as following: +// WMAC_STATE_IDLE : no BSS is selected (Adhoc or Infra) +// WMAC_STATE_STARTED : no BSS is selected, start own IBSS (Adhoc only) +// WMAC_STATE_JOINTED : BSS is selected and synchronized (Adhoc or Infra) +// WMAC_STATE_AUTHPENDING : Authentication pending (Infra) +// WMAC_STATE_AUTH : Authenticated (Infra) +// WMAC_STATE_ASSOCPENDING : Association pending (Infra) +// WMAC_STATE_ASSOC : Associated (Infra) + +typedef enum tagWMAC_BSS_STATE { + + WMAC_STATE_IDLE, + WMAC_STATE_STARTED, + WMAC_STATE_JOINTED, + WMAC_STATE_AUTHPENDING, + WMAC_STATE_AUTH, + WMAC_STATE_ASSOCPENDING, + WMAC_STATE_ASSOC + +} WMAC_BSS_STATE, *PWMAC_BSS_STATE; + +// WMAC selected running mode +typedef enum tagWMAC_CURRENT_MODE { + + WMAC_MODE_STANDBY, + WMAC_MODE_ESS_STA, + WMAC_MODE_IBSS_STA, + WMAC_MODE_ESS_AP + +} WMAC_CURRENT_MODE, *PWMAC_CURRENT_MODE; + +typedef enum tagWMAC_POWER_MODE { + + WMAC_POWER_CAM, + WMAC_POWER_FAST, + WMAC_POWER_MAX + +} WMAC_POWER_MODE, *PWMAC_POWER_MODE; + +/* Tx Management Packet descriptor */ +struct vnt_tx_mgmt { + PUWLAN_80211HDR p80211Header; + u32 cbMPDULen; + u32 cbPayloadLen; +}; + +/* Rx Management Packet descriptor */ +struct vnt_rx_mgmt { + PUWLAN_80211HDR p80211Header; + u64 qwLocalTSF; + u32 cbMPDULen; + u32 cbPayloadLen; + u32 uRSSI; + u8 bySQ; + u8 byRxRate; + u8 byRxChannel; +}; + +struct vnt_manager { + void *pAdapter; + + /* MAC address */ + u8 abyMACAddr[WLAN_ADDR_LEN]; + + /* Configuration Mode */ + WMAC_CONFIG_MODE eConfigMode; /* MAC pre-configed mode */ + + CARD_PHY_TYPE eCurrentPHYMode; + + /* Operation state variables */ + WMAC_CURRENT_MODE eCurrMode; /* MAC current connection mode */ + WMAC_BSS_STATE eCurrState; /* MAC current BSS state */ + WMAC_BSS_STATE eLastState; /* MAC last BSS state */ + + PKnownBSS pCurrBSS; + u8 byCSSGK; + u8 byCSSPK; + + int bCurrBSSIDFilterOn; + + /* Current state vars */ + u32 uCurrChannel; + u8 abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + u8 abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + u8 abyCurrSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + u8 abyCurrBSSID[WLAN_BSSID_LEN]; + u16 wCurrCapInfo; + u16 wCurrAID; + u32 uRSSITrigger; + u16 wCurrATIMWindow; + u16 wCurrBeaconPeriod; + int bIsDS; + u8 byERPContext; + + CMD_STATE eCommandState; + u32 uScanChannel; + + /* Desire joinning BSS vars */ + u8 abyDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + u8 abyDesireBSSID[WLAN_BSSID_LEN]; + + /*restore BSS info for Ad-Hoc mode */ + u8 abyAdHocSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + + /* Adhoc or AP configuration vars */ + u16 wIBSSBeaconPeriod; + u16 wIBSSATIMWindow; + u32 uIBSSChannel; + u8 abyIBSSSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + u8 byAPBBType; + u8 abyWPAIE[MAX_WPA_IE_LEN]; + u16 wWPAIELen; + + u32 uAssocCount; + int bMoreData; + + /* Scan state vars */ + WMAC_SCAN_STATE eScanState; + WMAC_SCAN_TYPE eScanType; + u32 uScanStartCh; + u32 uScanEndCh; + u16 wScanSteps; + u32 uScanBSSType; + /* Desire scannig vars */ + u8 abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + u8 abyScanBSSID[WLAN_BSSID_LEN]; + + /* Privacy */ + WMAC_AUTHENTICATION_MODE eAuthenMode; + int bShareKeyAlgorithm; + u8 abyChallenge[WLAN_CHALLENGE_LEN]; + int bPrivacyInvoked; + + /* Received beacon state vars */ + int bInTIM; + int bMulticastTIM; + u8 byDTIMCount; + u8 byDTIMPeriod; + + /* Power saving state vars */ + WMAC_POWER_MODE ePSMode; + u16 wListenInterval; + u16 wCountToWakeUp; + int bInTIMWake; + u8 *pbyPSPacketPool; + u8 byPSPacketPool[sizeof(struct vnt_tx_mgmt) + + WLAN_NULLDATA_FR_MAXLEN]; + int bRxBeaconInTBTTWake; + u8 abyPSTxMap[MAX_NODE_NUM + 1]; + + /* management command related */ + u32 uCmdBusy; + u32 uCmdHostAPBusy; + + /* management packet pool */ + u8 *pbyMgmtPacketPool; + u8 byMgmtPacketPool[sizeof(struct vnt_tx_mgmt) + + WLAN_A3FR_MAXLEN]; + + /* One second callback timer */ + struct timer_list sTimerSecondCallback; + + /* Temporarily Rx Mgmt Packet Descriptor */ + struct vnt_rx_mgmt sRxPacket; + + /* link list of known bss's (scan results) */ + KnownBSS sBSSList[MAX_BSS_NUM]; + /* link list of same bss's */ + KnownBSS pSameBSS[6]; + int Cisco_cckm; + u8 Roam_dbm; + + /* table list of known node */ + /* sNodeDBList[0] is reserved for AP under Infra mode */ + /* sNodeDBList[0] is reserved for Multicast under adhoc/AP mode */ + KnownNodeDB sNodeDBTable[MAX_NODE_NUM + 1]; + + /* WPA2 PMKID Cache */ + SPMKIDCache gsPMKIDCache; + int bRoaming; + + /* associate info */ + SAssocInfo sAssocInfo; + + /* for 802.11h */ + int b11hEnable; + int bSwitchChannel; + u8 byNewChannel; + PWLAN_IE_MEASURE_REP pCurrMeasureEIDRep; + u32 uLengthOfRepEIDs; + u8 abyCurrentMSRReq[sizeof(struct vnt_tx_mgmt) + + WLAN_A3FR_MAXLEN]; + u8 abyCurrentMSRRep[sizeof(struct vnt_tx_mgmt) + + WLAN_A3FR_MAXLEN]; + u8 abyIECountry[WLAN_A3FR_MAXLEN]; + u8 abyIBSSDFSOwner[6]; + u8 byIBSSDFSRecovery; + + struct sk_buff skb; + +}; + +void vMgrObjectInit(struct vnt_private *pDevice); + +void vMgrAssocBeginSta(struct vnt_private *pDevice, + struct vnt_manager *, PCMD_STATUS pStatus); + +void vMgrReAssocBeginSta(struct vnt_private *pDevice, + struct vnt_manager *, PCMD_STATUS pStatus); + +void vMgrDisassocBeginSta(struct vnt_private *pDevice, + struct vnt_manager *, u8 *abyDestAddress, u16 wReason, + PCMD_STATUS pStatus); + +void vMgrAuthenBeginSta(struct vnt_private *pDevice, + struct vnt_manager *, PCMD_STATUS pStatus); + +void vMgrCreateOwnIBSS(struct vnt_private *pDevice, + PCMD_STATUS pStatus); + +void vMgrJoinBSSBegin(struct vnt_private *pDevice, + PCMD_STATUS pStatus); + +void vMgrRxManagePacket(struct vnt_private *pDevice, + struct vnt_manager *, struct vnt_rx_mgmt *); + +/* +void +vMgrScanBegin( + void *hDeviceContext, + PCMD_STATUS pStatus + ); +*/ + +void vMgrDeAuthenBeginSta(struct vnt_private *pDevice, + struct vnt_manager *, u8 *abyDestAddress, u16 wReason, + PCMD_STATUS pStatus); + +int bMgrPrepareBeaconToSend(struct vnt_private *pDevice, + struct vnt_manager *); + +int bAdd_PMKID_Candidate(struct vnt_private *pDevice, + u8 *pbyBSSID, PSRSNCapObject psRSNCapObj); + +void vFlush_PMKID_Candidate(struct vnt_private *pDevice); + +#endif /* __WMGR_H__ */ diff --git a/drivers/staging/vt6656/wpa.c b/drivers/staging/vt6656/wpa.c new file mode 100644 index 00000000..01db4e71 --- /dev/null +++ b/drivers/staging/vt6656/wpa.c @@ -0,0 +1,314 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: wpa.c + * + * Purpose: Handles the Basic Service Set & Node Database functions + * + * Functions: + * WPA_ParseRSN - Parse RSN IE. + * + * Revision History: + * + * Author: Kyle Hsu + * + * Date: July 14, 2003 + * + */ + +#include "tmacro.h" +#include "tether.h" +#include "device.h" +#include "80211hdr.h" +#include "bssdb.h" +#include "wmgr.h" +#include "wpa.h" +#include "80211mgr.h" + +static int msglevel =MSG_LEVEL_INFO; + +const u8 abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 }; +const u8 abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 }; +const u8 abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 }; +const u8 abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 }; +const u8 abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 }; +const u8 abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 }; + +/*+ + * + * Description: + * Clear RSN information in BSSList. + * + * Parameters: + * In: + * pBSSList - BSS list. + * Out: + * none + * + * Return Value: none. + * +-*/ + +void +WPA_ClearRSN( + PKnownBSS pBSSList + ) +{ + int ii; + pBSSList->byGKType = WPA_TKIP; + for (ii=0; ii < 4; ii ++) + pBSSList->abyPKType[ii] = WPA_TKIP; + pBSSList->wPKCount = 0; + for (ii=0; ii < 4; ii ++) + pBSSList->abyAuthType[ii] = WPA_AUTH_IEEE802_1X; + pBSSList->wAuthCount = 0; + pBSSList->byDefaultK_as_PK = 0; + pBSSList->byReplayIdx = 0; + pBSSList->sRSNCapObj.bRSNCapExist = false; + pBSSList->sRSNCapObj.wRSNCap = 0; + pBSSList->bWPAValid = false; +} + +/*+ + * + * Description: + * Parse RSN IE. + * + * Parameters: + * In: + * pBSSList - BSS list. + * pRSN - Pointer to the RSN IE. + * Out: + * none + * + * Return Value: none. + * +-*/ +void +WPA_ParseRSN( + PKnownBSS pBSSList, + PWLAN_IE_RSN_EXT pRSN + ) +{ + PWLAN_IE_RSN_AUTH pIE_RSN_Auth = NULL; + int i, j, m, n = 0; + u8 * pbyCaps; + + WPA_ClearRSN(pBSSList); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA_ParseRSN: [%d]\n", pRSN->len); + + // information element header makes sense + if ((pRSN->len >= 6) // oui1(4)+ver(2) + && (pRSN->byElementID == WLAN_EID_RSN_WPA) && !memcmp(pRSN->abyOUI, abyOUI01, 4) + && (pRSN->wVersion == 1)) { + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Legal RSN\n"); + // update each variable if pRSN is long enough to contain the variable + if (pRSN->len >= 10) //oui1(4)+ver(2)+GKSuite(4) + { + if ( !memcmp(pRSN->abyMulticast, abyOUI01, 4)) + pBSSList->byGKType = WPA_WEP40; + else if ( !memcmp(pRSN->abyMulticast, abyOUI02, 4)) + pBSSList->byGKType = WPA_TKIP; + else if ( !memcmp(pRSN->abyMulticast, abyOUI03, 4)) + pBSSList->byGKType = WPA_AESWRAP; + else if ( !memcmp(pRSN->abyMulticast, abyOUI04, 4)) + pBSSList->byGKType = WPA_AESCCMP; + else if ( !memcmp(pRSN->abyMulticast, abyOUI05, 4)) + pBSSList->byGKType = WPA_WEP104; + else + // any vendor checks here + pBSSList->byGKType = WPA_NONE; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byGKType: %x\n", pBSSList->byGKType); + } + + if (pRSN->len >= 12) //oui1(4)+ver(2)+GKS(4)+PKSCnt(2) + { + j = 0; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType)); + for (i = 0; (i < pRSN->wPKCount) && + (j < ARRAY_SIZE(pBSSList->abyPKType)); i++) { + if(pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i) + if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4)) + pBSSList->abyPKType[j++] = WPA_NONE; + else if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI02, 4)) + pBSSList->abyPKType[j++] = WPA_TKIP; + else if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI03, 4)) + pBSSList->abyPKType[j++] = WPA_AESWRAP; + else if ( !memcmp(pRSN->PKSList[i].abyOUI, abyOUI04, 4)) + pBSSList->abyPKType[j++] = WPA_AESCCMP; + else + // any vendor checks here + ; + } + else + break; + //DBG_PRN_GRP14(("abyPKType[%d]: %X\n", j-1, pBSSList->abyPKType[j-1])); + } //for + pBSSList->wPKCount = (u16)j; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d\n", pBSSList->wPKCount); + } + + m = pRSN->wPKCount; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"m: %d\n", m); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"14+m*4: %d\n", 14+m*4); + + if (pRSN->len >= 14+m*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2) + // overlay IE_RSN_Auth structure into correct place + pIE_RSN_Auth = (PWLAN_IE_RSN_AUTH) pRSN->PKSList[m].abyOUI; + j = 0; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n", + pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType)); + for (i = 0; (i < pIE_RSN_Auth->wAuthCount) && + (j < ARRAY_SIZE(pBSSList->abyAuthType)); i++) { + if(pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i) + if ( !memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI01, 4)) + pBSSList->abyAuthType[j++] = WPA_AUTH_IEEE802_1X; + else if ( !memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI02, 4)) + pBSSList->abyAuthType[j++] = WPA_AUTH_PSK; + else + // any vendor checks here + ; + } + else + break; + //DBG_PRN_GRP14(("abyAuthType[%d]: %X\n", j-1, pBSSList->abyAuthType[j-1])); + } + if(j > 0) + pBSSList->wAuthCount = (u16)j; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d\n", pBSSList->wAuthCount); + } + + if (pIE_RSN_Auth != NULL) { + + n = pIE_RSN_Auth->wAuthCount; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"n: %d\n", n); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"14+4+(m+n)*4: %d\n", 14+4+(m+n)*4); + + if(pRSN->len+2 >= 14+4+(m+n)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*n)+Cap(2) + pbyCaps = (u8 *)pIE_RSN_Auth->AuthKSList[n].abyOUI; + pBSSList->byDefaultK_as_PK = (*pbyCaps) & WPA_GROUPFLAG; + pBSSList->byReplayIdx = 2 << ((*pbyCaps >> WPA_REPLAYBITSSHIFT) & WPA_REPLAYBITS); + pBSSList->sRSNCapObj.bRSNCapExist = true; + pBSSList->sRSNCapObj.wRSNCap = *(u16 *)pbyCaps; + //DBG_PRN_GRP14(("pbyCaps: %X\n", *pbyCaps)); + //DBG_PRN_GRP14(("byDefaultK_as_PK: %X\n", pBSSList->byDefaultK_as_PK)); + //DBG_PRN_GRP14(("byReplayIdx: %X\n", pBSSList->byReplayIdx)); + } + } + pBSSList->bWPAValid = true; + } +} + +/*+ + * + * Description: + * Search RSN information in BSSList. + * + * Parameters: + * In: + * byCmd - Search type + * byEncrypt- Encrypt Type + * pBSSList - BSS list + * Out: + * none + * + * Return Value: none. + * +-*/ +bool +WPA_SearchRSN( + u8 byCmd, + u8 byEncrypt, + PKnownBSS pBSSList + ) +{ + int ii; + u8 byPKType = WPA_NONE; + + if (pBSSList->bWPAValid == false) + return false; + + switch(byCmd) { + case 0: + + if (byEncrypt != pBSSList->byGKType) + return false; + + if (pBSSList->wPKCount > 0) { + for (ii = 0; ii < pBSSList->wPKCount; ii ++) { + if (pBSSList->abyPKType[ii] == WPA_AESCCMP) + byPKType = WPA_AESCCMP; + else if ((pBSSList->abyPKType[ii] == WPA_TKIP) && (byPKType != WPA_AESCCMP)) + byPKType = WPA_TKIP; + else if ((pBSSList->abyPKType[ii] == WPA_WEP40) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP)) + byPKType = WPA_WEP40; + else if ((pBSSList->abyPKType[ii] == WPA_WEP104) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP)) + byPKType = WPA_WEP104; + } + if (byEncrypt != byPKType) + return false; + } + return true; +// if (pBSSList->wAuthCount > 0) +// for (ii=0; ii < pBSSList->wAuthCount; ii ++) +// if (byAuth == pBSSList->abyAuthType[ii]) +// break; + break; + + default: + break; + } + return false; +} + +/*+ + * + * Description: + * Check if RSN IE makes sense. + * + * Parameters: + * In: + * pRSN - Pointer to the RSN IE. + * Out: + * none + * + * Return Value: none. + * +-*/ +bool +WPAb_Is_RSN( + PWLAN_IE_RSN_EXT pRSN + ) +{ + if (pRSN == NULL) + return false; + + if ((pRSN->len >= 6) && // oui1(4)+ver(2) + (pRSN->byElementID == WLAN_EID_RSN_WPA) && !memcmp(pRSN->abyOUI, abyOUI01, 4) && + (pRSN->wVersion == 1)) { + return true; + } + else + return false; +} + diff --git a/drivers/staging/vt6656/wpa.h b/drivers/staging/vt6656/wpa.h new file mode 100644 index 00000000..2a724c06 --- /dev/null +++ b/drivers/staging/vt6656/wpa.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: wpa.h + * + * Purpose: Defines the macros, types, and functions for dealing + * with WPA informations. + * + * Author: Kyle Hsu + * + * Date: Jul 14, 2003 + * + */ + +#ifndef __WPA_H__ +#define __WPA_H__ + +#include "80211hdr.h" + +#define WPA_NONE 0 +#define WPA_WEP40 1 +#define WPA_TKIP 2 +#define WPA_AESWRAP 3 +#define WPA_AESCCMP 4 +#define WPA_WEP104 5 +#define WPA_AUTH_IEEE802_1X 1 +#define WPA_AUTH_PSK 2 + +#define WPA_GROUPFLAG 0x02 +#define WPA_REPLAYBITSSHIFT 2 +#define WPA_REPLAYBITS 0x03 + +void +WPA_ClearRSN( + PKnownBSS pBSSList + ); + +void +WPA_ParseRSN( + PKnownBSS pBSSList, + PWLAN_IE_RSN_EXT pRSN + ); + +bool +WPA_SearchRSN( + u8 byCmd, + u8 byEncrypt, + PKnownBSS pBSSList + ); + +bool +WPAb_Is_RSN( + PWLAN_IE_RSN_EXT pRSN + ); + +#endif /* __WPA_H__ */ diff --git a/drivers/staging/vt6656/wpa2.c b/drivers/staging/vt6656/wpa2.c new file mode 100644 index 00000000..aa221618 --- /dev/null +++ b/drivers/staging/vt6656/wpa2.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: wpa2.c + * + * Purpose: Handles the Basic Service Set & Node Database functions + * + * Functions: + * + * Revision History: + * + * Author: Yiching Chen + * + * Date: Oct. 4, 2004 + * + */ + +#include "device.h" +#include "wpa2.h" + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +const u8 abyOUIGK[4] = { 0x00, 0x0F, 0xAC, 0x00 }; +const u8 abyOUIWEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +const u8 abyOUIWEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; +const u8 abyOUITKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; +const u8 abyOUICCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; + +const u8 abyOUI8021X[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +const u8 abyOUIPSK[4] = { 0x00, 0x0F, 0xAC, 0x02 }; + +/*+ + * + * Description: + * Clear RSN information in BSSList. + * + * Parameters: + * In: + * pBSSNode - BSS list. + * Out: + * none + * + * Return Value: none. + * +-*/ +void +WPA2_ClearRSN ( + PKnownBSS pBSSNode + ) +{ + int ii; + + pBSSNode->bWPA2Valid = false; + + pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP; + for (ii=0; ii < 4; ii ++) + pBSSNode->abyCSSPK[ii] = WLAN_11i_CSS_CCMP; + pBSSNode->wCSSPKCount = 1; + for (ii=0; ii < 4; ii ++) + pBSSNode->abyAKMSSAuthType[ii] = WLAN_11i_AKMSS_802_1X; + pBSSNode->wAKMSSAuthCount = 1; + pBSSNode->sRSNCapObj.bRSNCapExist = false; + pBSSNode->sRSNCapObj.wRSNCap = 0; +} + +/*+ + * + * Description: + * Parse RSN IE. + * + * Parameters: + * In: + * pBSSNode - BSS list. + * pRSN - Pointer to the RSN IE. + * Out: + * none + * + * Return Value: none. + * +-*/ +void +WPA2vParseRSN ( + PKnownBSS pBSSNode, + PWLAN_IE_RSN pRSN + ) +{ + int i, j; + u16 m = 0, n = 0; + u8 * pbyOUI; + bool bUseGK = false; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA2_ParseRSN: [%d]\n", pRSN->len); + + WPA2_ClearRSN(pBSSNode); + + if (pRSN->len == 2) { // ver(2) + if ((pRSN->byElementID == WLAN_EID_RSN) && (pRSN->wVersion == 1)) { + pBSSNode->bWPA2Valid = true; + } + return; + } + + if (pRSN->len < 6) { // ver(2) + GK(4) + // invalid CSS, P802.11i/D10.0, p31 + return; + } + + // information element header makes sense + if ((pRSN->byElementID == WLAN_EID_RSN) && + (pRSN->wVersion == 1)) { + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Legal 802.11i RSN\n"); + + pbyOUI = &(pRSN->abyRSN[0]); + if ( !memcmp(pbyOUI, abyOUIWEP40, 4)) + pBSSNode->byCSSGK = WLAN_11i_CSS_WEP40; + else if ( !memcmp(pbyOUI, abyOUITKIP, 4)) + pBSSNode->byCSSGK = WLAN_11i_CSS_TKIP; + else if ( !memcmp(pbyOUI, abyOUICCMP, 4)) + pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP; + else if ( !memcmp(pbyOUI, abyOUIWEP104, 4)) + pBSSNode->byCSSGK = WLAN_11i_CSS_WEP104; + else if ( !memcmp(pbyOUI, abyOUIGK, 4)) { + // invalid CSS, P802.11i/D10.0, p32 + return; + } else + // any vendor checks here + pBSSNode->byCSSGK = WLAN_11i_CSS_UNKNOWN; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"802.11i CSS: %X\n", pBSSNode->byCSSGK); + + if (pRSN->len == 6) { + pBSSNode->bWPA2Valid = true; + return; + } + + if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2) + pBSSNode->wCSSPKCount = *((u16 *) &(pRSN->abyRSN[4])); + j = 0; + pbyOUI = &(pRSN->abyRSN[6]); + + for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(u8)); i++) { + + if (pRSN->len >= 8+i*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*i) + if ( !memcmp(pbyOUI, abyOUIGK, 4)) { + pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP; + bUseGK = true; + } else if ( !memcmp(pbyOUI, abyOUIWEP40, 4)) { + // Invalid CSS, continue parsing + } else if ( !memcmp(pbyOUI, abyOUITKIP, 4)) { + if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP) + pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP; + else + ; // Invalid CSS, continue parsing + } else if ( !memcmp(pbyOUI, abyOUICCMP, 4)) { + pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP; + } else if ( !memcmp(pbyOUI, abyOUIWEP104, 4)) { + // Invalid CSS, continue parsing + } else { + // any vendor checks here + pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_UNKNOWN; + } + pbyOUI += 4; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyCSSPK[%d]: %X\n", j-1, pBSSNode->abyCSSPK[j-1]); + } else + break; + } //for + + if (bUseGK == true) { + if (j != 1) { + // invalid CSS, This should be only PK CSS. + return; + } + if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) { + // invalid CSS, If CCMP is enable , PK can't be CSSGK. + return; + } + } + if ((pBSSNode->wCSSPKCount != 0) && (j == 0)) { + // invalid CSS, No valid PK. + return; + } + pBSSNode->wCSSPKCount = (u16)j; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wCSSPKCount: %d\n", pBSSNode->wCSSPKCount); + } + + m = *((u16 *) &(pRSN->abyRSN[4])); + + if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2) + pBSSNode->wAKMSSAuthCount = *((u16 *) &(pRSN->abyRSN[6+4*m])); + j = 0; + pbyOUI = &(pRSN->abyRSN[8+4*m]); + for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(u8)); i++) { + if (pRSN->len >= 10+(m+i)*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSS(2)+AKS(4*i) + if ( !memcmp(pbyOUI, abyOUI8021X, 4)) + pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_802_1X; + else if ( !memcmp(pbyOUI, abyOUIPSK, 4)) + pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_PSK; + else + // any vendor checks here + pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_UNKNOWN; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyAKMSSAuthType[%d]: %X\n", j-1, pBSSNode->abyAKMSSAuthType[j-1]); + } else + break; + } + pBSSNode->wAKMSSAuthCount = (u16)j; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount); + + n = *((u16 *) &(pRSN->abyRSN[6+4*m])); + if (pRSN->len >= 12+4*m+4*n) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSSCnt(2)+AKMSS(4*n)+Cap(2) + pBSSNode->sRSNCapObj.bRSNCapExist = true; + pBSSNode->sRSNCapObj.wRSNCap = *((u16 *) &(pRSN->abyRSN[8+4*m+4*n])); + } + } + //ignore PMKID lists bcs only (Re)Assocrequest has this field + pBSSNode->bWPA2Valid = true; + } +} diff --git a/drivers/staging/vt6656/wpa2.h b/drivers/staging/vt6656/wpa2.h new file mode 100644 index 00000000..dc505ce7 --- /dev/null +++ b/drivers/staging/vt6656/wpa2.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: wpa2.h + * + * Purpose: Defines the macros, types, and functions for dealing + * with WPA2 informations. + * + * Author: Yiching Chen + * + * Date: Oct. 4, 2004 + * + */ + +#ifndef __WPA2_H__ +#define __WPA2_H__ + +#include "80211mgr.h" +#include "80211hdr.h" +#include "bssdb.h" + +#define MAX_PMKID_CACHE 16 + +typedef struct tagsPMKIDInfo { + u8 abyBSSID[6]; + u8 abyPMKID[16]; +} PMKIDInfo, *PPMKIDInfo; + +typedef struct tagSPMKIDCache { + u32 BSSIDInfoCount; + PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; +} SPMKIDCache, *PSPMKIDCache; + +void WPA2_ClearRSN(PKnownBSS pBSSNode); +void WPA2vParseRSN(PKnownBSS pBSSNode, PWLAN_IE_RSN pRSN); + +#endif /* __WPA2_H__ */ diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c new file mode 100644 index 00000000..9f1b413c --- /dev/null +++ b/drivers/staging/vt6656/wpactl.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: wpactl.c + * + * Purpose: handle wpa supplicant ioctl input/out functions + * + * Author: Lyndon Chen + * + * Date: July 28, 2006 + * + * Functions: + * + * Revision History: + * + */ + +#include "wpactl.h" +#include "key.h" +#include "mac.h" +#include "device.h" +#include "wmgr.h" +#include "iocmd.h" +#include "iowpa.h" +#include "control.h" +#include "rndis.h" +#include "rf.h" + +static int msglevel = MSG_LEVEL_INFO; + +/* + * Description: + * Set WPA algorithm & keys + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +int wpa_set_keys(struct vnt_private *pDevice, void *ctx) +{ + struct viawget_wpa_param *param = ctx; + struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; + u32 dwKeyIndex = 0; + u8 abyKey[MAX_KEY_LEN]; + u8 abySeq[MAX_KEY_LEN]; + u64 KeyRSC; + u8 byKeyDecMode = KEY_CTL_WEP; + int ret = 0; + int uu; + int ii; + + if (param->u.wpa_key.alg_name > WPA_ALG_CCMP) + return -EINVAL; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", + param->u.wpa_key.alg_name); + if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + pDevice->bEncryptionEnable = false; + pDevice->byKeyIndex = 0; + pDevice->bTransmitKey = false; + for (uu=0; uu<MAX_KEY_TABLE; uu++) { + MACvDisableKeyEntry(pDevice, uu); + } + return ret; + } + + if (param->u.wpa_key.key && param->u.wpa_key.key_len > sizeof(abyKey)) + return -EINVAL; + + memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); + + dwKeyIndex = (u32)(param->u.wpa_key.key_index); + + if (param->u.wpa_key.alg_name == WPA_ALG_WEP) { + if (dwKeyIndex > 3) { + return -EINVAL; + } else { + if (param->u.wpa_key.set_tx) { + pDevice->byKeyIndex = (u8)dwKeyIndex; + pDevice->bTransmitKey = true; + dwKeyIndex |= (1 << 31); + } + KeybSetDefaultKey( pDevice, + &(pDevice->sKey), + dwKeyIndex & ~(BIT30 | USE_KEYRSC), + param->u.wpa_key.key_len, + NULL, + abyKey, + KEY_CTL_WEP + ); + + } + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + pDevice->bEncryptionEnable = true; + return ret; + } + + if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq)) + return -EINVAL; + + memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); + + if (param->u.wpa_key.seq_len > 0) { + for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) { + if (ii < 4) + KeyRSC |= (abySeq[ii] << (ii * 8)); + else + KeyRSC |= (abySeq[ii] << ((ii-4) * 8)); + } + dwKeyIndex |= 1 << 29; + } + + if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n"); + return -EINVAL; + } + + if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + } + + if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + } + + if (param->u.wpa_key.set_tx) + dwKeyIndex |= (1 << 31); + + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) + byKeyDecMode = KEY_CTL_CCMP; + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) + byKeyDecMode = KEY_CTL_TKIP; + else + byKeyDecMode = KEY_CTL_WEP; + + // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + if (param->u.wpa_key.key_len == MAX_KEY_LEN) + byKeyDecMode = KEY_CTL_TKIP; + else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + } + + // Check TKIP key length + if ((byKeyDecMode == KEY_CTL_TKIP) && + (param->u.wpa_key.key_len != MAX_KEY_LEN)) { + // TKIP Key must be 256 bits + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - TKIP Key must be 256 bits!\n"); + return -EINVAL; + } + // Check AES key length + if ((byKeyDecMode == KEY_CTL_CCMP) && + (param->u.wpa_key.key_len != AES_KEY_LEN)) { + // AES Key must be 128 bits + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - AES Key must be 128 bits\n"); + return -EINVAL; + } + + if (is_broadcast_ether_addr(¶m->addr[0]) || (param->addr == NULL)) { + /* if broadcast, set the key as every key entry's group key */ + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); + + if ((KeybSetAllGroupKey(pDevice, &(pDevice->sKey), dwKeyIndex, + param->u.wpa_key.key_len, + &KeyRSC, + (u8 *)abyKey, + byKeyDecMode + ) == true) && + (KeybSetDefaultKey(pDevice, + &(pDevice->sKey), + dwKeyIndex, + param->u.wpa_key.key_len, + &KeyRSC, + (u8 *)abyKey, + byKeyDecMode + ) == true) ) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); + } else { + return -EINVAL; + } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); + // BSSID not 0xffffffffffff + // Pairwise Key can't be WEP + if (byKeyDecMode == KEY_CTL_WEP) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); + return -EINVAL; + } + dwKeyIndex |= (1 << 30); // set pairwise key + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n")); + return -EINVAL; + } + if (KeybSetKey(pDevice, &(pDevice->sKey), ¶m->addr[0], + dwKeyIndex, param->u.wpa_key.key_len, + &KeyRSC, (u8 *)abyKey, byKeyDecMode + ) == true) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); + } else { + // Key Table Full + if (!compare_ether_addr(¶m->addr[0], pDevice->abyBSSID)) { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); + return -EINVAL; + } else { + // Save Key and configure just before associate/reassociate to BSSID + // we do not implement now + return -EINVAL; + } + } + } // BSSID not 0xffffffffffff + if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { + pDevice->byKeyIndex = (u8)param->u.wpa_key.key_index; + pDevice->bTransmitKey = true; + } + pDevice->bEncryptionEnable = true; + + return ret; +} + diff --git a/drivers/staging/vt6656/wpactl.h b/drivers/staging/vt6656/wpactl.h new file mode 100644 index 00000000..e032a1b9 --- /dev/null +++ b/drivers/staging/vt6656/wpactl.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: wpactl.h + * + * Purpose: + * + * Author: Lyndon Chen + * + * Date: March 1, 2005 + * + */ + +#ifndef __WPACTL_H__ +#define __WPACTL_H__ + +#include "device.h" +#include "iowpa.h" + +//WPA related + +typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; + +#define AUTH_ALG_OPEN_SYSTEM 0x01 +#define AUTH_ALG_SHARED_KEY 0x02 +#define AUTH_ALG_LEAP 0x04 + +typedef unsigned long long NDIS_802_11_KEY_RSC; + +int wpa_set_keys(struct vnt_private *, void *ctx); + +#endif /* __WPACL_H__ */ |
