diff options
author | Forest Bond <forest@alittletooquiet.net> | 2009-04-25 10:30:44 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-19 11:00:51 -0700 |
commit | 5449c685a4b39534f18869a93896370224463715 (patch) | |
tree | dfe5ddb2fef11dc59ccb9720c086583b7d62c6a8 /drivers/staging/vt6655/wpactl.c | |
parent | be2e10710b1c330d25e66724ef10b8aabdae4a83 (diff) | |
download | op-kernel-dev-5449c685a4b39534f18869a93896370224463715.zip op-kernel-dev-5449c685a4b39534f18869a93896370224463715.tar.gz |
Staging: Add pristine upstream vt6655 driver sources
Add pristine upstream vt6655 driver sources to drivers/staging/vt6655. These
files were literally copied from the driver directory in the upstream source
archive, available here:
http://www.viaarena.com/Driver/vt6655_linux_src_v1.19.12_x86.zip
Signed-off-by: Forest Bond <forest@alittletooquiet.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/vt6655/wpactl.c')
-rw-r--r-- | drivers/staging/vt6655/wpactl.c | 1014 |
1 files changed, 1014 insertions, 0 deletions
diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c new file mode 100644 index 0000000..ee7109d --- /dev/null +++ b/drivers/staging/vt6655/wpactl.c @@ -0,0 +1,1014 @@ +/* + * 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: Oct. 20, 2003 + * + * Functions: + * + * Revision History: + * + */ + + +#if !defined(__WPACTL_H__) +#include "wpactl.h" +#endif +#if !defined(__KEY_H__) +#include "key.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__IOCMD_H__) +#include "iocmd.h" +#endif +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif +//2008-0717-05, <Add> by James +#if !defined(__RF_H__) +#include "rf.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +#define VIAWGET_WPA_MAX_BUF_SIZE 1024 + + + +static const int frequency_list[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +/*--------------------- Static Functions --------------------------*/ + + + + +/*--------------------- Export Variables --------------------------*/ + + +static void wpadev_setup(struct net_device *dev) +{ + dev->type = ARPHRD_IEEE80211; + dev->hard_header_len = ETH_HLEN; + dev->mtu = 2048; + dev->addr_len = ETH_ALEN; + dev->tx_queue_len = 1000; + + memset(dev->broadcast,0xFF, ETH_ALEN); + + dev->flags = IFF_BROADCAST|IFF_MULTICAST; +} + + + +/* + * Description: + * register netdev for wpa supplicant deamon + * + * Parameters: + * In: + * pDevice - + * enable - + * Out: + * + * Return Value: + * + */ + +static int wpa_init_wpadev(PSDevice pDevice) +{ + struct net_device *dev = pDevice->dev; + int ret=0; + + pDevice->wpadev = alloc_netdev(0, "vntwpa", wpadev_setup); + if (pDevice->wpadev == NULL) + return -ENOMEM; + + pDevice->wpadev->priv = pDevice; + memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, U_ETHER_ADDR_LEN); + pDevice->wpadev->base_addr = dev->base_addr; + pDevice->wpadev->irq = dev->irq; + pDevice->wpadev->mem_start = dev->mem_start; + pDevice->wpadev->mem_end = dev->mem_end; + ret = register_netdev(pDevice->wpadev); + if (ret) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n", + dev->name); + free_netdev(pDevice->wpadev); + return -1; + } + + if (pDevice->skb == NULL) { + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + if (pDevice->skb == NULL) + return -ENOMEM; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n", + dev->name, pDevice->wpadev->name); + + return 0; +} + + +/* + * Description: + * unregister net_device (wpadev) + * + * Parameters: + * In: + * pDevice - + * Out: + * + * Return Value: + * + */ + +static int wpa_release_wpadev(PSDevice pDevice) +{ + + if (pDevice->skb) { + dev_kfree_skb(pDevice->skb); + pDevice->skb = NULL; + } + + if (pDevice->wpadev) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", + pDevice->dev->name, pDevice->wpadev->name); + unregister_netdev(pDevice->wpadev); + free_netdev(pDevice->wpadev); + pDevice->wpadev = NULL; + } + + return 0; +} + + + + + +/* + * Description: + * Set enable/disable dev for wpa supplicant deamon + * + * Parameters: + * In: + * pDevice - + * val - + * Out: + * + * Return Value: + * + */ + +int wpa_set_wpadev(PSDevice pDevice, int val) +{ + + + if (val) + return wpa_init_wpadev(pDevice); + else + return wpa_release_wpadev(pDevice); +} + + +/* + * Description: + * Set WPA algorithm & keys + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +int wpa_set_keys(PSDevice pDevice, void *ctx, BOOL fcpfkernel) +{ + struct viawget_wpa_param *param=ctx; + PSMgmtObject pMgmt = pDevice->pMgmt; + DWORD dwKeyIndex = 0; + BYTE abyKey[MAX_KEY_LEN]; + BYTE abySeq[MAX_KEY_LEN]; + QWORD KeyRSC; +// NDIS_802_11_KEY_RSC KeyRSC; + BYTE byKeyDecMode = KEY_CTL_WEP; + int ret = 0; + int uu, ii; + + + if (param->u.wpa_key.alg_name > WPA_ALG_CCMP) + return -EINVAL; + + DEVICE_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; + KeyvRemoveAllWEPKey(&(pDevice->sKey), pDevice->PortOffset); + for (uu=0; uu<MAX_KEY_TABLE; uu++) { + MACvDisableKeyEntry(pDevice->PortOffset, uu); + } + return ret; + } + + //spin_unlock_irq(&pDevice->lock); + if(param->u.wpa_key.key && fcpfkernel) { + memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); + } + else { + spin_unlock_irq(&pDevice->lock); + if (param->u.wpa_key.key && + copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)){ + spin_lock_irq(&pDevice->lock); + return -EINVAL; + } +spin_lock_irq(&pDevice->lock); + } + + dwKeyIndex = (DWORD)(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 = (BYTE)dwKeyIndex; + pDevice->bTransmitKey = TRUE; + dwKeyIndex |= (1 << 31); + } + KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex & ~(BIT30 | USE_KEYRSC), + param->u.wpa_key.key_len, + NULL, + abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID); + + } + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + pDevice->bEncryptionEnable = TRUE; + return ret; + } + + //spin_unlock_irq(&pDevice->lock); + if(param->u.wpa_key.seq && fcpfkernel) { + memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); + } + else { + spin_unlock_irq(&pDevice->lock); + if (param->u.wpa_key.seq && + copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)){ + + spin_lock_irq(&pDevice->lock); + return -EINVAL; + } +spin_lock_irq(&pDevice->lock); +} + + if (param->u.wpa_key.seq_len > 0) { + for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) { + if (ii < 4) + LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8)); + else + HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8)); + //KeyRSC |= (abySeq[ii] << (ii * 8)); + } + dwKeyIndex |= 1 << 29; + } + + if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { + DEVICE_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_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n")); + DEVICE_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_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - AES Key must be 128 bits\n")); + return -EINVAL; + } + + // spin_lock_irq(&pDevice->lock); + if (IS_BROADCAST_ADDRESS(¶m->addr[0]) || (param->addr == NULL)) { + // If IS_BROADCAST_ADDRESS, set the key as every key entry's group key. + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); + + if ((KeybSetAllGroupKey(&(pDevice->sKey), + dwKeyIndex, + param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) && + (KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex, + param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) ) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); + + } else { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n")); + // spin_unlock_irq(&pDevice->lock); + return -EINVAL; + } + + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); + // BSSID not 0xffffffffffff + // Pairwise Key can't be WEP + if (byKeyDecMode == KEY_CTL_WEP) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); + //spin_unlock_irq(&pDevice->lock); + 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")); + //spin_unlock_irq(&pDevice->lock); + return -EINVAL; + } + if (KeybSetKey(&(pDevice->sKey), + ¶m->addr[0], + dwKeyIndex, + param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); + + } else { + // Key Table Full + if (IS_ETH_ADDRESS_EQUAL(¶m->addr[0], pDevice->abyBSSID)) { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); + //spin_unlock_irq(&pDevice->lock); + return -EINVAL; + + } else { + // Save Key and configure just before associate/reassociate to BSSID + // we do not implement now + //spin_unlock_irq(&pDevice->lock); + return -EINVAL; + } + } + } // BSSID not 0xffffffffffff + if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { + pDevice->byKeyIndex = (BYTE)param->u.wpa_key.key_index; + pDevice->bTransmitKey = TRUE; + } + pDevice->bEncryptionEnable = TRUE; + //spin_unlock_irq(&pDevice->lock); + +/* + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n", + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4] + ); +*/ + + return ret; + +} + + +/* + * Description: + * enable wpa auth & mode + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_set_wpa(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + + PSMgmtObject pMgmt = pDevice->pMgmt; + int ret = 0; + + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + pMgmt->bShareKeyAlgorithm = FALSE; + + return ret; +} + + + + + /* + * Description: + * set disassociate + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_set_disassociate(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + int ret = 0; + + spin_lock_irq(&pDevice->lock); + if (pDevice->bLinkPass) { + if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6)) + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_DISASSOCIATE, NULL); + } + spin_unlock_irq(&pDevice->lock); + + return ret; +} + + + +/* + * Description: + * enable scan process + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_set_scan(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + int ret = 0; + + spin_lock_irq(&pDevice->lock); + BSSvClearBSSList((HANDLE)pDevice, pDevice->bLinkPass); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, NULL); + spin_unlock_irq(&pDevice->lock); + + return ret; +} + + + +/* + * Description: + * get bssid + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_get_bssid(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + int ret = 0; + + memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID , 6); + + return ret; + +} + + +/* + * Description: + * get bssid + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_get_ssid(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + PWLAN_IE_SSID pItemSSID; + int ret = 0; + + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + + memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID , pItemSSID->len); + param->u.wpa_associate.ssid_len = pItemSSID->len; + + return ret; +} + + + +/* + * Description: + * get scan results + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_get_scan(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + struct viawget_scan_result *scan_buf; + PSMgmtObject pMgmt = pDevice->pMgmt; + PWLAN_IE_SSID pItemSSID; + PKnownBSS pBSS; + PBYTE pBuf; + int ret = 0; + u16 count = 0; + u16 ii, jj; +#if 1 + + PBYTE ptempBSS; + + + + ptempBSS = kmalloc(sizeof(KnownBSS), (int)GFP_ATOMIC); + + if (ptempBSS == NULL) { + + printk("bubble sort kmalloc memory fail@@@\n"); + + ret = -ENOMEM; + + return ret; + + } + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + + for(jj=0;jj<MAX_BSS_NUM-ii-1;jj++) { + + if((pMgmt->sBSSList[jj].bActive!=TRUE) || + + ((pMgmt->sBSSList[jj].uRSSI>pMgmt->sBSSList[jj+1].uRSSI) &&(pMgmt->sBSSList[jj+1].bActive!=FALSE))) { + + memcpy(ptempBSS,&pMgmt->sBSSList[jj],sizeof(KnownBSS)); + + memcpy(&pMgmt->sBSSList[jj],&pMgmt->sBSSList[jj+1],sizeof(KnownBSS)); + + memcpy(&pMgmt->sBSSList[jj+1],ptempBSS,sizeof(KnownBSS)); + + } + + } + + }; + + kfree(ptempBSS); + + // printk("bubble sort result:\n"); + + //for (ii = 0; ii < MAX_BSS_NUM; ii++) + + // printk("%d [%s]:RSSI=%d\n",ii,((PWLAN_IE_SSID)(pMgmt->sBSSList[ii].abySSID))->abySSID, + + // pMgmt->sBSSList[ii].uRSSI); + + #endif + +//******mike:bubble sort by stronger RSSI*****// + + + + + count = 0; + pBSS = &(pMgmt->sBSSList[0]); + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (!pBSS->bActive) + continue; + count++; + }; + + pBuf = kmalloc(sizeof(struct viawget_scan_result) * count, (int)GFP_ATOMIC); + + if (pBuf == NULL) { + ret = -ENOMEM; + return ret; + } + memset(pBuf, 0, sizeof(struct viawget_scan_result) * count); + scan_buf = (struct viawget_scan_result *)pBuf; + pBSS = &(pMgmt->sBSSList[0]); + for (ii = 0, jj = 0; ii < MAX_BSS_NUM ; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (pBSS->bActive) { + if (jj >= count) + break; + memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN); + pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; + memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len); + scan_buf->ssid_len = pItemSSID->len; + scan_buf->freq = frequency_list[pBSS->uChannel-1]; + scan_buf->caps = pBSS->wCapInfo; + //scan_buf->caps = pBSS->wCapInfo; + //scan_buf->qual = + //scan_buf->noise = + //scan_buf->level = + //scan_buf->maxrate = + if (pBSS->wWPALen != 0) { + scan_buf->wpa_ie_len = pBSS->wWPALen; + memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen); + } + if (pBSS->wRSNLen != 0) { + scan_buf->rsn_ie_len = pBSS->wRSNLen; + memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen); + } + scan_buf = (struct viawget_scan_result *)((PBYTE)scan_buf + sizeof(struct viawget_scan_result)); + jj ++; + } + } + + if (jj < count) + count = jj; + + if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) { + ret = -EFAULT; + }; + param->u.scan_results.scan_count = count; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count) + + kfree(pBuf); + return ret; +} + + + +/* + * Description: + * set associate with AP + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_set_associate(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + PWLAN_IE_SSID pItemSSID; + BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + BYTE abyWPAIE[64]; + int ret = 0; + BOOL bWepEnabled=FALSE; + + // set key type & algorithm + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); + + + if (param->u.wpa_associate.wpa_ie && + copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) + return -EINVAL; + + if (param->u.wpa_associate.mode == 1) + pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; + else + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + // set ssid + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSID->byElementID = WLAN_EID_SSID; + pItemSSID->len = param->u.wpa_associate.ssid_len; + memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len); + // set bssid + if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0) + memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6); +else +{ + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID); +} + + if (param->u.wpa_associate.wpa_ie_len == 0) { + if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY) + pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; + else + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + } else if (abyWPAIE[0] == RSN_INFO_ELEM) { + if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) + pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; + else + pMgmt->eAuthenMode = WMAC_AUTH_WPA2; + } else { + if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE) + pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; + else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) + pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; + else + pMgmt->eAuthenMode = WMAC_AUTH_WPA; + } + + switch (param->u.wpa_associate.pairwise_suite) { + case CIPHER_CCMP: + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + break; + case CIPHER_TKIP: + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + break; + case CIPHER_WEP40: + case CIPHER_WEP104: + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + bWepEnabled=TRUE; + break; + case CIPHER_NONE: + if (param->u.wpa_associate.group_suite == CIPHER_CCMP) + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + else + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + break; + default: + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + }; + +//DavidWang add for WPA_supplicant support open/share mode + + if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + //pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; + pMgmt->bShareKeyAlgorithm = TRUE; + } + else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) { + if(!bWepEnabled) pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + //pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + //pMgmt->bShareKeyAlgorithm = FALSE; //20080717-06,<Modify> by chester//Fix Open mode, WEP encrytion + } +//mike save old encryption status + pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus; + + if (pDevice->eEncryptionStatus != Ndis802_11EncryptionDisabled) + pDevice->bEncryptionEnable = TRUE; + else + pDevice->bEncryptionEnable = FALSE; +if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) || + ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bWepEnabled==TRUE))) ) //DavidWang //20080717-06,<Modify> by chester//Not to initial WEP + KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); + spin_lock_irq(&pDevice->lock); + pDevice->bLinkPass = FALSE; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); + //20080701-02,<Add> by Mike Liu +/*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/ +{ + PKnownBSS pCurr = NULL; + pCurr = BSSpSearchBSSList(pDevice, + pMgmt->abyDesireBSSID, + pMgmt->abyDesireSSID, + pMgmt->eConfigPHYMode + ); + + if (pCurr == NULL){ + printk("wpa_set_associate---->hidden mode site survey before associate.......\n"); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); + }; +} +/****************************************************************/ + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, NULL); + spin_unlock_irq(&pDevice->lock); + + return ret; +} + + +/* + * Description: + * wpa_ioctl main function supported for wpa supplicant + * + * Parameters: + * In: + * pDevice - + * iw_point - + * Out: + * + * Return Value: + * + */ + +int wpa_ioctl(PSDevice pDevice, struct iw_point *p) +{ + struct viawget_wpa_param *param; + int ret = 0; + int wpa_ioctl = 0; + + if (p->length < sizeof(struct viawget_wpa_param) || + p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer) + return -EINVAL; + + param = (struct viawget_wpa_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_SET_WPA: + ret = wpa_set_wpa(pDevice, param); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n"); + break; + + case VIAWGET_SET_KEY: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n"); + spin_lock_irq(&pDevice->lock); + ret = wpa_set_keys(pDevice, param, FALSE); + spin_unlock_irq(&pDevice->lock); + break; + + case VIAWGET_SET_SCAN: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n"); + ret = wpa_set_scan(pDevice, param); + break; + + case VIAWGET_GET_SCAN: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n"); + ret = wpa_get_scan(pDevice, param); + wpa_ioctl = 1; + break; + + case VIAWGET_GET_SSID: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n"); + ret = wpa_get_ssid(pDevice, param); + wpa_ioctl = 1; + break; + + case VIAWGET_GET_BSSID: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n"); + ret = wpa_get_bssid(pDevice, param); + wpa_ioctl = 1; + break; + + case VIAWGET_SET_ASSOCIATE: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n"); + ret = wpa_set_associate(pDevice, param); + break; + + case VIAWGET_SET_DISASSOCIATE: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n"); + ret = wpa_set_disassociate(pDevice, param); + break; + + case VIAWGET_SET_DROP_UNENCRYPT: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n"); + break; + + case VIAWGET_SET_DEAUTHENTICATE: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n"); + break; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n", + param->cmd); + return -EOPNOTSUPP; + break; + } + + if ((ret == 0) && wpa_ioctl) { + if (copy_to_user(p->pointer, param, p->length)) { + ret = -EFAULT; + goto out; + } + } + +out: + if (param != NULL) + kfree(param); + + return ret; +} + |