Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation; either version 2 of the License, or |
| 8 | * (at your option) any later version. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along |
| 16 | * with this program; if not, write to the Free Software Foundation, Inc., |
| 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * File: ioctl.c |
| 20 | * |
| 21 | * Purpose: private ioctl functions |
| 22 | * |
| 23 | * Author: Lyndon Chen |
| 24 | * |
| 25 | * Date: Auguest 20, 2003 |
| 26 | * |
| 27 | * Functions: |
| 28 | * |
| 29 | * Revision History: |
| 30 | * |
| 31 | */ |
| 32 | |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 33 | #include "ioctl.h" |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 34 | #include "iocmd.h" |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 35 | #include "mac.h" |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 36 | #include "card.h" |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 37 | #include "hostap.h" |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 38 | #include "wpactl.h" |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 39 | #include "rf.h" |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 40 | |
Malcolm Priestley | 8f335dd | 2014-08-10 15:47:00 +0100 | [diff] [blame] | 41 | int private_ioctl(struct vnt_private *pDevice, struct ifreq *rq) |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 42 | { |
| 43 | PSCmdRequest pReq = (PSCmdRequest)rq; |
| 44 | PSMgmtObject pMgmt = pDevice->pMgmt; |
| 45 | int result = 0; |
| 46 | PWLAN_IE_SSID pItemSSID; |
| 47 | SCmdBSSJoin sJoinCmd; |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 48 | SCmdScan sScanCmd; |
| 49 | SCmdStartAP sStartAPCmd; |
| 50 | SCmdSetWEP sWEPCmd; |
| 51 | SCmdValue sValue; |
| 52 | SBSSIDList sList; |
| 53 | SNodeList sNodeList; |
| 54 | PSBSSIDList pList; |
| 55 | PSNodeList pNodeList; |
| 56 | unsigned int cbListCount; |
| 57 | PKnownBSS pBSS; |
| 58 | PKnownNodeDB pNode; |
| 59 | unsigned int ii, jj; |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 60 | unsigned char abySuppRates[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16}; |
| 61 | unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| 62 | unsigned long dwKeyIndex = 0; |
| 63 | unsigned char abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; |
| 64 | long ldBm; |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 65 | |
| 66 | pReq->wResult = 0; |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 67 | |
| 68 | switch (pReq->wCmdCode) { |
| 69 | case WLAN_CMD_BSS_SCAN: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 70 | pr_debug("WLAN_CMD_BSS_SCAN..begin\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 71 | if (copy_from_user(&sScanCmd, pReq->data, sizeof(SCmdScan))) { |
| 72 | result = -EFAULT; |
| 73 | break; |
| 74 | } |
| 75 | |
| 76 | pItemSSID = (PWLAN_IE_SSID)sScanCmd.ssid; |
Dan Carpenter | 0c849b3 | 2011-10-20 09:10:09 +0300 | [diff] [blame] | 77 | if (pItemSSID->len > WLAN_SSID_MAXLEN + 1) |
| 78 | return -EINVAL; |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 79 | if (pItemSSID->len != 0) { |
| 80 | memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); |
| 81 | memcpy(abyScanSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN); |
| 82 | } |
| 83 | |
| 84 | if (pDevice->bMACSuspend == true) { |
| 85 | if (pDevice->bRadioOff == true) |
| 86 | CARDbRadioPowerOn(pDevice); |
| 87 | vMgrTimerInit(pDevice); |
| 88 | MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); |
| 89 | add_timer(&pMgmt->sTimerSecondCallback); |
| 90 | pDevice->bMACSuspend = false; |
| 91 | } |
| 92 | spin_lock_irq(&pDevice->lock); |
| 93 | if (memcmp(pMgmt->abyCurrBSSID, &abyNullAddr[0], 6) == 0) |
| 94 | BSSvClearBSSList((void *)pDevice, false); |
| 95 | else |
| 96 | BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass); |
| 97 | |
| 98 | if (pItemSSID->len != 0) |
Joe Perches | 281c746 | 2013-03-18 10:44:51 -0700 | [diff] [blame] | 99 | bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 100 | else |
Joe Perches | 281c746 | 2013-03-18 10:44:51 -0700 | [diff] [blame] | 101 | bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 102 | spin_unlock_irq(&pDevice->lock); |
| 103 | break; |
| 104 | |
| 105 | case WLAN_CMD_ZONETYPE_SET: |
Justin P. Mattock | 789d1ae | 2012-08-20 08:43:13 -0700 | [diff] [blame] | 106 | /* mike add :can't support. */ |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 107 | result = -EOPNOTSUPP; |
| 108 | break; |
| 109 | |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 110 | case WLAN_CMD_BSS_JOIN: |
| 111 | if (pDevice->bMACSuspend == true) { |
| 112 | if (pDevice->bRadioOff == true) |
| 113 | CARDbRadioPowerOn(pDevice); |
| 114 | vMgrTimerInit(pDevice); |
| 115 | MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); |
| 116 | add_timer(&pMgmt->sTimerSecondCallback); |
| 117 | pDevice->bMACSuspend = false; |
| 118 | } |
| 119 | |
| 120 | if (copy_from_user(&sJoinCmd, pReq->data, sizeof(SCmdBSSJoin))) { |
| 121 | result = -EFAULT; |
| 122 | break; |
| 123 | } |
| 124 | |
| 125 | pItemSSID = (PWLAN_IE_SSID)sJoinCmd.ssid; |
Dan Carpenter | 0c849b3 | 2011-10-20 09:10:09 +0300 | [diff] [blame] | 126 | if (pItemSSID->len > WLAN_SSID_MAXLEN + 1) |
| 127 | return -EINVAL; |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 128 | memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); |
| 129 | memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN); |
| 130 | if (sJoinCmd.wBSSType == ADHOC) { |
| 131 | pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 132 | pr_debug("ioct set to adhoc mode\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 133 | } else { |
| 134 | pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 135 | pr_debug("ioct set to STA mode\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 136 | } |
| 137 | if (sJoinCmd.bPSEnable == true) { |
| 138 | pDevice->ePSMode = WMAC_POWER_FAST; |
| 139 | pMgmt->wListenInterval = 2; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 140 | pr_debug("Power Saving On\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 141 | } else { |
| 142 | pDevice->ePSMode = WMAC_POWER_CAM; |
| 143 | pMgmt->wListenInterval = 1; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 144 | pr_debug("Power Saving Off\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | if (sJoinCmd.bShareKeyAuth == true) { |
| 148 | pMgmt->bShareKeyAlgorithm = true; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 149 | pr_debug("Share Key\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 150 | } else { |
| 151 | pMgmt->bShareKeyAlgorithm = false; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 152 | pr_debug("Open System\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 153 | } |
| 154 | pDevice->uChannel = sJoinCmd.uChannel; |
| 155 | netif_stop_queue(pDevice->dev); |
| 156 | spin_lock_irq(&pDevice->lock); |
| 157 | pMgmt->eCurrState = WMAC_STATE_IDLE; |
Joe Perches | 281c746 | 2013-03-18 10:44:51 -0700 | [diff] [blame] | 158 | bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); |
| 159 | bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 160 | spin_unlock_irq(&pDevice->lock); |
| 161 | break; |
| 162 | |
| 163 | case WLAN_CMD_SET_WEP: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 164 | pr_debug("WLAN_CMD_SET_WEP Key\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 165 | memset(&sWEPCmd, 0, sizeof(SCmdSetWEP)); |
| 166 | if (copy_from_user(&sWEPCmd, pReq->data, sizeof(SCmdSetWEP))) { |
| 167 | result = -EFAULT; |
| 168 | break; |
| 169 | } |
| 170 | if (sWEPCmd.bEnableWep != true) { |
| 171 | pDevice->bEncryptionEnable = false; |
| 172 | pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; |
| 173 | MACvDisableDefaultKey(pDevice->PortOffset); |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 174 | pr_debug("WEP function disable\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 175 | break; |
| 176 | } |
| 177 | |
| 178 | for (ii = 0; ii < WLAN_WEP_NKEYS; ii++) { |
| 179 | if (sWEPCmd.bWepKeyAvailable[ii]) { |
| 180 | if (ii == sWEPCmd.byKeyIndex) |
| 181 | dwKeyIndex = ii | (1 << 31); |
| 182 | else |
| 183 | dwKeyIndex = ii; |
| 184 | |
| 185 | KeybSetDefaultKey(&(pDevice->sKey), |
| 186 | dwKeyIndex, |
| 187 | sWEPCmd.auWepKeyLength[ii], |
| 188 | NULL, |
| 189 | (unsigned char *)&sWEPCmd.abyWepKey[ii][0], |
| 190 | KEY_CTL_WEP, |
| 191 | pDevice->PortOffset, |
| 192 | pDevice->byLocalID); |
| 193 | } |
| 194 | } |
| 195 | pDevice->byKeyIndex = sWEPCmd.byKeyIndex; |
| 196 | pDevice->bTransmitKey = true; |
| 197 | pDevice->bEncryptionEnable = true; |
| 198 | pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; |
| 199 | break; |
| 200 | |
Dan Carpenter | 34fbb97 | 2013-06-24 19:12:09 +0300 | [diff] [blame] | 201 | case WLAN_CMD_GET_LINK: { |
| 202 | SCmdLinkStatus sLinkStatus; |
| 203 | |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 204 | pr_debug("WLAN_CMD_GET_LINK status\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 205 | |
Dan Carpenter | 34fbb97 | 2013-06-24 19:12:09 +0300 | [diff] [blame] | 206 | memset(&sLinkStatus, 0, sizeof(sLinkStatus)); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 207 | |
| 208 | if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) |
| 209 | sLinkStatus.wBSSType = ADHOC; |
| 210 | else |
| 211 | sLinkStatus.wBSSType = INFRA; |
| 212 | |
| 213 | if (pMgmt->eCurrState == WMAC_STATE_JOINTED) |
| 214 | sLinkStatus.byState = ADHOC_JOINTED; |
| 215 | else |
| 216 | sLinkStatus.byState = ADHOC_STARTED; |
| 217 | |
| 218 | sLinkStatus.uChannel = pMgmt->uCurrChannel; |
| 219 | if (pDevice->bLinkPass == true) { |
| 220 | sLinkStatus.bLink = true; |
| 221 | pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; |
| 222 | memcpy(sLinkStatus.abySSID, pItemSSID->abySSID, pItemSSID->len); |
| 223 | memcpy(sLinkStatus.abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); |
| 224 | sLinkStatus.uLinkRate = pMgmt->sNodeDBTable[0].wTxDataRate; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 225 | pr_debug(" Link Success!\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 226 | } else { |
| 227 | sLinkStatus.bLink = false; |
| 228 | sLinkStatus.uLinkRate = 0; |
| 229 | } |
| 230 | if (copy_to_user(pReq->data, &sLinkStatus, sizeof(SCmdLinkStatus))) { |
| 231 | result = -EFAULT; |
| 232 | break; |
| 233 | } |
| 234 | break; |
Dan Carpenter | 34fbb97 | 2013-06-24 19:12:09 +0300 | [diff] [blame] | 235 | } |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 236 | case WLAN_CMD_GET_LISTLEN: |
| 237 | cbListCount = 0; |
| 238 | pBSS = &(pMgmt->sBSSList[0]); |
| 239 | for (ii = 0; ii < MAX_BSS_NUM; ii++) { |
| 240 | pBSS = &(pMgmt->sBSSList[ii]); |
| 241 | if (!pBSS->bActive) |
| 242 | continue; |
| 243 | cbListCount++; |
| 244 | } |
| 245 | sList.uItem = cbListCount; |
| 246 | if (copy_to_user(pReq->data, &sList, sizeof(SBSSIDList))) { |
| 247 | result = -EFAULT; |
| 248 | break; |
| 249 | } |
| 250 | pReq->wResult = 0; |
| 251 | break; |
| 252 | |
| 253 | case WLAN_CMD_GET_LIST: |
| 254 | if (copy_from_user(&sList, pReq->data, sizeof(SBSSIDList))) { |
| 255 | result = -EFAULT; |
| 256 | break; |
| 257 | } |
Xi Wang | 2a58b19 | 2011-11-29 21:52:46 -0500 | [diff] [blame] | 258 | if (sList.uItem > (ULONG_MAX - sizeof(SBSSIDList)) / sizeof(SBSSIDItem)) { |
| 259 | result = -EINVAL; |
| 260 | break; |
| 261 | } |
Silvio Fricke | b47eb6c | 2014-04-12 02:30:25 +0200 | [diff] [blame] | 262 | pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), |
| 263 | GFP_ATOMIC); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 264 | if (pList == NULL) { |
| 265 | result = -ENOMEM; |
| 266 | break; |
| 267 | } |
| 268 | pList->uItem = sList.uItem; |
| 269 | pBSS = &(pMgmt->sBSSList[0]); |
Joe Perches | 281c746 | 2013-03-18 10:44:51 -0700 | [diff] [blame] | 270 | for (ii = 0, jj = 0; jj < MAX_BSS_NUM; jj++) { |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 271 | pBSS = &(pMgmt->sBSSList[jj]); |
| 272 | if (pBSS->bActive) { |
| 273 | pList->sBSSIDList[ii].uChannel = pBSS->uChannel; |
| 274 | pList->sBSSIDList[ii].wBeaconInterval = pBSS->wBeaconInterval; |
| 275 | pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo; |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 276 | RFvRSSITodBm(pDevice, (unsigned char)(pBSS->uRSSI), &ldBm); |
| 277 | pList->sBSSIDList[ii].uRSSI = (unsigned int)ldBm; |
| 278 | memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN); |
| 279 | pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; |
| 280 | memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1); |
| 281 | memcpy(pList->sBSSIDList[ii].abySSID, pItemSSID->abySSID, pItemSSID->len); |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 282 | if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 283 | pList->sBSSIDList[ii].byNetType = INFRA; |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 284 | else |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 285 | pList->sBSSIDList[ii].byNetType = ADHOC; |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 286 | |
| 287 | if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 288 | pList->sBSSIDList[ii].bWEPOn = true; |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 289 | else |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 290 | pList->sBSSIDList[ii].bWEPOn = false; |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 291 | |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 292 | ii++; |
| 293 | if (ii >= pList->uItem) |
| 294 | break; |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | if (copy_to_user(pReq->data, pList, sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)))) { |
| 299 | result = -EFAULT; |
| 300 | break; |
| 301 | } |
| 302 | kfree(pList); |
| 303 | pReq->wResult = 0; |
| 304 | break; |
| 305 | |
| 306 | case WLAN_CMD_GET_MIB: |
| 307 | if (copy_to_user(pReq->data, &(pDevice->s802_11Counter), sizeof(SDot11MIBCount))) { |
| 308 | result = -EFAULT; |
| 309 | break; |
| 310 | } |
| 311 | break; |
| 312 | |
| 313 | case WLAN_CMD_GET_STAT: |
| 314 | if (copy_to_user(pReq->data, &(pDevice->scStatistic), sizeof(SStatCounter))) { |
| 315 | result = -EFAULT; |
| 316 | break; |
| 317 | } |
| 318 | break; |
| 319 | |
| 320 | case WLAN_CMD_STOP_MAC: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 321 | pr_debug("WLAN_CMD_STOP_MAC\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 322 | netif_stop_queue(pDevice->dev); |
| 323 | |
| 324 | spin_lock_irq(&pDevice->lock); |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 325 | if (pDevice->bRadioOff == false) |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 326 | CARDbRadioPowerOff(pDevice); |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 327 | |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 328 | pDevice->bLinkPass = false; |
| 329 | memset(pMgmt->abyCurrBSSID, 0, 6); |
| 330 | pMgmt->eCurrState = WMAC_STATE_IDLE; |
| 331 | del_timer(&pDevice->sTimerCommand); |
| 332 | del_timer(&pMgmt->sTimerSecondCallback); |
| 333 | pDevice->bCmdRunning = false; |
| 334 | pDevice->bMACSuspend = true; |
| 335 | MACvIntDisable(pDevice->PortOffset); |
| 336 | spin_unlock_irq(&pDevice->lock); |
| 337 | break; |
| 338 | |
| 339 | case WLAN_CMD_START_MAC: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 340 | pr_debug("WLAN_CMD_START_MAC\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 341 | |
| 342 | if (pDevice->bMACSuspend == true) { |
| 343 | if (pDevice->bRadioOff == true) |
| 344 | CARDbRadioPowerOn(pDevice); |
| 345 | vMgrTimerInit(pDevice); |
| 346 | MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); |
| 347 | add_timer(&pMgmt->sTimerSecondCallback); |
| 348 | pDevice->bMACSuspend = false; |
| 349 | } |
| 350 | break; |
| 351 | |
| 352 | case WLAN_CMD_SET_HOSTAPD: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 353 | pr_debug("WLAN_CMD_SET_HOSTAPD\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 354 | |
| 355 | if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) { |
| 356 | result = -EFAULT; |
| 357 | break; |
| 358 | } |
| 359 | if (sValue.dwValue == 1) { |
| 360 | if (vt6655_hostap_set_hostapd(pDevice, 1, 1) == 0) { |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 361 | pr_debug("Enable HOSTAP\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 362 | } else { |
| 363 | result = -EFAULT; |
| 364 | break; |
| 365 | } |
| 366 | } else { |
| 367 | vt6655_hostap_set_hostapd(pDevice, 0, 1); |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 368 | pr_debug("Disable HOSTAP\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 369 | } |
| 370 | break; |
| 371 | |
| 372 | case WLAN_CMD_SET_HOSTAPD_STA: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 373 | pr_debug("WLAN_CMD_SET_HOSTAPD_STA\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 374 | break; |
| 375 | |
| 376 | case WLAN_CMD_SET_802_1X: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 377 | pr_debug("WLAN_CMD_SET_802_1X\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 378 | if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) { |
| 379 | result = -EFAULT; |
| 380 | break; |
| 381 | } |
| 382 | |
| 383 | if (sValue.dwValue == 1) { |
| 384 | pDevice->bEnable8021x = true; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 385 | pr_debug("Enable 802.1x\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 386 | } else { |
| 387 | pDevice->bEnable8021x = false; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 388 | pr_debug("Disable 802.1x\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 389 | } |
| 390 | break; |
| 391 | |
| 392 | case WLAN_CMD_SET_HOST_WEP: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 393 | pr_debug("WLAN_CMD_SET_HOST_WEP\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 394 | if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) { |
| 395 | result = -EFAULT; |
| 396 | break; |
| 397 | } |
| 398 | |
| 399 | if (sValue.dwValue == 1) { |
| 400 | pDevice->bEnableHostWEP = true; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 401 | pr_debug("Enable HostWEP\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 402 | } else { |
| 403 | pDevice->bEnableHostWEP = false; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 404 | pr_debug("Disable HostWEP\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 405 | } |
| 406 | break; |
| 407 | |
| 408 | case WLAN_CMD_SET_WPA: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 409 | pr_debug("WLAN_CMD_SET_WPA\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 410 | |
| 411 | if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) { |
| 412 | result = -EFAULT; |
| 413 | break; |
| 414 | } |
| 415 | if (sValue.dwValue == 1) { |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 416 | pr_debug("up wpadev\n"); |
Bjørn Mork | 314cb11 | 2013-08-30 18:08:52 +0200 | [diff] [blame] | 417 | eth_hw_addr_inherit(pDevice->wpadev, pDevice->dev); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 418 | pDevice->bWPADEVUp = true; |
| 419 | } else { |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 420 | pr_debug("close wpadev\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 421 | pDevice->bWPADEVUp = false; |
| 422 | } |
| 423 | break; |
| 424 | |
| 425 | case WLAN_CMD_AP_START: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 426 | pr_debug("WLAN_CMD_AP_START\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 427 | if (pDevice->bRadioOff == true) { |
| 428 | CARDbRadioPowerOn(pDevice); |
| 429 | vMgrTimerInit(pDevice); |
| 430 | MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); |
| 431 | add_timer(&pMgmt->sTimerSecondCallback); |
| 432 | } |
| 433 | if (copy_from_user(&sStartAPCmd, pReq->data, sizeof(SCmdStartAP))) { |
| 434 | result = -EFAULT; |
| 435 | break; |
| 436 | } |
| 437 | |
| 438 | if (sStartAPCmd.wBSSType == AP) { |
| 439 | pMgmt->eConfigMode = WMAC_CONFIG_AP; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 440 | pr_debug("ioct set to AP mode\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 441 | } else { |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 442 | pr_debug("ioct BSS type not set to AP mode\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 443 | result = -EFAULT; |
| 444 | break; |
| 445 | } |
| 446 | |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 447 | if (sStartAPCmd.wBBPType == PHY80211g) |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 448 | pMgmt->byAPBBType = PHY_TYPE_11G; |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 449 | else if (sStartAPCmd.wBBPType == PHY80211a) |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 450 | pMgmt->byAPBBType = PHY_TYPE_11A; |
mahendra singh meena | 08afcf9 | 2012-01-16 23:50:38 +0530 | [diff] [blame] | 451 | else |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 452 | pMgmt->byAPBBType = PHY_TYPE_11B; |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 453 | |
| 454 | pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid; |
Dan Carpenter | 0c849b3 | 2011-10-20 09:10:09 +0300 | [diff] [blame] | 455 | if (pItemSSID->len > WLAN_SSID_MAXLEN + 1) |
| 456 | return -EINVAL; |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 457 | memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); |
| 458 | memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN); |
| 459 | |
| 460 | if ((sStartAPCmd.uChannel > 0) && (sStartAPCmd.uChannel <= 14)) |
| 461 | pDevice->uChannel = sStartAPCmd.uChannel; |
| 462 | |
| 463 | if ((sStartAPCmd.uBeaconInt >= 20) && (sStartAPCmd.uBeaconInt <= 1000)) |
| 464 | pMgmt->wIBSSBeaconPeriod = sStartAPCmd.uBeaconInt; |
| 465 | else |
| 466 | pMgmt->wIBSSBeaconPeriod = 100; |
| 467 | |
| 468 | if (sStartAPCmd.bShareKeyAuth == true) { |
| 469 | pMgmt->bShareKeyAlgorithm = true; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 470 | pr_debug("Share Key\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 471 | } else { |
| 472 | pMgmt->bShareKeyAlgorithm = false; |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 473 | pr_debug("Open System\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 474 | } |
| 475 | memcpy(pMgmt->abyIBSSSuppRates, abySuppRates, 6); |
| 476 | |
| 477 | if (sStartAPCmd.byBasicRate & BIT3) { |
| 478 | pMgmt->abyIBSSSuppRates[2] |= BIT7; |
| 479 | pMgmt->abyIBSSSuppRates[3] |= BIT7; |
| 480 | pMgmt->abyIBSSSuppRates[4] |= BIT7; |
| 481 | pMgmt->abyIBSSSuppRates[5] |= BIT7; |
| 482 | } else if (sStartAPCmd.byBasicRate & BIT2) { |
| 483 | pMgmt->abyIBSSSuppRates[2] |= BIT7; |
| 484 | pMgmt->abyIBSSSuppRates[3] |= BIT7; |
| 485 | pMgmt->abyIBSSSuppRates[4] |= BIT7; |
| 486 | } else if (sStartAPCmd.byBasicRate & BIT1) { |
| 487 | pMgmt->abyIBSSSuppRates[2] |= BIT7; |
| 488 | pMgmt->abyIBSSSuppRates[3] |= BIT7; |
| 489 | } else if (sStartAPCmd.byBasicRate & BIT1) { |
| 490 | pMgmt->abyIBSSSuppRates[2] |= BIT7; |
| 491 | } else { |
| 492 | /* default 1,2M */ |
| 493 | pMgmt->abyIBSSSuppRates[2] |= BIT7; |
| 494 | pMgmt->abyIBSSSuppRates[3] |= BIT7; |
| 495 | } |
| 496 | |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 497 | pr_debug("Support Rate= %*ph\n", |
| 498 | 4, pMgmt->abyIBSSSuppRates + 2); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 499 | |
| 500 | netif_stop_queue(pDevice->dev); |
| 501 | spin_lock_irq(&pDevice->lock); |
| 502 | bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL); |
| 503 | spin_unlock_irq(&pDevice->lock); |
| 504 | break; |
| 505 | |
| 506 | case WLAN_CMD_GET_NODE_CNT: |
| 507 | cbListCount = 0; |
| 508 | pNode = &(pMgmt->sNodeDBTable[0]); |
| 509 | for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) { |
| 510 | pNode = &(pMgmt->sNodeDBTable[ii]); |
| 511 | if (!pNode->bActive) |
| 512 | continue; |
| 513 | cbListCount++; |
| 514 | } |
| 515 | |
| 516 | sNodeList.uItem = cbListCount; |
| 517 | if (copy_to_user(pReq->data, &sNodeList, sizeof(SNodeList))) { |
| 518 | result = -EFAULT; |
| 519 | break; |
| 520 | } |
| 521 | pReq->wResult = 0; |
| 522 | break; |
| 523 | |
| 524 | case WLAN_CMD_GET_NODE_LIST: |
| 525 | if (copy_from_user(&sNodeList, pReq->data, sizeof(SNodeList))) { |
| 526 | result = -EFAULT; |
| 527 | break; |
| 528 | } |
Xi Wang | 2a58b19 | 2011-11-29 21:52:46 -0500 | [diff] [blame] | 529 | if (sNodeList.uItem > (ULONG_MAX - sizeof(SNodeList)) / sizeof(SNodeItem)) { |
| 530 | result = -EINVAL; |
| 531 | break; |
| 532 | } |
Silvio Fricke | b47eb6c | 2014-04-12 02:30:25 +0200 | [diff] [blame] | 533 | pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), |
| 534 | GFP_ATOMIC); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 535 | if (pNodeList == NULL) { |
| 536 | result = -ENOMEM; |
| 537 | break; |
| 538 | } |
| 539 | pNodeList->uItem = sNodeList.uItem; |
| 540 | pNode = &(pMgmt->sNodeDBTable[0]); |
| 541 | for (ii = 0, jj = 0; ii < (MAX_NODE_NUM + 1); ii++) { |
| 542 | pNode = &(pMgmt->sNodeDBTable[ii]); |
| 543 | if (pNode->bActive) { |
| 544 | pNodeList->sNodeList[jj].wAID = pNode->wAID; |
| 545 | memcpy(pNodeList->sNodeList[jj].abyMACAddr, pNode->abyMACAddr, WLAN_ADDR_LEN); |
| 546 | pNodeList->sNodeList[jj].wTxDataRate = pNode->wTxDataRate; |
| 547 | pNodeList->sNodeList[jj].wInActiveCount = (unsigned short)pNode->uInActiveCount; |
| 548 | pNodeList->sNodeList[jj].wEnQueueCnt = (unsigned short)pNode->wEnQueueCnt; |
| 549 | pNodeList->sNodeList[jj].wFlags = (unsigned short)pNode->dwFlags; |
| 550 | pNodeList->sNodeList[jj].bPWBitOn = pNode->bPSEnable; |
| 551 | pNodeList->sNodeList[jj].byKeyIndex = pNode->byKeyIndex; |
| 552 | pNodeList->sNodeList[jj].wWepKeyLength = pNode->uWepKeyLength; |
| 553 | memcpy(&(pNodeList->sNodeList[jj].abyWepKey[0]), &(pNode->abyWepKey[0]), WEP_KEYMAXLEN); |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 554 | pr_debug("key= %2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", |
| 555 | pNodeList->sNodeList[jj].abyWepKey[0], |
| 556 | pNodeList->sNodeList[jj].abyWepKey[1], |
| 557 | pNodeList->sNodeList[jj].abyWepKey[2], |
| 558 | pNodeList->sNodeList[jj].abyWepKey[3], |
| 559 | pNodeList->sNodeList[jj].abyWepKey[4]); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 560 | pNodeList->sNodeList[jj].bIsInFallback = pNode->bIsInFallback; |
| 561 | pNodeList->sNodeList[jj].uTxFailures = pNode->uTxFailures; |
| 562 | pNodeList->sNodeList[jj].uTxAttempts = pNode->uTxAttempts; |
| 563 | pNodeList->sNodeList[jj].wFailureRatio = (unsigned short)pNode->uFailureRatio; |
| 564 | jj++; |
| 565 | if (jj >= pNodeList->uItem) |
| 566 | break; |
| 567 | } |
| 568 | } |
| 569 | if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) { |
| 570 | result = -EFAULT; |
| 571 | break; |
| 572 | } |
| 573 | kfree(pNodeList); |
| 574 | pReq->wResult = 0; |
| 575 | break; |
| 576 | |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 577 | default: |
Joe Perches | 48caf5a | 2014-08-17 09:17:04 -0700 | [diff] [blame] | 578 | pr_debug("Private command not support..\n"); |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 579 | } |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 580 | |
Dan Carpenter | 0d3eb2b | 2011-10-20 09:09:46 +0300 | [diff] [blame] | 581 | return result; |
Forest Bond | 5449c68 | 2009-04-25 10:30:44 -0400 | [diff] [blame] | 582 | } |