blob: c2b6763c8ab9b2df52ba33d85e6da702185efe20 [file] [log] [blame]
Forest Bond5449c682009-04-25 10:30:44 -04001/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * File: 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 Bond5449c682009-04-25 10:30:44 -040033#include "ioctl.h"
Forest Bond5449c682009-04-25 10:30:44 -040034#include "iocmd.h"
Forest Bond5449c682009-04-25 10:30:44 -040035#include "mac.h"
Forest Bond5449c682009-04-25 10:30:44 -040036#include "card.h"
Forest Bond5449c682009-04-25 10:30:44 -040037#include "hostap.h"
Forest Bond5449c682009-04-25 10:30:44 -040038#include "wpactl.h"
Forest Bond5449c682009-04-25 10:30:44 -040039#include "rf.h"
Forest Bond5449c682009-04-25 10:30:44 -040040
Malcolm Priestley8f335dd2014-08-10 15:47:00 +010041int private_ioctl(struct vnt_private *pDevice, struct ifreq *rq)
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +030042{
43 PSCmdRequest pReq = (PSCmdRequest)rq;
44 PSMgmtObject pMgmt = pDevice->pMgmt;
45 int result = 0;
46 PWLAN_IE_SSID pItemSSID;
47 SCmdBSSJoin sJoinCmd;
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +030048 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 Carpenter0d3eb2b2011-10-20 09:09:46 +030060 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 Bond5449c682009-04-25 10:30:44 -040065
66 pReq->wResult = 0;
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +030067
68 switch (pReq->wCmdCode) {
69 case WLAN_CMD_BSS_SCAN:
Joe Perches48caf5a2014-08-17 09:17:04 -070070 pr_debug("WLAN_CMD_BSS_SCAN..begin\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +030071 if (copy_from_user(&sScanCmd, pReq->data, sizeof(SCmdScan))) {
72 result = -EFAULT;
73 break;
74 }
75
76 pItemSSID = (PWLAN_IE_SSID)sScanCmd.ssid;
Dan Carpenter0c849b32011-10-20 09:10:09 +030077 if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
78 return -EINVAL;
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +030079 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 Perches281c7462013-03-18 10:44:51 -070099 bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID);
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300100 else
Joe Perches281c7462013-03-18 10:44:51 -0700101 bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300102 spin_unlock_irq(&pDevice->lock);
103 break;
104
105 case WLAN_CMD_ZONETYPE_SET:
Justin P. Mattock789d1ae2012-08-20 08:43:13 -0700106 /* mike add :can't support. */
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300107 result = -EOPNOTSUPP;
108 break;
109
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300110 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 Carpenter0c849b32011-10-20 09:10:09 +0300126 if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
127 return -EINVAL;
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300128 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 Perches48caf5a2014-08-17 09:17:04 -0700132 pr_debug("ioct set to adhoc mode\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300133 } else {
134 pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
Joe Perches48caf5a2014-08-17 09:17:04 -0700135 pr_debug("ioct set to STA mode\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300136 }
137 if (sJoinCmd.bPSEnable == true) {
138 pDevice->ePSMode = WMAC_POWER_FAST;
139 pMgmt->wListenInterval = 2;
Joe Perches48caf5a2014-08-17 09:17:04 -0700140 pr_debug("Power Saving On\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300141 } else {
142 pDevice->ePSMode = WMAC_POWER_CAM;
143 pMgmt->wListenInterval = 1;
Joe Perches48caf5a2014-08-17 09:17:04 -0700144 pr_debug("Power Saving Off\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300145 }
146
147 if (sJoinCmd.bShareKeyAuth == true) {
148 pMgmt->bShareKeyAlgorithm = true;
Joe Perches48caf5a2014-08-17 09:17:04 -0700149 pr_debug("Share Key\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300150 } else {
151 pMgmt->bShareKeyAlgorithm = false;
Joe Perches48caf5a2014-08-17 09:17:04 -0700152 pr_debug("Open System\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300153 }
154 pDevice->uChannel = sJoinCmd.uChannel;
155 netif_stop_queue(pDevice->dev);
156 spin_lock_irq(&pDevice->lock);
157 pMgmt->eCurrState = WMAC_STATE_IDLE;
Joe Perches281c7462013-03-18 10:44:51 -0700158 bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
159 bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300160 spin_unlock_irq(&pDevice->lock);
161 break;
162
163 case WLAN_CMD_SET_WEP:
Joe Perches48caf5a2014-08-17 09:17:04 -0700164 pr_debug("WLAN_CMD_SET_WEP Key\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300165 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 Perches48caf5a2014-08-17 09:17:04 -0700174 pr_debug("WEP function disable\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300175 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 Carpenter34fbb972013-06-24 19:12:09 +0300201 case WLAN_CMD_GET_LINK: {
202 SCmdLinkStatus sLinkStatus;
203
Joe Perches48caf5a2014-08-17 09:17:04 -0700204 pr_debug("WLAN_CMD_GET_LINK status\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300205
Dan Carpenter34fbb972013-06-24 19:12:09 +0300206 memset(&sLinkStatus, 0, sizeof(sLinkStatus));
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300207
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 Perches48caf5a2014-08-17 09:17:04 -0700225 pr_debug(" Link Success!\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300226 } 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 Carpenter34fbb972013-06-24 19:12:09 +0300235 }
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300236 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 Wang2a58b192011-11-29 21:52:46 -0500258 if (sList.uItem > (ULONG_MAX - sizeof(SBSSIDList)) / sizeof(SBSSIDItem)) {
259 result = -EINVAL;
260 break;
261 }
Silvio Frickeb47eb6c2014-04-12 02:30:25 +0200262 pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)),
263 GFP_ATOMIC);
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300264 if (pList == NULL) {
265 result = -ENOMEM;
266 break;
267 }
268 pList->uItem = sList.uItem;
269 pBSS = &(pMgmt->sBSSList[0]);
Joe Perches281c7462013-03-18 10:44:51 -0700270 for (ii = 0, jj = 0; jj < MAX_BSS_NUM; jj++) {
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300271 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 Carpenter0d3eb2b2011-10-20 09:09:46 +0300276 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 meena08afcf92012-01-16 23:50:38 +0530282 if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo))
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300283 pList->sBSSIDList[ii].byNetType = INFRA;
mahendra singh meena08afcf92012-01-16 23:50:38 +0530284 else
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300285 pList->sBSSIDList[ii].byNetType = ADHOC;
mahendra singh meena08afcf92012-01-16 23:50:38 +0530286
287 if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo))
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300288 pList->sBSSIDList[ii].bWEPOn = true;
mahendra singh meena08afcf92012-01-16 23:50:38 +0530289 else
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300290 pList->sBSSIDList[ii].bWEPOn = false;
mahendra singh meena08afcf92012-01-16 23:50:38 +0530291
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300292 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 Perches48caf5a2014-08-17 09:17:04 -0700321 pr_debug("WLAN_CMD_STOP_MAC\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300322 netif_stop_queue(pDevice->dev);
323
324 spin_lock_irq(&pDevice->lock);
mahendra singh meena08afcf92012-01-16 23:50:38 +0530325 if (pDevice->bRadioOff == false)
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300326 CARDbRadioPowerOff(pDevice);
mahendra singh meena08afcf92012-01-16 23:50:38 +0530327
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300328 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 Perches48caf5a2014-08-17 09:17:04 -0700340 pr_debug("WLAN_CMD_START_MAC\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300341
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 Perches48caf5a2014-08-17 09:17:04 -0700353 pr_debug("WLAN_CMD_SET_HOSTAPD\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300354
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 Perches48caf5a2014-08-17 09:17:04 -0700361 pr_debug("Enable HOSTAP\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300362 } else {
363 result = -EFAULT;
364 break;
365 }
366 } else {
367 vt6655_hostap_set_hostapd(pDevice, 0, 1);
Joe Perches48caf5a2014-08-17 09:17:04 -0700368 pr_debug("Disable HOSTAP\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300369 }
370 break;
371
372 case WLAN_CMD_SET_HOSTAPD_STA:
Joe Perches48caf5a2014-08-17 09:17:04 -0700373 pr_debug("WLAN_CMD_SET_HOSTAPD_STA\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300374 break;
375
376 case WLAN_CMD_SET_802_1X:
Joe Perches48caf5a2014-08-17 09:17:04 -0700377 pr_debug("WLAN_CMD_SET_802_1X\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300378 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 Perches48caf5a2014-08-17 09:17:04 -0700385 pr_debug("Enable 802.1x\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300386 } else {
387 pDevice->bEnable8021x = false;
Joe Perches48caf5a2014-08-17 09:17:04 -0700388 pr_debug("Disable 802.1x\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300389 }
390 break;
391
392 case WLAN_CMD_SET_HOST_WEP:
Joe Perches48caf5a2014-08-17 09:17:04 -0700393 pr_debug("WLAN_CMD_SET_HOST_WEP\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300394 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 Perches48caf5a2014-08-17 09:17:04 -0700401 pr_debug("Enable HostWEP\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300402 } else {
403 pDevice->bEnableHostWEP = false;
Joe Perches48caf5a2014-08-17 09:17:04 -0700404 pr_debug("Disable HostWEP\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300405 }
406 break;
407
408 case WLAN_CMD_SET_WPA:
Joe Perches48caf5a2014-08-17 09:17:04 -0700409 pr_debug("WLAN_CMD_SET_WPA\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300410
411 if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
412 result = -EFAULT;
413 break;
414 }
415 if (sValue.dwValue == 1) {
Joe Perches48caf5a2014-08-17 09:17:04 -0700416 pr_debug("up wpadev\n");
Bjørn Mork314cb112013-08-30 18:08:52 +0200417 eth_hw_addr_inherit(pDevice->wpadev, pDevice->dev);
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300418 pDevice->bWPADEVUp = true;
419 } else {
Joe Perches48caf5a2014-08-17 09:17:04 -0700420 pr_debug("close wpadev\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300421 pDevice->bWPADEVUp = false;
422 }
423 break;
424
425 case WLAN_CMD_AP_START:
Joe Perches48caf5a2014-08-17 09:17:04 -0700426 pr_debug("WLAN_CMD_AP_START\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300427 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 Perches48caf5a2014-08-17 09:17:04 -0700440 pr_debug("ioct set to AP mode\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300441 } else {
Joe Perches48caf5a2014-08-17 09:17:04 -0700442 pr_debug("ioct BSS type not set to AP mode\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300443 result = -EFAULT;
444 break;
445 }
446
mahendra singh meena08afcf92012-01-16 23:50:38 +0530447 if (sStartAPCmd.wBBPType == PHY80211g)
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300448 pMgmt->byAPBBType = PHY_TYPE_11G;
mahendra singh meena08afcf92012-01-16 23:50:38 +0530449 else if (sStartAPCmd.wBBPType == PHY80211a)
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300450 pMgmt->byAPBBType = PHY_TYPE_11A;
mahendra singh meena08afcf92012-01-16 23:50:38 +0530451 else
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300452 pMgmt->byAPBBType = PHY_TYPE_11B;
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300453
454 pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid;
Dan Carpenter0c849b32011-10-20 09:10:09 +0300455 if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
456 return -EINVAL;
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300457 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 Perches48caf5a2014-08-17 09:17:04 -0700470 pr_debug("Share Key\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300471 } else {
472 pMgmt->bShareKeyAlgorithm = false;
Joe Perches48caf5a2014-08-17 09:17:04 -0700473 pr_debug("Open System\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300474 }
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 Perches48caf5a2014-08-17 09:17:04 -0700497 pr_debug("Support Rate= %*ph\n",
498 4, pMgmt->abyIBSSSuppRates + 2);
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300499
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 Wang2a58b192011-11-29 21:52:46 -0500529 if (sNodeList.uItem > (ULONG_MAX - sizeof(SNodeList)) / sizeof(SNodeItem)) {
530 result = -EINVAL;
531 break;
532 }
Silvio Frickeb47eb6c2014-04-12 02:30:25 +0200533 pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)),
534 GFP_ATOMIC);
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300535 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 Perches48caf5a2014-08-17 09:17:04 -0700554 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 Carpenter0d3eb2b2011-10-20 09:09:46 +0300560 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 Carpenter0d3eb2b2011-10-20 09:09:46 +0300577 default:
Joe Perches48caf5a2014-08-17 09:17:04 -0700578 pr_debug("Private command not support..\n");
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300579 }
Forest Bond5449c682009-04-25 10:30:44 -0400580
Dan Carpenter0d3eb2b2011-10-20 09:09:46 +0300581 return result;
Forest Bond5449c682009-04-25 10:30:44 -0400582}