staging: vt6656: Remove WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT macro
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / vt6656 / iwctl.c
CommitLineData
92b96797
FB
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: iwctl.c
20 *
21 * Purpose: wireless ext & ioctl functions
22 *
23 * Author: Lyndon Chen
24 *
25 * Date: July 5, 2006
26 *
27 * Functions:
28 *
29 * Revision History:
30 *
31 */
32
92b96797 33#include "device.h"
92b96797 34#include "ioctl.h"
92b96797 35#include "iocmd.h"
92b96797 36#include "mac.h"
92b96797 37#include "card.h"
92b96797 38#include "hostap.h"
92b96797 39#include "power.h"
92b96797 40#include "rf.h"
92b96797 41#include "iowpa.h"
92b96797 42#include "wpactl.h"
92b96797 43
92b96797 44#include <net/iw_handler.h>
92b96797 45
c5a415ca 46#define SUPPORTED_WIRELESS_EXT 18
92b96797 47
92b96797 48static const long frequency_list[] = {
48746d7f
JJ
49 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484,
50 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
51 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240,
52 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680,
53 5700, 5745, 5765, 5785, 5805, 5825
54};
92b96797 55
c91a8d5a 56static int msglevel = MSG_LEVEL_INFO;
92b96797 57
92b96797
FB
58struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev)
59{
1e28efa3 60 PSDevice pDevice = netdev_priv(dev);
92b96797
FB
61 long ldBm;
62
63 pDevice->wstats.status = pDevice->eOPMode;
f269d1c2 64 if (pDevice->scStatistic.LinkQuality > 100)
48746d7f 65 pDevice->scStatistic.LinkQuality = 100;
bd4208e9 66 pDevice->wstats.qual.qual =(BYTE)pDevice->scStatistic.LinkQuality;
92b96797
FB
67 RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm);
68 pDevice->wstats.qual.level = ldBm;
92b96797
FB
69 pDevice->wstats.qual.noise = 0;
70 pDevice->wstats.qual.updated = 1;
71 pDevice->wstats.discard.nwid = 0;
72 pDevice->wstats.discard.code = 0;
73 pDevice->wstats.discard.fragment = 0;
74 pDevice->wstats.discard.retries = pDevice->scStatistic.dwTsrErr;
75 pDevice->wstats.discard.misc = 0;
76 pDevice->wstats.miss.beacon = 0;
92b96797
FB
77 return &pDevice->wstats;
78}
79
92b96797 80/*
5a673637 81 * Wireless Handler: get protocol name
92b96797 82 */
921cd68b
JJ
83int iwctl_giwname(struct net_device *dev, struct iw_request_info *info,
84 char *wrq, char *extra)
92b96797
FB
85{
86 strcpy(wrq, "802.11-a/b/g");
87 return 0;
88}
89
92b96797 90/*
5a673637 91 * Wireless Handler: set scan
92b96797 92 */
921cd68b
JJ
93int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info,
94 struct iw_point *wrq, char *extra)
92b96797 95{
1a6dd0da 96 PSDevice pDevice = netdev_priv(dev);
c91a8d5a
JJ
97 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
98 struct iw_scan_req *req = (struct iw_scan_req *)extra;
99 BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
4063d060 100 PWLAN_IE_SSID pItemSSID = NULL;
92b96797 101
48746d7f
JJ
102 if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
103 return -EINVAL;
92b96797 104
48746d7f 105 PRINT_K(" SIOCSIWSCAN \n");
92b96797 106
48746d7f
JJ
107 if (pMgmt->eScanState == WMAC_IS_SCANNING) {
108 // In scanning..
109 PRINT_K("SIOCSIWSCAN(overlap??)-->In scanning...\n");
110 return -EAGAIN;
111 }
92b96797 112
5a673637
JJ
113 if (pDevice->byReAssocCount > 0) { // reject scan when re-associating!
114 // send scan event to wpa_Supplicant
48746d7f
JJ
115 union iwreq_data wrqu;
116 PRINT_K("wireless_send_event--->SIOCGIWSCAN(scan done)\n");
117 memset(&wrqu, 0, sizeof(wrqu));
118 wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
119 return 0;
120 }
92b96797
FB
121
122 spin_lock_irq(&pDevice->lock);
123
bd4208e9 124 BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
92b96797 125
5a673637 126 // mike add: active scan OR passive scan OR desire_ssid scan
f269d1c2 127 if (wrq->length == sizeof(struct iw_scan_req)) {
8c3337fe 128 if (wrq->flags & IW_SCAN_THIS_ESSID) { // desire_ssid scan
48746d7f
JJ
129 memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
130 pItemSSID = (PWLAN_IE_SSID)abyScanSSID;
131 pItemSSID->byElementID = WLAN_EID_SSID;
132 memcpy(pItemSSID->abySSID, req->essid, (int)req->essid_len);
133 if (pItemSSID->abySSID[req->essid_len - 1] == '\0') {
37f0777f 134 if (req->essid_len > 0)
48746d7f 135 pItemSSID->len = req->essid_len - 1;
0c5c7901 136 } else {
48746d7f 137 pItemSSID->len = req->essid_len;
0c5c7901 138 }
48746d7f 139 pMgmt->eScanType = WMAC_SCAN_PASSIVE;
37f0777f 140 PRINT_K("SIOCSIWSCAN:[desired_ssid=%s,len=%d]\n", ((PWLAN_IE_SSID)abyScanSSID)->abySSID,
48746d7f 141 ((PWLAN_IE_SSID)abyScanSSID)->len);
bd4208e9 142 bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID);
48746d7f
JJ
143 spin_unlock_irq(&pDevice->lock);
144
145 return 0;
8c3337fe 146 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { // passive scan
48746d7f
JJ
147 pMgmt->eScanType = WMAC_SCAN_PASSIVE;
148 }
8c3337fe 149 } else { // active scan
48746d7f
JJ
150 pMgmt->eScanType = WMAC_SCAN_ACTIVE;
151 }
92b96797 152
48746d7f 153 pMgmt->eScanType = WMAC_SCAN_PASSIVE;
bd4208e9 154 bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
92b96797
FB
155 spin_unlock_irq(&pDevice->lock);
156
157 return 0;
158}
159
92b96797
FB
160/*
161 * Wireless Handler : get scan results
162 */
921cd68b
JJ
163int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info,
164 struct iw_point *wrq, char *extra)
92b96797 165{
c91a8d5a
JJ
166 int ii;
167 int jj;
168 int kk;
1a6dd0da 169 PSDevice pDevice = netdev_priv(dev);
c91a8d5a
JJ
170 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
171 PKnownBSS pBSS;
172 PWLAN_IE_SSID pItemSSID;
173 PWLAN_IE_SUPP_RATES pSuppRates;
174 PWLAN_IE_SUPP_RATES pExtSuppRates;
92b96797
FB
175 char *current_ev = extra;
176 char *end_buf = extra + IW_SCAN_MAX_DATA;
177 char *current_val = NULL;
178 struct iw_event iwe;
179 long ldBm;
92b96797 180 char buf[MAX_WPA_IE_LEN * 2 + 30];
92b96797 181
48746d7f 182 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSCAN\n");
92b96797 183
48746d7f
JJ
184 if (pMgmt->eScanState == WMAC_IS_SCANNING) {
185 // In scanning..
92b96797
FB
186 return -EAGAIN;
187 }
188 pBSS = &(pMgmt->sBSSList[0]);
48746d7f 189 for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
92b96797
FB
190 if (current_ev >= end_buf)
191 break;
48746d7f
JJ
192 pBSS = &(pMgmt->sBSSList[jj]);
193 if (pBSS->bActive) {
5a673637 194 // ADD mac address
48746d7f
JJ
195 memset(&iwe, 0, sizeof(iwe));
196 iwe.cmd = SIOCGIWAP;
197 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
92b96797 198 memcpy(iwe.u.ap_addr.sa_data, pBSS->abyBSSID, WLAN_BSSID_LEN);
4063d060 199 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
5a673637 200 // ADD ssid
48746d7f
JJ
201 memset(&iwe, 0, sizeof(iwe));
202 iwe.cmd = SIOCGIWESSID;
203 pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
204 iwe.u.data.length = pItemSSID->len;
205 iwe.u.data.flags = 1;
37f0777f 206 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pItemSSID->abySSID);
5a673637 207 // ADD mode
48746d7f
JJ
208 memset(&iwe, 0, sizeof(iwe));
209 iwe.cmd = SIOCGIWMODE;
8c3337fe 210 if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo))
48746d7f 211 iwe.u.mode = IW_MODE_INFRA;
8c3337fe 212 else
48746d7f 213 iwe.u.mode = IW_MODE_ADHOC;
48746d7f 214 iwe.len = IW_EV_UINT_LEN;
37f0777f 215 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
5a673637 216 // ADD frequency
48746d7f
JJ
217 pSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abySuppRates;
218 pExtSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abyExtSuppRates;
219 memset(&iwe, 0, sizeof(iwe));
220 iwe.cmd = SIOCGIWFREQ;
221 iwe.u.freq.m = pBSS->uChannel;
222 iwe.u.freq.e = 0;
223 iwe.u.freq.i = 0;
37f0777f 224 current_ev = iwe_stream_add_event(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
92b96797 225 {
48746d7f 226 int f = (int)pBSS->uChannel - 1;
aeadd58d
JJ
227 if (f < 0)
228 f = 0;
48746d7f
JJ
229 iwe.u.freq.m = frequency_list[f] * 100000;
230 iwe.u.freq.e = 1;
92b96797 231 }
37f0777f 232 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
5a673637 233 // ADD quality
48746d7f
JJ
234 memset(&iwe, 0, sizeof(iwe));
235 iwe.cmd = IWEVQUAL;
236 RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
237 iwe.u.qual.level = ldBm;
238 iwe.u.qual.noise = 0;
465711b3 239
4063d060 240 if (-ldBm < 50)
92b96797 241 iwe.u.qual.qual = 100;
8c3337fe 242 else if (-ldBm > 90)
48746d7f 243 iwe.u.qual.qual = 0;
8c3337fe 244 else
37f0777f 245 iwe.u.qual.qual = (40 - (-ldBm - 50)) * 100 / 40;
37f0777f 246 iwe.u.qual.updated = 7;
92b96797 247
37f0777f 248 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
5a673637 249 // ADD encryption
48746d7f
JJ
250 memset(&iwe, 0, sizeof(iwe));
251 iwe.cmd = SIOCGIWENCODE;
252 iwe.u.data.length = 0;
8c3337fe 253 if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo))
37f0777f 254 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
8c3337fe 255 else
48746d7f 256 iwe.u.data.flags = IW_ENCODE_DISABLED;
37f0777f 257 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pItemSSID->abySSID);
48746d7f
JJ
258
259 memset(&iwe, 0, sizeof(iwe));
260 iwe.cmd = SIOCGIWRATE;
261 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
262 current_val = current_ev + IW_EV_LCP_LEN;
263
37f0777f 264 for (kk = 0; kk < 12; kk++) {
48746d7f
JJ
265 if (pSuppRates->abyRates[kk] == 0)
266 break;
267 // Bit rate given in 500 kb/s units (+ 0x80)
268 iwe.u.bitrate.value = ((pSuppRates->abyRates[kk] & 0x7f) * 500000);
37f0777f 269 current_val = iwe_stream_add_value(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
48746d7f 270 }
37f0777f 271 for (kk = 0; kk < 8; kk++) {
48746d7f
JJ
272 if (pExtSuppRates->abyRates[kk] == 0)
273 break;
274 // Bit rate given in 500 kb/s units (+ 0x80)
275 iwe.u.bitrate.value = ((pExtSuppRates->abyRates[kk] & 0x7f) * 500000);
37f0777f 276 current_val = iwe_stream_add_value(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
48746d7f
JJ
277 }
278
f269d1c2 279 if ((current_val - current_ev) > IW_EV_LCP_LEN)
48746d7f
JJ
280 current_ev = current_val;
281
282 memset(&iwe, 0, sizeof(iwe));
283 iwe.cmd = IWEVCUSTOM;
284 sprintf(buf, "bcn_int=%d", pBSS->wBeaconInterval);
285 iwe.u.data.length = strlen(buf);
37f0777f 286 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, buf);
48746d7f
JJ
287
288 if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) {
289 memset(&iwe, 0, sizeof(iwe));
290 iwe.cmd = IWEVGENIE;
291 iwe.u.data.length = pBSS->wWPALen;
37f0777f 292 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pBSS->byWPAIE);
48746d7f
JJ
293 }
294
295 if ((pBSS->wRSNLen > 0) && (pBSS->wRSNLen <= MAX_WPA_IE_LEN)) {
296 memset(&iwe, 0, sizeof(iwe));
297 iwe.cmd = IWEVGENIE;
298 iwe.u.data.length = pBSS->wRSNLen;
37f0777f 299 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pBSS->byRSNIE);
48746d7f 300 }
48746d7f 301 }
5a673637 302 } // for
92b96797
FB
303 wrq->length = current_ev - extra;
304 return 0;
92b96797
FB
305}
306
92b96797 307/*
5a673637 308 * Wireless Handler: set frequence or channel
92b96797 309 */
921cd68b
JJ
310int iwctl_siwfreq(struct net_device *dev, struct iw_request_info *info,
311 struct iw_freq *wrq, char *extra)
92b96797 312{
1a6dd0da 313 PSDevice pDevice = netdev_priv(dev);
92b96797
FB
314 int rc = 0;
315
48746d7f 316 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFREQ \n");
92b96797
FB
317
318 // If setting by frequency, convert to a channel
8c3337fe 319 if ((wrq->e == 1) && (wrq->m >= (int)2.412e8) &&
bd4208e9 320 (wrq->m <= (int)2.487e8)) {
92b96797
FB
321 int f = wrq->m / 100000;
322 int c = 0;
f269d1c2 323 while ((c < 14) && (f != frequency_list[c]))
92b96797
FB
324 c++;
325 wrq->e = 0;
326 wrq->m = c + 1;
327 }
328 // Setting by channel number
8c3337fe 329 if ((wrq->m > 14) || (wrq->e > 0)) {
92b96797 330 rc = -EOPNOTSUPP;
8c3337fe 331 } else {
92b96797 332 int channel = wrq->m;
f269d1c2 333 if ((channel < 1) || (channel > 14)) {
92b96797
FB
334 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: New channel value of %d is invalid!\n", dev->name, wrq->m);
335 rc = -EINVAL;
336 } else {
48746d7f
JJ
337 // Yes ! We can set it !!!
338 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set to channel = %d\n", channel);
339 pDevice->uChannel = channel;
92b96797
FB
340 }
341 }
92b96797
FB
342 return rc;
343}
344
345/*
5a673637 346 * Wireless Handler: get frequence or channel
92b96797 347 */
921cd68b
JJ
348int iwctl_giwfreq(struct net_device *dev, struct iw_request_info *info,
349 struct iw_freq *wrq, char *extra)
92b96797 350{
1a6dd0da 351 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 352 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797 353
48746d7f 354 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFREQ \n");
92b96797
FB
355
356#ifdef WEXT_USECHANNELS
357 wrq->m = (int)pMgmt->uCurrChannel;
358 wrq->e = 0;
359#else
360 {
361 int f = (int)pMgmt->uCurrChannel - 1;
f269d1c2 362 if (f < 0)
48746d7f 363 f = 0;
92b96797
FB
364 wrq->m = frequency_list[f] * 100000;
365 wrq->e = 1;
366 }
367#endif
92b96797
FB
368 return 0;
369}
370
371/*
5a673637 372 * Wireless Handler: set operation mode
92b96797 373 */
921cd68b
JJ
374int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info,
375 __u32 *wmode, char *extra)
92b96797 376{
1a6dd0da 377 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 378 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
48746d7f 379 int rc = 0;
92b96797 380
48746d7f 381 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMODE \n");
92b96797 382
48746d7f
JJ
383 if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP && pDevice->bEnableHostapd) {
384 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Can't set operation mode, hostapd is running \n");
385 return rc;
386 }
92b96797 387
f269d1c2 388 switch (*wmode) {
92b96797 389 case IW_MODE_ADHOC:
48746d7f
JJ
390 if (pMgmt->eConfigMode != WMAC_CONFIG_IBSS_STA) {
391 pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
8c3337fe 392 if (pDevice->flags & DEVICE_FLAGS_OPENED)
48746d7f 393 pDevice->bCommit = TRUE;
92b96797 394 }
48746d7f 395 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc \n");
92b96797
FB
396 break;
397 case IW_MODE_AUTO:
398 case IW_MODE_INFRA:
48746d7f
JJ
399 if (pMgmt->eConfigMode != WMAC_CONFIG_ESS_STA) {
400 pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
8c3337fe 401 if (pDevice->flags & DEVICE_FLAGS_OPENED)
48746d7f 402 pDevice->bCommit = TRUE;
92b96797 403 }
48746d7f 404 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure \n");
92b96797
FB
405 break;
406 case IW_MODE_MASTER:
407
48746d7f 408 pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
92b96797
FB
409 rc = -EOPNOTSUPP;
410 break;
411
48746d7f
JJ
412 if (pMgmt->eConfigMode != WMAC_CONFIG_AP) {
413 pMgmt->eConfigMode = WMAC_CONFIG_AP;
8c3337fe 414 if (pDevice->flags & DEVICE_FLAGS_OPENED)
48746d7f 415 pDevice->bCommit = TRUE;
92b96797 416 }
48746d7f 417 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point \n");
92b96797
FB
418 break;
419
420 case IW_MODE_REPEAT:
48746d7f 421 pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
92b96797
FB
422 rc = -EOPNOTSUPP;
423 break;
424 default:
425 rc = -EINVAL;
426 }
427
428 return rc;
429}
430
431/*
5a673637 432 * Wireless Handler: get operation mode
92b96797 433 */
921cd68b
JJ
434void iwctl_giwmode(struct net_device *dev, struct iw_request_info *info,
435 __u32 *wmode, char *extra)
92b96797 436{
1a6dd0da 437 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 438 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797 439
48746d7f 440 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWMODE \n");
92b96797
FB
441 // If not managed, assume it's ad-hoc
442 switch (pMgmt->eConfigMode) {
443 case WMAC_CONFIG_ESS_STA:
444 *wmode = IW_MODE_INFRA;
445 break;
446 case WMAC_CONFIG_IBSS_STA:
48746d7f 447 *wmode = IW_MODE_ADHOC;
92b96797
FB
448 break;
449 case WMAC_CONFIG_AUTO:
450 *wmode = IW_MODE_INFRA;
451 break;
452 case WMAC_CONFIG_AP:
453 *wmode = IW_MODE_MASTER;
454 break;
455 default:
456 *wmode = IW_MODE_ADHOC;
457 }
92b96797
FB
458}
459
92b96797 460/*
5a673637 461 * Wireless Handler: get capability range
92b96797 462 */
921cd68b
JJ
463void iwctl_giwrange(struct net_device *dev, struct iw_request_info *info,
464 struct iw_point *wrq, char *extra)
92b96797 465{
bd4208e9 466 struct iw_range *range = (struct iw_range *)extra;
c91a8d5a
JJ
467 int i;
468 int k;
469 BYTE abySupportedRates[13] = {
470 0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
471 0x60, 0x6C, 0x90
472 };
92b96797 473
48746d7f 474 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRANGE\n");
92b96797
FB
475 if (wrq->pointer) {
476 wrq->length = sizeof(struct iw_range);
477 memset(range, 0, sizeof(struct iw_range));
478 range->min_nwid = 0x0000;
479 range->max_nwid = 0x0000;
480 range->num_channels = 14;
481 // Should be based on cap_rid.country to give only
5a673637 482 // what the current card support
92b96797 483 k = 0;
33d33e42 484 for (i = 0; i < 14; i++) {
92b96797
FB
485 range->freq[k].i = i + 1; // List index
486 range->freq[k].m = frequency_list[i] * 100000;
487 range->freq[k++].e = 1; // Values in table in MHz -> * 10^5 * 10
488 }
489 range->num_frequency = k;
490 // Hum... Should put the right values there
48746d7f 491 range->max_qual.qual = 100;
92b96797
FB
492 range->max_qual.level = 0;
493 range->max_qual.noise = 0;
494 range->sensitivity = 255;
495
37f0777f 496 for (i = 0; i < 13; i++) {
92b96797 497 range->bitrate[i] = abySupportedRates[i] * 500000;
f269d1c2 498 if (range->bitrate[i] == 0)
92b96797
FB
499 break;
500 }
501 range->num_bitrates = i;
502
503 // Set an indication of the max TCP throughput
504 // in bit/s that we can expect using this interface.
505 // May be use for QoS stuff... Jean II
f269d1c2 506 if (i > 2)
92b96797
FB
507 range->throughput = 5 * 1000 * 1000;
508 else
509 range->throughput = 1.5 * 1000 * 1000;
510
511 range->min_rts = 0;
512 range->max_rts = 2312;
513 range->min_frag = 256;
514 range->max_frag = 2312;
515
48746d7f
JJ
516 // the encoding capabilities
517 range->num_encoding_sizes = 3;
518 // 64(40) bits WEP
519 range->encoding_size[0] = 5;
520 // 128(104) bits WEP
521 range->encoding_size[1] = 13;
522 // 256 bits for WPA-PSK
523 range->encoding_size[2] = 32;
524 // 4 keys are allowed
525 range->max_encoding_tokens = 4;
92b96797 526
48746d7f
JJ
527 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
528 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
92b96797 529
92b96797 530 range->min_pmp = 0;
5a673637 531 range->max_pmp = 1000000; // 1 secs
92b96797 532 range->min_pmt = 0;
5a673637 533 range->max_pmt = 1000000; // 1 secs
92b96797
FB
534 range->pmp_flags = IW_POWER_PERIOD;
535 range->pmt_flags = IW_POWER_TIMEOUT;
536 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
537
538 // Transmit Power - values are in mW
48746d7f 539 range->txpower[0] = 100;
92b96797
FB
540 range->num_txpower = 1;
541 range->txpower_capa = IW_TXPOW_MWATT;
92b96797
FB
542 range->we_version_source = SUPPORTED_WIRELESS_EXT;
543 range->we_version_compiled = WIRELESS_EXT;
544 range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
545 range->retry_flags = IW_RETRY_LIMIT;
546 range->r_time_flags = IW_RETRY_LIFETIME;
547 range->min_retry = 1;
548 range->max_retry = 65535;
549 range->min_r_time = 1024;
550 range->max_r_time = 65535 * 1024;
92b96797
FB
551 // Experimental measurements - boundary 11/5.5 Mb/s
552 // Note : with or without the (local->rssi), results
553 // are somewhat different. - Jean II
554 range->avg_qual.qual = 6;
5a673637 555 range->avg_qual.level = 176; // -80 dBm
92b96797 556 range->avg_qual.noise = 0;
92b96797 557 }
92b96797
FB
558}
559
92b96797
FB
560/*
561 * Wireless Handler : set ap mac address
562 */
921cd68b
JJ
563int iwctl_siwap(struct net_device *dev, struct iw_request_info *info,
564 struct sockaddr *wrq, char *extra)
92b96797 565{
1a6dd0da 566 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 567 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
48746d7f 568 int rc = 0;
c91a8d5a 569 BYTE ZeroBSSID[WLAN_BSSID_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
92b96797 570
48746d7f 571 PRINT_K(" SIOCSIWAP \n");
92b96797 572
0c5c7901 573 if (wrq->sa_family != ARPHRD_ETHER) {
92b96797 574 rc = -EINVAL;
0c5c7901 575 } else {
92b96797 576 memcpy(pMgmt->abyDesireBSSID, wrq->sa_data, 6);
5a673637 577 // mike: add
48746d7f 578 if ((is_broadcast_ether_addr(pMgmt->abyDesireBSSID)) ||
37f0777f 579 (memcmp(pMgmt->abyDesireBSSID, ZeroBSSID, 6) == 0)) {
48746d7f
JJ
580 PRINT_K("SIOCSIWAP:invalid desired BSSID return!\n");
581 return rc;
582 }
5a673637
JJ
583 // mike add: if desired AP is hidden ssid(there are
584 // two same BSSID in list), then ignore,because you
585 // don't known which one to be connect with??
48746d7f 586 {
c91a8d5a
JJ
587 unsigned ii;
588 unsigned uSameBssidNum = 0;
48746d7f
JJ
589 for (ii = 0; ii < MAX_BSS_NUM; ii++) {
590 if (pMgmt->sBSSList[ii].bActive &&
591 !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID,
592 pMgmt->abyDesireBSSID)) {
593 uSameBssidNum++;
594 }
595 }
f269d1c2 596 if (uSameBssidNum >= 2) { //hit: desired AP is in hidden ssid mode!!!
48746d7f
JJ
597 PRINT_K("SIOCSIWAP:ignore for desired AP in hidden mode\n");
598 return rc;
599 }
600 }
601
8c3337fe 602 if (pDevice->flags & DEVICE_FLAGS_OPENED)
48746d7f 603 pDevice->bCommit = TRUE;
92b96797
FB
604 }
605 return rc;
606}
607
608/*
5a673637 609 * Wireless Handler: get ap mac address
92b96797 610 */
921cd68b
JJ
611int iwctl_giwap(struct net_device *dev, struct iw_request_info *info,
612 struct sockaddr *wrq, char *extra)
92b96797 613{
1a6dd0da 614 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 615 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797 616
48746d7f 617 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAP \n");
92b96797 618
48746d7f 619 memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6);
92b96797 620
48746d7f
JJ
621 if ((pDevice->bLinkPass == FALSE) && (pMgmt->eCurrMode != WMAC_MODE_ESS_AP))
622 memset(wrq->sa_data, 0, 6);
92b96797 623
8c3337fe 624 if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)
48746d7f 625 memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6);
92b96797
FB
626
627 wrq->sa_family = ARPHRD_ETHER;
92b96797 628 return 0;
92b96797
FB
629}
630
92b96797 631/*
5a673637 632 * Wireless Handler: get ap list
92b96797 633 */
921cd68b
JJ
634int iwctl_giwaplist(struct net_device *dev, struct iw_request_info *info,
635 struct iw_point *wrq, char *extra)
92b96797 636{
c91a8d5a
JJ
637 int ii;
638 int jj;
639 int rc = 0;
92b96797
FB
640 struct sockaddr sock[IW_MAX_AP];
641 struct iw_quality qual[IW_MAX_AP];
1a6dd0da 642 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 643 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797 644
48746d7f 645 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAPLIST \n");
92b96797
FB
646 // Only super-user can see AP list
647
648 if (!capable(CAP_NET_ADMIN)) {
649 rc = -EPERM;
650 return rc;
651 }
652
653 if (wrq->pointer) {
92b96797
FB
654 PKnownBSS pBSS = &(pMgmt->sBSSList[0]);
655
656 for (ii = 0, jj= 0; ii < MAX_BSS_NUM; ii++) {
48746d7f
JJ
657 pBSS = &(pMgmt->sBSSList[ii]);
658 if (!pBSS->bActive)
659 continue;
37f0777f 660 if (jj >= IW_MAX_AP)
48746d7f 661 break;
92b96797
FB
662 memcpy(sock[jj].sa_data, pBSS->abyBSSID, 6);
663 sock[jj].sa_family = ARPHRD_ETHER;
664 qual[jj].level = pBSS->uRSSI;
665 qual[jj].qual = qual[jj].noise = 0;
666 qual[jj].updated = 2;
667 jj++;
668 }
669
a0a1f61a 670 wrq->flags = 1; // Should be defined
92b96797 671 wrq->length = jj;
37f0777f
JJ
672 memcpy(extra, sock, sizeof(struct sockaddr) * jj);
673 memcpy(extra + sizeof(struct sockaddr) * jj, qual, sizeof(struct iw_quality) * jj);
92b96797 674 }
92b96797
FB
675 return rc;
676}
677
92b96797 678/*
5a673637 679 * Wireless Handler: set essid
92b96797 680 */
921cd68b
JJ
681int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
682 struct iw_point *wrq, char *extra)
92b96797 683{
1a6dd0da 684 PSDevice pDevice = netdev_priv(dev);
c91a8d5a
JJ
685 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
686 PWLAN_IE_SSID pItemSSID;
92b96797 687
48746d7f
JJ
688 if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
689 return -EINVAL;
92b96797 690
48746d7f 691 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWESSID :\n");
92b96797 692
48746d7f 693 pDevice->fWPA_Authened = FALSE;
92b96797 694 // Check if we asked for `any'
f269d1c2 695 if (wrq->flags == 0) {
92b96797
FB
696 // Just send an empty SSID list
697 memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
48746d7f
JJ
698 memset(pMgmt->abyDesireBSSID, 0xFF,6);
699 PRINT_K("set essid to 'any' \n");
37f0777f 700 // Unknown desired AP, so here need not associate??
48746d7f 701 return 0;
92b96797
FB
702 } else {
703 // Set the SSID
704 memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
48746d7f
JJ
705 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
706 pItemSSID->byElementID = WLAN_EID_SSID;
92b96797
FB
707
708 memcpy(pItemSSID->abySSID, extra, wrq->length);
48746d7f 709 if (pItemSSID->abySSID[wrq->length - 1] == '\0') {
f269d1c2 710 if (wrq->length>0)
48746d7f 711 pItemSSID->len = wrq->length - 1;
8c3337fe 712 } else {
48746d7f 713 pItemSSID->len = wrq->length;
8c3337fe 714 }
37f0777f 715 PRINT_K("set essid to %s \n", pItemSSID->abySSID);
92b96797 716
5a673637 717 // mike: need clear desiredBSSID
f269d1c2 718 if (pItemSSID->len==0) {
37f0777f 719 memset(pMgmt->abyDesireBSSID, 0xFF, 6);
48746d7f
JJ
720 return 0;
721 }
92b96797 722
5a673637
JJ
723 // Wext wil order another command of siwap to link
724 // with desired AP, so here need not associate??
f269d1c2 725 if (pDevice->bWPASuppWextEnabled == TRUE) {
48746d7f 726 /*******search if in hidden ssid mode ****/
da06f7db
JJ
727 PKnownBSS pCurr = NULL;
728 BYTE abyTmpDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
729 unsigned ii;
730 unsigned uSameBssidNum = 0;
731
37f0777f 732 memcpy(abyTmpDesireSSID, pMgmt->abyDesireSSID, sizeof(abyTmpDesireSSID));
da06f7db
JJ
733 pCurr = BSSpSearchBSSList(pDevice, NULL,
734 abyTmpDesireSSID,
37f0777f 735 pDevice->eConfigPHYMode);
da06f7db 736
37f0777f 737 if (pCurr == NULL) {
da06f7db 738 PRINT_K("SIOCSIWESSID:hidden ssid site survey before associate.......\n");
bd4208e9 739 vResetCommandTimer((void *)pDevice);
da06f7db 740 pMgmt->eScanType = WMAC_SCAN_ACTIVE;
bd4208e9 741 bScheduleCommand((void *)pDevice,
da06f7db
JJ
742 WLAN_CMD_BSSID_SCAN,
743 pMgmt->abyDesireSSID);
bd4208e9 744 bScheduleCommand((void *)pDevice,
da06f7db
JJ
745 WLAN_CMD_SSID,
746 pMgmt->abyDesireSSID);
8c3337fe 747 } else { // mike: to find out if that desired SSID is a
5a673637
JJ
748 // hidden-ssid AP, by means of judging if there
749 // are two same BSSID exist in list ?
da06f7db
JJ
750 for (ii = 0; ii < MAX_BSS_NUM; ii++) {
751 if (pMgmt->sBSSList[ii].bActive &&
752 !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID,
753 pCurr->abyBSSID)) {
754 uSameBssidNum++;
755 }
756 }
5a673637 757 if (uSameBssidNum >= 2) { // hit: desired AP is in hidden ssid mode!!!
da06f7db 758 PRINT_K("SIOCSIWESSID:hidden ssid directly associate.......\n");
bd4208e9 759 vResetCommandTimer((void *)pDevice);
5a673637 760 pMgmt->eScanType = WMAC_SCAN_PASSIVE; // this scan type, you'll submit scan result!
bd4208e9 761 bScheduleCommand((void *)pDevice,
48746d7f
JJ
762 WLAN_CMD_BSSID_SCAN,
763 pMgmt->abyDesireSSID);
bd4208e9 764 bScheduleCommand((void *)pDevice,
48746d7f
JJ
765 WLAN_CMD_SSID,
766 pMgmt->abyDesireSSID);
767 }
48746d7f
JJ
768 }
769 return 0;
770 }
48746d7f
JJ
771
772 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s \n", pItemSSID->abySSID);
92b96797
FB
773 }
774
8c3337fe 775 if (pDevice->flags & DEVICE_FLAGS_OPENED)
48746d7f 776 pDevice->bCommit = TRUE;
8c3337fe 777
92b96797
FB
778 return 0;
779}
780
92b96797 781/*
5a673637 782 * Wireless Handler: get essid
92b96797 783 */
921cd68b
JJ
784void iwctl_giwessid(struct net_device *dev, struct iw_request_info *info,
785 struct iw_point *wrq, char *extra)
92b96797 786{
1a6dd0da 787 PSDevice pDevice = netdev_priv(dev);
c91a8d5a
JJ
788 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
789 PWLAN_IE_SSID pItemSSID;
92b96797 790
48746d7f 791 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWESSID \n");
92b96797 792
5a673637
JJ
793 // Note: if wrq->u.data.flags != 0, we should get the relevant
794 // SSID from the SSID list...
92b96797
FB
795
796 // Get the current SSID
48746d7f 797 pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
37f0777f 798 memcpy(extra, pItemSSID->abySSID, pItemSSID->len);
92b96797 799 extra[pItemSSID->len] = '\0';
465711b3 800
92b96797 801 wrq->length = pItemSSID->len;
92b96797 802 wrq->flags = 1; // active
92b96797
FB
803}
804
805/*
5a673637 806 * Wireless Handler: set data rate
92b96797 807 */
921cd68b
JJ
808int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info,
809 struct iw_param *wrq, char *extra)
92b96797 810{
1a6dd0da 811 PSDevice pDevice = netdev_priv(dev);
48746d7f 812 int rc = 0;
c91a8d5a
JJ
813 u8 brate = 0;
814 int i;
815 BYTE abySupportedRates[13] = {
816 0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
817 0x60, 0x6C, 0x90
818 };
92b96797 819
48746d7f
JJ
820 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE \n");
821 if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
822 rc = -EINVAL;
823 return rc;
824 }
92b96797 825
5a673637 826 // First: get a valid bit rate value
92b96797
FB
827
828 // Which type of value
37f0777f 829 if ((wrq->value < 13) && (wrq->value >= 0)) {
92b96797
FB
830 // Setting by rate index
831 // Find value in the magic rate table
832 brate = wrq->value;
833 } else {
834 // Setting by frequency value
37f0777f 835 u8 normvalue = (u8)(wrq->value/500000);
92b96797
FB
836
837 // Check if rate is valid
37f0777f 838 for (i = 0; i < 13; i++) {
f269d1c2 839 if (normvalue == abySupportedRates[i]) {
92b96797
FB
840 brate = i;
841 break;
842 }
843 }
844 }
845 // -1 designed the max rate (mostly auto mode)
f269d1c2 846 if (wrq->value == -1) {
92b96797 847 // Get the highest available rate
37f0777f 848 for (i = 0; i < 13; i++) {
f269d1c2 849 if (abySupportedRates[i] == 0)
92b96797
FB
850 break;
851 }
f269d1c2 852 if (i != 0)
92b96797
FB
853 brate = i - 1;
854
855 }
856 // Check that it is valid
857 // brate is index of abySupportedRates[]
f269d1c2 858 if (brate > 13 ) {
92b96797
FB
859 rc = -EINVAL;
860 return rc;
861 }
862
863 // Now, check if we want a fixed or auto value
f269d1c2 864 if (wrq->fixed != 0) {
92b96797
FB
865 // Fixed mode
866 // One rate, fixed
867 pDevice->bFixRate = TRUE;
37f0777f 868 if ((pDevice->byBBType == BB_TYPE_11B) && (brate > 3)) {
48746d7f 869 pDevice->uConnectionRate = 3;
8c3337fe 870 } else {
48746d7f
JJ
871 pDevice->uConnectionRate = brate;
872 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d \n", pDevice->uConnectionRate);
873 }
0c5c7901 874 } else {
48746d7f
JJ
875 pDevice->bFixRate = FALSE;
876 pDevice->uConnectionRate = 13;
877 }
92b96797
FB
878
879 return rc;
880}
881
882/*
5a673637 883 * Wireless Handler: get data rate
92b96797 884 */
921cd68b
JJ
885void iwctl_giwrate(struct net_device *dev, struct iw_request_info *info,
886 struct iw_param *wrq, char *extra)
92b96797 887{
1a6dd0da 888 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 889 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797 890
48746d7f
JJ
891 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRATE \n");
892 {
c91a8d5a
JJ
893 BYTE abySupportedRates[13] = {
894 0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30,
895 0x48, 0x60, 0x6C, 0x90
896 };
48746d7f 897 int brate = 0;
c91a8d5a 898
92b96797 899 if (pDevice->uConnectionRate < 13) {
48746d7f 900 brate = abySupportedRates[pDevice->uConnectionRate];
8c3337fe 901 } else {
48746d7f
JJ
902 if (pDevice->byBBType == BB_TYPE_11B)
903 brate = 0x16;
904 if (pDevice->byBBType == BB_TYPE_11G)
905 brate = 0x6C;
906 if (pDevice->byBBType == BB_TYPE_11A)
907 brate = 0x6C;
908 }
48746d7f
JJ
909 if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
910 if (pDevice->byBBType == BB_TYPE_11B)
911 brate = 0x16;
912 if (pDevice->byBBType == BB_TYPE_11G)
913 brate = 0x6C;
914 if (pDevice->byBBType == BB_TYPE_11A)
915 brate = 0x6C;
916 }
92b96797 917 if (pDevice->uConnectionRate == 13)
48746d7f
JJ
918 brate = abySupportedRates[pDevice->wCurrentRate];
919 wrq->value = brate * 500000;
920 // If more than one rate, set auto
921 if (pDevice->bFixRate == TRUE)
922 wrq->fixed = TRUE;
923 }
92b96797
FB
924}
925
92b96797 926/*
5a673637 927 * Wireless Handler: set rts threshold
92b96797 928 */
921cd68b 929int iwctl_siwrts(struct net_device *dev, struct iw_param *wrq)
92b96797 930{
1a6dd0da 931 PSDevice pDevice = netdev_priv(dev);
92b96797 932
2fdde902
MPS
933 if ((wrq->value < 0 || wrq->value > 2312) && !wrq->disabled)
934 return -EINVAL;
92b96797 935
2fdde902
MPS
936 else if (wrq->disabled)
937 pDevice->wRTSThreshold = 2312;
2fdde902
MPS
938 else
939 pDevice->wRTSThreshold = wrq->value;
92b96797
FB
940
941 return 0;
942}
943
944/*
5a673637 945 * Wireless Handler: get rts
92b96797 946 */
921cd68b
JJ
947int iwctl_giwrts(struct net_device *dev, struct iw_request_info *info,
948 struct iw_param *wrq, char *extra)
92b96797 949{
1a6dd0da 950 PSDevice pDevice = netdev_priv(dev);
92b96797 951
48746d7f 952 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRTS \n");
92b96797
FB
953 wrq->value = pDevice->wRTSThreshold;
954 wrq->disabled = (wrq->value >= 2312);
955 wrq->fixed = 1;
92b96797
FB
956 return 0;
957}
958
959/*
5a673637 960 * Wireless Handler: set fragment threshold
92b96797 961 */
921cd68b
JJ
962int iwctl_siwfrag(struct net_device *dev, struct iw_request_info *info,
963 struct iw_param *wrq, char *extra)
92b96797 964{
1a6dd0da 965 PSDevice pDevice = netdev_priv(dev);
48746d7f
JJ
966 int rc = 0;
967 int fthr = wrq->value;
92b96797 968
48746d7f 969 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFRAG \n");
92b96797 970
48746d7f 971 if (wrq->disabled)
92b96797 972 fthr = 2312;
f269d1c2 973 if ((fthr < 256) || (fthr > 2312)) {
92b96797 974 rc = -EINVAL;
8c3337fe 975 } else {
5a673637 976 fthr &= ~0x1; // Get an even value
48746d7f
JJ
977 pDevice->wFragmentationThreshold = (u16)fthr;
978 }
92b96797
FB
979 return rc;
980}
981
982/*
5a673637 983 * Wireless Handler: get fragment threshold
92b96797 984 */
921cd68b
JJ
985int iwctl_giwfrag(struct net_device *dev, struct iw_request_info *info,
986 struct iw_param *wrq, char *extra)
92b96797 987{
1a6dd0da 988 PSDevice pDevice = netdev_priv(dev);
92b96797 989
48746d7f 990 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFRAG \n");
92b96797
FB
991 wrq->value = pDevice->wFragmentationThreshold;
992 wrq->disabled = (wrq->value >= 2312);
993 wrq->fixed = 1;
92b96797
FB
994 return 0;
995}
996
92b96797 997/*
5a673637 998 * Wireless Handler: set retry threshold
92b96797 999 */
921cd68b
JJ
1000int iwctl_siwretry(struct net_device *dev, struct iw_request_info *info,
1001 struct iw_param *wrq, char *extra)
92b96797 1002{
1a6dd0da 1003 PSDevice pDevice = netdev_priv(dev);
48746d7f 1004 int rc = 0;
92b96797 1005
48746d7f 1006 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRETRY \n");
92b96797
FB
1007
1008 if (wrq->disabled) {
1009 rc = -EINVAL;
1010 return rc;
1011 }
1012
1013 if (wrq->flags & IW_RETRY_LIMIT) {
8c3337fe 1014 if (wrq->flags & IW_RETRY_MAX) {
92b96797 1015 pDevice->byLongRetryLimit = wrq->value;
8c3337fe 1016 } else if (wrq->flags & IW_RETRY_MIN) {
92b96797 1017 pDevice->byShortRetryLimit = wrq->value;
8c3337fe 1018 } else {
92b96797
FB
1019 // No modifier : set both
1020 pDevice->byShortRetryLimit = wrq->value;
1021 pDevice->byLongRetryLimit = wrq->value;
1022 }
1023 }
8c3337fe 1024 if (wrq->flags & IW_RETRY_LIFETIME)
92b96797 1025 pDevice->wMaxTransmitMSDULifetime = wrq->value;
92b96797
FB
1026 return rc;
1027}
1028
1029/*
5a673637 1030 * Wireless Handler: get retry threshold
92b96797 1031 */
921cd68b
JJ
1032int iwctl_giwretry(struct net_device *dev, struct iw_request_info *info,
1033 struct iw_param *wrq, char *extra)
92b96797 1034{
1a6dd0da 1035 PSDevice pDevice = netdev_priv(dev);
48746d7f 1036 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRETRY \n");
5a673637 1037 wrq->disabled = 0; // Can't be disabled
92b96797 1038
5a673637 1039 // Note: by default, display the min retry number
f269d1c2 1040 if ((wrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
92b96797 1041 wrq->flags = IW_RETRY_LIFETIME;
5a673637 1042 wrq->value = (int)pDevice->wMaxTransmitMSDULifetime; // ms
f269d1c2 1043 } else if ((wrq->flags & IW_RETRY_MAX)) {
92b96797
FB
1044 wrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
1045 wrq->value = (int)pDevice->byLongRetryLimit;
1046 } else {
1047 wrq->flags = IW_RETRY_LIMIT;
1048 wrq->value = (int)pDevice->byShortRetryLimit;
f269d1c2 1049 if ((int)pDevice->byShortRetryLimit != (int)pDevice->byLongRetryLimit)
92b96797
FB
1050 wrq->flags |= IW_RETRY_MIN;
1051 }
92b96797
FB
1052 return 0;
1053}
1054
92b96797 1055/*
5a673637 1056 * Wireless Handler: set encode mode
92b96797 1057 */
921cd68b
JJ
1058int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info,
1059 struct iw_point *wrq, char *extra)
92b96797 1060{
1a6dd0da 1061 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 1062 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797 1063 DWORD dwKeyIndex = (DWORD)(wrq->flags & IW_ENCODE_INDEX);
c91a8d5a
JJ
1064 int ii;
1065 int uu;
1066 int rc = 0;
92b96797
FB
1067 int index = (wrq->flags & IW_ENCODE_INDEX);
1068
48746d7f 1069 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE \n");
92b96797
FB
1070
1071 // Check the size of the key
1072 if (wrq->length > WLAN_WEP232_KEYLEN) {
1073 rc = -EINVAL;
48746d7f 1074 return rc;
92b96797
FB
1075 }
1076
1077 if (dwKeyIndex > WLAN_WEP_NKEYS) {
1078 rc = -EINVAL;
48746d7f
JJ
1079 return rc;
1080 }
92b96797 1081
48746d7f 1082 if (dwKeyIndex > 0)
92b96797
FB
1083 dwKeyIndex--;
1084
1085 // Send the key to the card
1086 if (wrq->length > 0) {
4063d060 1087 if (wrq->length == WLAN_WEP232_KEYLEN) {
48746d7f 1088 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n");
4063d060 1089 } else if (wrq->length == WLAN_WEP104_KEYLEN) {
48746d7f 1090 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n");
8c3337fe 1091 } else if (wrq->length == WLAN_WEP40_KEYLEN) {
48746d7f
JJ
1092 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex);
1093 }
1094 memset(pDevice->abyKey, 0, WLAN_WEP232_KEYLEN);
1095 memcpy(pDevice->abyKey, extra, wrq->length);
1096
1097 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyKey: ");
8c3337fe 1098 for (ii = 0; ii < wrq->length; ii++)
48746d7f 1099 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pDevice->abyKey[ii]);
48746d7f
JJ
1100
1101 if (pDevice->flags & DEVICE_FLAGS_OPENED) {
1102 spin_lock_irq(&pDevice->lock);
37f0777f 1103 KeybSetDefaultKey(pDevice,
48746d7f
JJ
1104 &(pDevice->sKey),
1105 dwKeyIndex | (1 << 31),
37f0777f 1106 wrq->length, NULL,
48746d7f 1107 pDevice->abyKey,
9a671f88 1108 KEY_CTL_WEP);
48746d7f
JJ
1109 spin_unlock_irq(&pDevice->lock);
1110 }
1111 pDevice->byKeyIndex = (BYTE)dwKeyIndex;
1112 pDevice->uKeyLength = wrq->length;
1113 pDevice->bTransmitKey = TRUE;
1114 pDevice->bEncryptionEnable = TRUE;
1115 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
92b96797 1116
5a673637 1117 // Do we want to just set the transmit key index?
8c3337fe 1118 if (index < 4) {
48746d7f 1119 pDevice->byKeyIndex = index;
2e9ab1e7 1120 } else if (!(wrq->flags & IW_ENCODE_MODE)) {
48746d7f
JJ
1121 rc = -EINVAL;
1122 return rc;
1123 }
92b96797
FB
1124 }
1125 // Read the flags
8c3337fe 1126 if (wrq->flags & IW_ENCODE_DISABLED) {
48746d7f 1127 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable WEP function\n");
92b96797 1128 pMgmt->bShareKeyAlgorithm = FALSE;
48746d7f
JJ
1129 pDevice->bEncryptionEnable = FALSE;
1130 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
1131 if (pDevice->flags & DEVICE_FLAGS_OPENED) {
1132 spin_lock_irq(&pDevice->lock);
1133 for (uu = 0; uu < MAX_KEY_TABLE; uu++)
1134 MACvDisableKeyEntry(pDevice, uu);
1135 spin_unlock_irq(&pDevice->lock);
1136 }
92b96797 1137 }
f269d1c2 1138 if (wrq->flags & IW_ENCODE_RESTRICTED) {
48746d7f 1139 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & ShareKey System\n");
92b96797
FB
1140 pMgmt->bShareKeyAlgorithm = TRUE;
1141 }
f269d1c2 1142 if (wrq->flags & IW_ENCODE_OPEN) {
48746d7f 1143 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & Open System\n");
92b96797
FB
1144 pMgmt->bShareKeyAlgorithm = FALSE;
1145 }
1146
37f0777f 1147 memset(pMgmt->abyDesireBSSID, 0xFF, 6);
f1426fd7 1148
92b96797
FB
1149 return rc;
1150}
1151
921cd68b
JJ
1152int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info,
1153 struct iw_point *wrq, char *extra)
92b96797 1154{
1a6dd0da 1155 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 1156 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797
FB
1157 char abyKey[WLAN_WEP232_KEYLEN];
1158
c91a8d5a
JJ
1159 unsigned index = (unsigned)(wrq->flags & IW_ENCODE_INDEX);
1160 PSKeyItem pKey = NULL;
92b96797
FB
1161
1162 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n");
1163
8c3337fe 1164 if (index > WLAN_WEP_NKEYS)
92b96797 1165 return -EINVAL;
37f0777f 1166 if (index < 1) { // get default key
8c3337fe 1167 if (pDevice->byKeyIndex < WLAN_WEP_NKEYS)
37f0777f 1168 index = pDevice->byKeyIndex;
8c3337fe 1169 else
37f0777f 1170 index = 0;
8c3337fe 1171 } else {
48746d7f 1172 index--;
8c3337fe 1173 }
92b96797
FB
1174
1175 memset(abyKey, 0, WLAN_WEP232_KEYLEN);
1176 // Check encryption mode
1177 wrq->flags = IW_ENCODE_NOKEY;
1178 // Is WEP enabled ???
1179 if (pDevice->bEncryptionEnable)
37f0777f 1180 wrq->flags |= IW_ENCODE_ENABLED;
92b96797 1181 else
37f0777f 1182 wrq->flags |= IW_ENCODE_DISABLED;
92b96797
FB
1183
1184 if (pMgmt->bShareKeyAlgorithm)
37f0777f 1185 wrq->flags |= IW_ENCODE_RESTRICTED;
92b96797 1186 else
37f0777f
JJ
1187 wrq->flags |= IW_ENCODE_OPEN;
1188 wrq->length = 0;
92b96797 1189
37f0777f 1190 if ((index == 0) && (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled ||
0c5c7901 1191 pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)) { // get wpa pairwise key
37f0777f 1192 if (KeybGetKey(&(pDevice->sKey), pMgmt->abyCurrBSSID, 0xffffffff, &pKey)) {
92b96797 1193 wrq->length = pKey->uKeyLength;
48746d7f
JJ
1194 memcpy(abyKey, pKey->abyKey, pKey->uKeyLength);
1195 memcpy(extra, abyKey, WLAN_WEP232_KEYLEN);
1196 }
8c3337fe 1197 } else if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (BYTE)index, &pKey)) {
48746d7f 1198 wrq->length = pKey->uKeyLength;
37f0777f
JJ
1199 memcpy(abyKey, pKey->abyKey, pKey->uKeyLength);
1200 memcpy(extra, abyKey, WLAN_WEP232_KEYLEN);
92b96797
FB
1201 }
1202
37f0777f 1203 wrq->flags |= index + 1;
92b96797
FB
1204 return 0;
1205}
1206
92b96797 1207/*
5a673637 1208 * Wireless Handler: set power mode
92b96797 1209 */
921cd68b
JJ
1210int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info,
1211 struct iw_param *wrq, char *extra)
92b96797 1212{
1a6dd0da 1213 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 1214 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
48746d7f 1215 int rc = 0;
92b96797 1216
48746d7f 1217 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER \n");
92b96797 1218
48746d7f
JJ
1219 if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
1220 rc = -EINVAL;
1221 return rc;
92b96797
FB
1222 }
1223
1224 if (wrq->disabled) {
1225 pDevice->ePSMode = WMAC_POWER_CAM;
1226 PSvDisablePowerSaving(pDevice);
1227 return rc;
1228 }
1229 if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
48746d7f 1230 pDevice->ePSMode = WMAC_POWER_FAST;
bd4208e9 1231 PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
92b96797
FB
1232
1233 } else if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
48746d7f 1234 pDevice->ePSMode = WMAC_POWER_FAST;
bd4208e9 1235 PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
92b96797
FB
1236 }
1237 switch (wrq->flags & IW_POWER_MODE) {
1238 case IW_POWER_UNICAST_R:
48746d7f 1239 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n");
92b96797
FB
1240 rc = -EINVAL;
1241 break;
1242 case IW_POWER_ALL_R:
48746d7f 1243 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R \n");
92b96797
FB
1244 rc = -EINVAL;
1245 case IW_POWER_ON:
48746d7f 1246 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON \n");
92b96797
FB
1247 break;
1248 default:
1249 rc = -EINVAL;
1250 }
1251
1252 return rc;
1253}
1254
1255/*
5a673637 1256 * Wireless Handler: get power mode
92b96797 1257 */
921cd68b
JJ
1258int iwctl_giwpower(struct net_device *dev, struct iw_request_info *info,
1259 struct iw_param *wrq, char *extra)
92b96797 1260{
1a6dd0da 1261 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 1262 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
48746d7f 1263 int mode = pDevice->ePSMode;
92b96797 1264
48746d7f 1265 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPOWER \n");
92b96797 1266
92b96797 1267 if ((wrq->disabled = (mode == WMAC_POWER_CAM)))
48746d7f 1268 return 0;
92b96797
FB
1269
1270 if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
1271 wrq->value = (int)((pMgmt->wListenInterval * pMgmt->wCurrBeaconPeriod) << 10);
1272 wrq->flags = IW_POWER_TIMEOUT;
1273 } else {
1274 wrq->value = (int)((pMgmt->wListenInterval * pMgmt->wCurrBeaconPeriod) << 10);
1275 wrq->flags = IW_POWER_PERIOD;
1276 }
1277 wrq->flags |= IW_POWER_ALL_R;
92b96797
FB
1278 return 0;
1279}
1280
92b96797 1281/*
5a673637 1282 * Wireless Handler: get Sensitivity
92b96797 1283 */
921cd68b
JJ
1284int iwctl_giwsens(struct net_device *dev, struct iw_request_info *info,
1285 struct iw_param *wrq, char *extra)
92b96797 1286{
1a6dd0da 1287 PSDevice pDevice = netdev_priv(dev);
48746d7f 1288 long ldBm;
92b96797 1289
48746d7f
JJ
1290 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSENS \n");
1291 if (pDevice->bLinkPass == TRUE) {
1292 RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm);
1293 wrq->value = ldBm;
8c3337fe 1294 } else {
48746d7f 1295 wrq->value = 0;
bb6ec004 1296 }
92b96797
FB
1297 wrq->disabled = (wrq->value == 0);
1298 wrq->fixed = 1;
92b96797
FB
1299 return 0;
1300}
1301
921cd68b
JJ
1302int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info,
1303 struct iw_param *wrq, char *extra)
92b96797 1304{
1a6dd0da 1305 PSDevice pDevice = netdev_priv(dev);
c91a8d5a
JJ
1306 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
1307 int ret = 0;
5a673637 1308 static int wpa_version = 0; // must be static to save the last value, einsn liu
c91a8d5a 1309 static int pairwise = 0;
92b96797 1310
48746d7f 1311 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n");
92b96797
FB
1312 switch (wrq->flags & IW_AUTH_INDEX) {
1313 case IW_AUTH_WPA_VERSION:
1314 wpa_version = wrq->value;
f269d1c2 1315 if (wrq->value == IW_AUTH_WPA_VERSION_DISABLED) {
48746d7f 1316 PRINT_K("iwctl_siwauth:set WPADEV to disable at 1??????\n");
8c3337fe 1317 } else if (wrq->value == IW_AUTH_WPA_VERSION_WPA) {
48746d7f 1318 PRINT_K("iwctl_siwauth:set WPADEV to WPA1******\n");
8c3337fe 1319 } else {
48746d7f 1320 PRINT_K("iwctl_siwauth:set WPADEV to WPA2******\n");
92b96797 1321 }
92b96797
FB
1322 break;
1323 case IW_AUTH_CIPHER_PAIRWISE:
1324 pairwise = wrq->value;
37f0777f 1325 PRINT_K("iwctl_siwauth:set pairwise=%d\n", pairwise);
f269d1c2 1326 if (pairwise == IW_AUTH_CIPHER_CCMP){
92b96797 1327 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
8c3337fe 1328 } else if (pairwise == IW_AUTH_CIPHER_TKIP) {
92b96797 1329 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
bd2bc4c7 1330 } else if (pairwise == IW_AUTH_CIPHER_WEP40 ||
48746d7f 1331 pairwise == IW_AUTH_CIPHER_WEP104) {
92b96797 1332 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
8c3337fe 1333 } else if (pairwise == IW_AUTH_CIPHER_NONE) {
5a673637 1334 // do nothing, einsn liu
8c3337fe
JJ
1335 } else {
1336 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
1337 }
92b96797
FB
1338 break;
1339 case IW_AUTH_CIPHER_GROUP:
37f0777f 1340 PRINT_K("iwctl_siwauth:set GROUP=%d\n", wrq->value);
f269d1c2 1341 if (wpa_version == IW_AUTH_WPA_VERSION_DISABLED)
92b96797 1342 break;
8c3337fe 1343 if (pairwise == IW_AUTH_CIPHER_NONE) {
0c5c7901 1344 if (wrq->value == IW_AUTH_CIPHER_CCMP)
92b96797 1345 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
0c5c7901 1346 else
92b96797 1347 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
92b96797
FB
1348 }
1349 break;
1350 case IW_AUTH_KEY_MGMT:
37f0777f 1351 PRINT_K("iwctl_siwauth(wpa_version=%d):set KEY_MGMT=%d\n", wpa_version,wrq->value);
f269d1c2
JJ
1352 if (wpa_version == IW_AUTH_WPA_VERSION_WPA2){
1353 if (wrq->value == IW_AUTH_KEY_MGMT_PSK)
92b96797
FB
1354 pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
1355 else pMgmt->eAuthenMode = WMAC_AUTH_WPA2;
37f0777f 1356 } else if (wpa_version == IW_AUTH_WPA_VERSION_WPA) {
f269d1c2 1357 if (wrq->value == 0){
92b96797 1358 pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
8c3337fe 1359 } else if (wrq->value == IW_AUTH_KEY_MGMT_PSK)
92b96797 1360 pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
8c3337fe
JJ
1361 } else {
1362 pMgmt->eAuthenMode = WMAC_AUTH_WPA;
92b96797 1363 }
92b96797
FB
1364 break;
1365 case IW_AUTH_TKIP_COUNTERMEASURES:
5a673637 1366 break; /* FIXME */
92b96797
FB
1367 case IW_AUTH_DROP_UNENCRYPTED:
1368 break;
1369 case IW_AUTH_80211_AUTH_ALG:
37f0777f 1370 PRINT_K("iwctl_siwauth:set AUTH_ALG=%d\n", wrq->value);
8c3337fe 1371 if (wrq->value == IW_AUTH_ALG_OPEN_SYSTEM)
37f0777f 1372 pMgmt->bShareKeyAlgorithm = FALSE;
8c3337fe
JJ
1373 else if (wrq->value == IW_AUTH_ALG_SHARED_KEY)
1374 pMgmt->bShareKeyAlgorithm = TRUE;
92b96797
FB
1375 break;
1376 case IW_AUTH_WPA_ENABLED:
92b96797
FB
1377 break;
1378 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1379 break;
1380 case IW_AUTH_ROAMING_CONTROL:
1381 ret = -EOPNOTSUPP;
1382 break;
1383 case IW_AUTH_PRIVACY_INVOKED:
1384 pDevice->bEncryptionEnable = !!wrq->value;
8c3337fe 1385 if (pDevice->bEncryptionEnable == FALSE) {
92b96797
FB
1386 wpa_version = 0;
1387 pairwise = 0;
1388 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
1389 pMgmt->bShareKeyAlgorithm = FALSE;
1390 pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
48746d7f 1391 PRINT_K("iwctl_siwauth:set WPADEV to disaable at 2?????\n");
92b96797 1392 }
92b96797
FB
1393 break;
1394 default:
1395 ret = -EOPNOTSUPP;
1396 break;
1397 }
48746d7f 1398 return ret;
92b96797
FB
1399}
1400
921cd68b
JJ
1401int iwctl_giwauth(struct net_device *dev, struct iw_request_info *info,
1402 struct iw_param *wrq, char *extra)
92b96797
FB
1403{
1404 return -EOPNOTSUPP;
1405}
1406
921cd68b
JJ
1407int iwctl_siwgenie(struct net_device *dev, struct iw_request_info *info,
1408 struct iw_point *wrq, char *extra)
92b96797 1409{
1a6dd0da 1410 PSDevice pDevice = netdev_priv(dev);
c91a8d5a
JJ
1411 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
1412 int ret = 0;
92b96797 1413
f269d1c2 1414 if (wrq->length){
37f0777f 1415 if ((wrq->length < 2) || (extra[1] + 2 != wrq->length)) {
92b96797
FB
1416 ret = -EINVAL;
1417 goto out;
1418 }
f269d1c2 1419 if (wrq->length > MAX_WPA_IE_LEN){
92b96797
FB
1420 ret = -ENOMEM;
1421 goto out;
1422 }
1423 memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN);
f269d1c2 1424 if (copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)){
92b96797
FB
1425 ret = -EFAULT;
1426 goto out;
1427 }
1428 pMgmt->wWPAIELen = wrq->length;
0c5c7901 1429 } else {
92b96797
FB
1430 memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN);
1431 pMgmt->wWPAIELen = 0;
1432 }
1433
5a673637 1434out: // not completely ...not necessary in wpa_supplicant 0.5.8
4d9db977 1435 return ret;
92b96797
FB
1436}
1437
921cd68b 1438int iwctl_giwgenie(struct net_device *dev, struct iw_request_info *info,
48746d7f 1439 struct iw_point *wrq, char *extra)
92b96797 1440{
1a6dd0da 1441 PSDevice pDevice = netdev_priv(dev);
c91a8d5a
JJ
1442 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
1443 int ret = 0;
92b96797
FB
1444 int space = wrq->length;
1445
1446 wrq->length = 0;
8c3337fe 1447 if (pMgmt->wWPAIELen > 0) {
92b96797 1448 wrq->length = pMgmt->wWPAIELen;
37f0777f
JJ
1449 if (pMgmt->wWPAIELen <= space) {
1450 if (copy_to_user(extra, pMgmt->abyWPAIE, pMgmt->wWPAIELen)) {
92b96797
FB
1451 ret = -EFAULT;
1452 }
0c5c7901 1453 } else {
92b96797 1454 ret = -E2BIG;
0c5c7901 1455 }
92b96797 1456 }
92b96797
FB
1457 return ret;
1458}
1459
921cd68b 1460int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info,
48746d7f 1461 struct iw_point *wrq, char *extra)
92b96797 1462{
1a6dd0da 1463 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 1464 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797 1465 struct iw_encode_ext *ext = (struct iw_encode_ext*)extra;
48746d7f 1466 struct viawget_wpa_param *param=NULL;
5a673637 1467// original member
48746d7f 1468 wpa_alg alg_name;
c91a8d5a
JJ
1469 u8 addr[6];
1470 int key_idx;
37f0777f 1471 int set_tx = 0;
c91a8d5a 1472 u8 seq[IW_ENCODE_SEQ_MAX_SIZE];
48746d7f 1473 u8 key[64];
c91a8d5a
JJ
1474 size_t seq_len = 0;
1475 size_t key_len = 0;
48746d7f 1476 u8 *buf;
48746d7f 1477 u8 key_array[64];
c91a8d5a 1478 int ret = 0;
48746d7f 1479
04212268 1480 PRINT_K("SIOCSIWENCODEEXT......\n");
48746d7f 1481
04212268 1482 buf = kzalloc(sizeof(struct viawget_wpa_param), GFP_KERNEL);
48746d7f
JJ
1483 if (buf == NULL)
1484 return -ENOMEM;
04212268 1485
bd4208e9 1486 param = (struct viawget_wpa_param *)buf;
92b96797 1487
5a673637 1488// recover alg_name
48746d7f
JJ
1489 switch (ext->alg) {
1490 case IW_ENCODE_ALG_NONE:
1491 alg_name = WPA_ALG_NONE;
92b96797 1492 break;
48746d7f
JJ
1493 case IW_ENCODE_ALG_WEP:
1494 alg_name = WPA_ALG_WEP;
92b96797 1495 break;
48746d7f
JJ
1496 case IW_ENCODE_ALG_TKIP:
1497 alg_name = WPA_ALG_TKIP;
92b96797 1498 break;
48746d7f
JJ
1499 case IW_ENCODE_ALG_CCMP:
1500 alg_name = WPA_ALG_CCMP;
92b96797 1501 break;
48746d7f 1502 default:
92b96797
FB
1503 PRINT_K("Unknown alg = %d\n",ext->alg);
1504 ret= -ENOMEM;
1505 goto error;
48746d7f 1506 }
5a673637 1507// recover addr
48746d7f 1508 memcpy(addr, ext->addr.sa_data, ETH_ALEN);
5a673637 1509// recover key_idx
48746d7f 1510 key_idx = (wrq->flags&IW_ENCODE_INDEX) - 1;
5a673637 1511// recover set_tx
f269d1c2 1512 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
48746d7f 1513 set_tx = 1;
5a673637 1514// recover seq,seq_len
f269d1c2 1515 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
48746d7f
JJ
1516 seq_len=IW_ENCODE_SEQ_MAX_SIZE;
1517 memcpy(seq, ext->rx_seq, seq_len);
92b96797 1518 }
5a673637 1519// recover key,key_len
f269d1c2 1520 if (ext->key_len) {
37f0777f 1521 key_len = ext->key_len;
48746d7f 1522 memcpy(key, &ext->key[0], key_len);
92b96797 1523 }
48746d7f 1524 memset(key_array, 0, 64);
37f0777f 1525 if (key_len > 0) {
48746d7f
JJ
1526 memcpy(key_array, key, key_len);
1527 if (key_len == 32) {
1528 // notice ! the oder
1529 memcpy(&key_array[16], &key[24], 8);
1530 memcpy(&key_array[24], &key[16], 8);
1531 }
92b96797
FB
1532 }
1533
1534/**************Translate iw_encode_ext to viawget_wpa_param****************/
48746d7f
JJ
1535 memcpy(param->addr, addr, ETH_ALEN);
1536 param->u.wpa_key.alg_name = (int)alg_name;
1537 param->u.wpa_key.set_tx = set_tx;
1538 param->u.wpa_key.key_index = key_idx;
1539 param->u.wpa_key.key_len = key_len;
1540 param->u.wpa_key.key = (u8 *)key_array;
1541 param->u.wpa_key.seq = (u8 *)seq;
1542 param->u.wpa_key.seq_len = seq_len;
92b96797 1543
5a673637
JJ
1544/****set if current action is Network Manager count?? */
1545/****this method is so foolish,but there is no other way??? */
f269d1c2
JJ
1546 if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
1547 if (param->u.wpa_key.key_index ==0) {
48746d7f
JJ
1548 pDevice->bwextstep0 = TRUE;
1549 }
1550 if ((pDevice->bwextstep0 == TRUE) && (param->u.wpa_key.key_index == 1)) {
1551 pDevice->bwextstep0 = FALSE;
1552 pDevice->bwextstep1 = TRUE;
1553 }
1554 if ((pDevice->bwextstep1 == TRUE) && (param->u.wpa_key.key_index == 2)) {
1555 pDevice->bwextstep1 = FALSE;
1556 pDevice->bwextstep2 = TRUE;
1557 }
37f0777f 1558 if ((pDevice->bwextstep2 == TRUE) && (param->u.wpa_key.key_index == 3)) {
48746d7f
JJ
1559 pDevice->bwextstep2 = FALSE;
1560 pDevice->bwextstep3 = TRUE;
1561 }
1562 }
f269d1c2 1563 if (pDevice->bwextstep3 == TRUE) {
48746d7f
JJ
1564 PRINT_K("SIOCSIWENCODEEXT:Enable WPA WEXT SUPPORT!!!!!\n");
1565 pDevice->bwextstep0 = FALSE;
1566 pDevice->bwextstep1 = FALSE;
1567 pDevice->bwextstep2 = FALSE;
1568 pDevice->bwextstep3 = FALSE;
1569 pDevice->bWPASuppWextEnabled = TRUE;
37f0777f
JJ
1570 memset(pMgmt->abyDesireBSSID, 0xFF, 6);
1571 KeyvInitTable(pDevice, &pDevice->sKey);
92b96797 1572 }
5a673637 1573/*******/
48746d7f
JJ
1574 spin_lock_irq(&pDevice->lock);
1575 ret = wpa_set_keys(pDevice, param, TRUE);
1576 spin_unlock_irq(&pDevice->lock);
92b96797
FB
1577
1578error:
04212268 1579 kfree(buf);
92b96797
FB
1580 return ret;
1581}
1582
921cd68b
JJ
1583int iwctl_giwencodeext(struct net_device *dev, struct iw_request_info *info,
1584 struct iw_point *wrq, char *extra)
92b96797 1585{
48746d7f 1586 return -EOPNOTSUPP;
92b96797
FB
1587}
1588
921cd68b
JJ
1589int iwctl_siwmlme(struct net_device *dev, struct iw_request_info *info,
1590 struct iw_point *wrq, char *extra)
92b96797 1591{
1a6dd0da 1592 PSDevice pDevice = netdev_priv(dev);
c91a8d5a 1593 PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
92b96797 1594 struct iw_mlme *mlme = (struct iw_mlme *)extra;
92b96797
FB
1595 int ret = 0;
1596
8c3337fe 1597 if (memcmp(pMgmt->abyCurrBSSID, mlme->addr.sa_data, ETH_ALEN)) {
92b96797
FB
1598 ret = -EINVAL;
1599 return ret;
1600 }
f269d1c2 1601 switch (mlme->cmd){
92b96797 1602 case IW_MLME_DEAUTH:
92b96797 1603 case IW_MLME_DISASSOC:
8c3337fe 1604 if (pDevice->bLinkPass == TRUE) {
48746d7f 1605 PRINT_K("iwctl_siwmlme--->send DISASSOCIATE\n");
4063d060 1606 bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE,
48746d7f 1607 NULL);
92b96797
FB
1608 }
1609 break;
1610 default:
1611 ret = -EOPNOTSUPP;
1612 }
92b96797 1613 return ret;
92b96797
FB
1614}
1615
c91a8d5a 1616static const iw_handler iwctl_handler[] = {
5a673637
JJ
1617 (iw_handler)NULL, // SIOCSIWCOMMIT
1618 (iw_handler)NULL, // SIOCGIWNAME
1619 (iw_handler)NULL, // SIOCSIWNWID
1620 (iw_handler)NULL, // SIOCGIWNWID
1621 (iw_handler)NULL, // SIOCSIWFREQ
1622 (iw_handler)NULL, // SIOCGIWFREQ
1623 (iw_handler)NULL, // SIOCSIWMODE
1624 (iw_handler)NULL, // SIOCGIWMODE
1625 (iw_handler)NULL, // SIOCSIWSENS
1626 (iw_handler)NULL, // SIOCGIWSENS
1627 (iw_handler)NULL, // SIOCSIWRANGE
1628 (iw_handler)iwctl_giwrange, // SIOCGIWRANGE
1629 (iw_handler)NULL, // SIOCSIWPRIV
1630 (iw_handler)NULL, // SIOCGIWPRIV
1631 (iw_handler)NULL, // SIOCSIWSTATS
1632 (iw_handler)NULL, // SIOCGIWSTATS
1633 (iw_handler)NULL, // SIOCSIWSPY
1634 (iw_handler)NULL, // SIOCGIWSPY
1635 (iw_handler)NULL, // -- hole --
1636 (iw_handler)NULL, // -- hole --
1637 (iw_handler)NULL, // SIOCSIWAP
1638 (iw_handler)NULL, // SIOCGIWAP
1639 (iw_handler)NULL, // -- hole -- 0x16
1640 (iw_handler)NULL, // SIOCGIWAPLIST
1641 (iw_handler)iwctl_siwscan, // SIOCSIWSCAN
1642 (iw_handler)iwctl_giwscan, // SIOCGIWSCAN
1643 (iw_handler)NULL, // SIOCSIWESSID
1644 (iw_handler)NULL, // SIOCGIWESSID
1645 (iw_handler)NULL, // SIOCSIWNICKN
1646 (iw_handler)NULL, // SIOCGIWNICKN
1647 (iw_handler)NULL, // -- hole --
1648 (iw_handler)NULL, // -- hole --
1649 (iw_handler)NULL, // SIOCSIWRATE 0x20
1650 (iw_handler)NULL, // SIOCGIWRATE
1651 (iw_handler)NULL, // SIOCSIWRTS
1652 (iw_handler)NULL, // SIOCGIWRTS
1653 (iw_handler)NULL, // SIOCSIWFRAG
1654 (iw_handler)NULL, // SIOCGIWFRAG
1655 (iw_handler)NULL, // SIOCSIWTXPOW
1656 (iw_handler)NULL, // SIOCGIWTXPOW
1657 (iw_handler)NULL, // SIOCSIWRETRY
1658 (iw_handler)NULL, // SIOCGIWRETRY
1659 (iw_handler)NULL, // SIOCSIWENCODE
1660 (iw_handler)NULL, // SIOCGIWENCODE
1661 (iw_handler)NULL, // SIOCSIWPOWER
1662 (iw_handler)NULL, // SIOCGIWPOWER
1663 (iw_handler)NULL, // -- hole --
1664 (iw_handler)NULL, // -- hole --
1665 (iw_handler)NULL, // SIOCSIWGENIE
1666 (iw_handler)NULL, // SIOCGIWGENIE
1667 (iw_handler)NULL, // SIOCSIWAUTH
1668 (iw_handler)NULL, // SIOCGIWAUTH
1669 (iw_handler)NULL, // SIOCSIWENCODEEXT
1670 (iw_handler)NULL, // SIOCGIWENCODEEXT
1671 (iw_handler)NULL, // SIOCSIWPMKSA
1672 (iw_handler)NULL, // -- hole --
92b96797
FB
1673};
1674
c91a8d5a 1675static const iw_handler iwctl_private_handler[] = {
5a673637 1676 NULL, // SIOCIWFIRSTPRIV
92b96797
FB
1677};
1678
92b96797 1679struct iw_priv_args iwctl_private_args[] = {
37f0777f 1680 { IOCTL_CMD_SET, IW_PRIV_TYPE_CHAR | 1024, 0, "set" },
92b96797
FB
1681};
1682
c91a8d5a 1683const struct iw_handler_def iwctl_handler_def = {
37f0777f
JJ
1684 .get_wireless_stats = &iwctl_get_wireless_stats,
1685 .num_standard = sizeof(iwctl_handler) / sizeof(iw_handler),
1686 .num_private = 0,
1687 .num_private_args = 0,
1688 .standard = (iw_handler *)iwctl_handler,
1689 .private = NULL,
1690 .private_args = NULL,
92b96797 1691};