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