]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/vt6655/wpactl.c
staging: vt6655: Convert to kernel brace style
[karo-tx-linux.git] / drivers / staging / vt6655 / wpactl.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  *
20  * File: wpactl.c
21  *
22  * Purpose: handle wpa supplicant ioctl input/out functions
23  *
24  * Author: Lyndon Chen
25  *
26  * Date: Oct. 20, 2003
27  *
28  * Functions:
29  *
30  * Revision History:
31  *
32  */
33
34 #include "wpactl.h"
35 #include "key.h"
36 #include "mac.h"
37 #include "device.h"
38 #include "wmgr.h"
39 #include "iocmd.h"
40 #include "iowpa.h"
41 #include "rf.h"
42
43 /*---------------------  Static Definitions -------------------------*/
44
45 #define VIAWGET_WPA_MAX_BUF_SIZE 1024
46
47
48
49 static const int frequency_list[] = {
50         2412, 2417, 2422, 2427, 2432, 2437, 2442,
51         2447, 2452, 2457, 2462, 2467, 2472, 2484
52 };
53 /*---------------------  Static Classes  ----------------------------*/
54
55 /*---------------------  Static Variables  --------------------------*/
56 //static int          msglevel                =MSG_LEVEL_DEBUG;
57 static int msglevel = MSG_LEVEL_INFO;
58
59 /*---------------------  Static Functions  --------------------------*/
60
61
62
63
64 /*---------------------  Export Variables  --------------------------*/
65 static void wpadev_setup(struct net_device *dev)
66 {
67         dev->type               = ARPHRD_IEEE80211;
68         dev->hard_header_len    = ETH_HLEN;
69         dev->mtu                = 2048;
70         dev->addr_len           = ETH_ALEN;
71         dev->tx_queue_len       = 1000;
72
73         memset(dev->broadcast, 0xFF, ETH_ALEN);
74
75         dev->flags              = IFF_BROADCAST|IFF_MULTICAST;
76 }
77
78 /*
79  * Description:
80  *      register netdev for wpa supplicant daemon
81  *
82  * Parameters:
83  *  In:
84  *      pDevice             -
85  *      enable              -
86  *  Out:
87  *
88  * Return Value:
89  *
90  */
91
92 static int wpa_init_wpadev(PSDevice pDevice)
93 {
94         PSDevice wpadev_priv;
95         struct net_device *dev = pDevice->dev;
96         int ret = 0;
97
98         pDevice->wpadev = alloc_netdev(sizeof(PSDevice), "vntwpa", wpadev_setup);
99         if (pDevice->wpadev == NULL)
100                 return -ENOMEM;
101
102         wpadev_priv = netdev_priv(pDevice->wpadev);
103         *wpadev_priv = *pDevice;
104         memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, ETH_ALEN);
105         pDevice->wpadev->base_addr = dev->base_addr;
106         pDevice->wpadev->irq = dev->irq;
107         pDevice->wpadev->mem_start = dev->mem_start;
108         pDevice->wpadev->mem_end = dev->mem_end;
109         ret = register_netdev(pDevice->wpadev);
110         if (ret) {
111                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n",
112                         dev->name);
113                 free_netdev(pDevice->wpadev);
114                 return -1;
115         }
116
117         if (pDevice->skb == NULL) {
118                 pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
119                 if (pDevice->skb == NULL)
120                         return -ENOMEM;
121         }
122
123         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n",
124                 dev->name, pDevice->wpadev->name);
125
126         return 0;
127 }
128
129
130 /*
131  * Description:
132  *      unregister net_device (wpadev)
133  *
134  * Parameters:
135  *  In:
136  *      pDevice             -
137  *  Out:
138  *
139  * Return Value:
140  *
141  */
142
143 static int wpa_release_wpadev(PSDevice pDevice)
144 {
145         if (pDevice->skb) {
146                 dev_kfree_skb(pDevice->skb);
147                 pDevice->skb = NULL;
148         }
149
150         if (pDevice->wpadev) {
151                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
152                         pDevice->dev->name, pDevice->wpadev->name);
153                 unregister_netdev(pDevice->wpadev);
154                 free_netdev(pDevice->wpadev);
155                 pDevice->wpadev = NULL;
156         }
157
158         return 0;
159 }
160
161
162
163
164
165 /*
166  * Description:
167  *      Set enable/disable dev for wpa supplicant daemon
168  *
169  * Parameters:
170  *  In:
171  *      pDevice             -
172  *      val                 -
173  *  Out:
174  *
175  * Return Value:
176  *
177  */
178
179 int wpa_set_wpadev(PSDevice pDevice, int val)
180 {
181         if (val)
182                 return wpa_init_wpadev(pDevice);
183         else
184                 return wpa_release_wpadev(pDevice);
185 }
186
187
188 /*
189  * Description:
190  *      Set WPA algorithm & keys
191  *
192  * Parameters:
193  *  In:
194  *      pDevice -
195  *      param -
196  *  Out:
197  *
198  * Return Value:
199  *
200  */
201
202 int wpa_set_keys(PSDevice pDevice, void *ctx, bool fcpfkernel)
203 {
204         struct viawget_wpa_param *param = ctx;
205         PSMgmtObject pMgmt = pDevice->pMgmt;
206         unsigned long dwKeyIndex = 0;
207         unsigned char abyKey[MAX_KEY_LEN];
208         unsigned char abySeq[MAX_KEY_LEN];
209         QWORD   KeyRSC;
210 //    NDIS_802_11_KEY_RSC KeyRSC;
211         unsigned char byKeyDecMode = KEY_CTL_WEP;
212         int ret = 0;
213         int uu, ii;
214
215
216         if (param->u.wpa_key.alg_name > WPA_ALG_CCMP ||
217             param->u.wpa_key.key_len >= MAX_KEY_LEN ||
218             param->u.wpa_key.seq_len >= MAX_KEY_LEN)
219                 return -EINVAL;
220
221         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", param->u.wpa_key.alg_name);
222         if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
223                 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
224                 pDevice->bEncryptionEnable = false;
225                 pDevice->byKeyIndex = 0;
226                 pDevice->bTransmitKey = false;
227                 KeyvRemoveAllWEPKey(&(pDevice->sKey), pDevice->PortOffset);
228                 for (uu = 0; uu < MAX_KEY_TABLE; uu++) {
229                         MACvDisableKeyEntry(pDevice->PortOffset, uu);
230                 }
231                 return ret;
232         }
233
234         //spin_unlock_irq(&pDevice->lock);
235         if (param->u.wpa_key.key && fcpfkernel) {
236                 memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
237         } else {
238                 spin_unlock_irq(&pDevice->lock);
239                 if (param->u.wpa_key.key &&
240                     copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)) {
241                         spin_lock_irq(&pDevice->lock);
242                         return -EINVAL;
243                 }
244                 spin_lock_irq(&pDevice->lock);
245         }
246
247         dwKeyIndex = (unsigned long)(param->u.wpa_key.key_index);
248
249         if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
250                 if (dwKeyIndex > 3) {
251                         return -EINVAL;
252                 } else {
253                         if (param->u.wpa_key.set_tx) {
254                                 pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
255                                 pDevice->bTransmitKey = true;
256                                 dwKeyIndex |= (1 << 31);
257                         }
258                         KeybSetDefaultKey(&(pDevice->sKey),
259                                           dwKeyIndex & ~(BIT30 | USE_KEYRSC),
260                                           param->u.wpa_key.key_len,
261                                           NULL,
262                                           abyKey,
263                                           KEY_CTL_WEP,
264                                           pDevice->PortOffset,
265                                           pDevice->byLocalID);
266
267                 }
268                 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
269                 pDevice->bEncryptionEnable = true;
270                 return ret;
271         }
272
273         //spin_unlock_irq(&pDevice->lock);
274         if (param->u.wpa_key.seq && fcpfkernel) {
275                 memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
276         } else {
277                 spin_unlock_irq(&pDevice->lock);
278                 if (param->u.wpa_key.seq &&
279                     copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)) {
280                         spin_lock_irq(&pDevice->lock);
281                         return -EINVAL;
282                 }
283                 spin_lock_irq(&pDevice->lock);
284         }
285
286         if (param->u.wpa_key.seq_len > 0) {
287                 for (ii = 0; ii < param->u.wpa_key.seq_len; ii++) {
288                         if (ii < 4)
289                                 LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8));
290                         else
291                                 HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8));
292                         //KeyRSC |= (abySeq[ii] << (ii * 8));
293                 }
294                 dwKeyIndex |= 1 << 29;
295         }
296
297         if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) {
298                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return  dwKeyIndex > 3\n");
299                 return -EINVAL;
300         }
301
302         if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) {
303                 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
304         }
305
306         if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) {
307                 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
308         }
309
310         if (param->u.wpa_key.set_tx)
311                 dwKeyIndex |= (1 << 31);
312
313
314         if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
315                 byKeyDecMode = KEY_CTL_CCMP;
316         else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
317                 byKeyDecMode = KEY_CTL_TKIP;
318         else
319                 byKeyDecMode = KEY_CTL_WEP;
320
321         // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled
322         if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
323                 if (param->u.wpa_key.key_len == MAX_KEY_LEN)
324                         byKeyDecMode = KEY_CTL_TKIP;
325                 else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
326                         byKeyDecMode = KEY_CTL_WEP;
327                 else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
328                         byKeyDecMode = KEY_CTL_WEP;
329         } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
330                 if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
331                         byKeyDecMode = KEY_CTL_WEP;
332                 else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
333                         byKeyDecMode = KEY_CTL_WEP;
334         }
335
336         // Check TKIP key length
337         if ((byKeyDecMode == KEY_CTL_TKIP) &&
338             (param->u.wpa_key.key_len != MAX_KEY_LEN)) {
339                 // TKIP Key must be 256 bits
340                 //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n"));
341                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n");
342                 return -EINVAL;
343         }
344         // Check AES key length
345         if ((byKeyDecMode == KEY_CTL_CCMP) &&
346             (param->u.wpa_key.key_len != AES_KEY_LEN)) {
347                 // AES Key must be 128 bits
348                 //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - AES Key must be 128 bits\n"));
349                 return -EINVAL;
350         }
351
352         // spin_lock_irq(&pDevice->lock);
353         if (is_broadcast_ether_addr(&param->addr[0]) || (param->addr == NULL)) {
354                 // If is_broadcast_ether_addr, set the key as every key entry's group key.
355                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n");
356
357                 if ((KeybSetAllGroupKey(&(pDevice->sKey),
358                                         dwKeyIndex,
359                                         param->u.wpa_key.key_len,
360                                         (PQWORD) &(KeyRSC),
361                                         (unsigned char *)abyKey,
362                                         byKeyDecMode,
363                                         pDevice->PortOffset,
364                                         pDevice->byLocalID) == true) &&
365                     (KeybSetDefaultKey(&(pDevice->sKey),
366                                        dwKeyIndex,
367                                        param->u.wpa_key.key_len,
368                                        (PQWORD) &(KeyRSC),
369                                        (unsigned char *)abyKey,
370                                        byKeyDecMode,
371                                        pDevice->PortOffset,
372                                        pDevice->byLocalID) == true)) {
373                         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n");
374
375                 } else {
376                         //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n"));
377                         // spin_unlock_irq(&pDevice->lock);
378                         return -EINVAL;
379                 }
380
381         } else {
382                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n");
383                 // BSSID not 0xffffffffffff
384                 // Pairwise Key can't be WEP
385                 if (byKeyDecMode == KEY_CTL_WEP) {
386                         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n");
387                         //spin_unlock_irq(&pDevice->lock);
388                         return -EINVAL;
389                 }
390
391                 dwKeyIndex |= (1 << 30); // set pairwise key
392                 if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
393                         //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n"));
394                         //spin_unlock_irq(&pDevice->lock);
395                         return -EINVAL;
396                 }
397                 if (KeybSetKey(&(pDevice->sKey),
398                                &param->addr[0],
399                                dwKeyIndex,
400                                param->u.wpa_key.key_len,
401                                (PQWORD) &(KeyRSC),
402                                (unsigned char *)abyKey,
403                                byKeyDecMode,
404                                pDevice->PortOffset,
405                                pDevice->byLocalID) == true) {
406                         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
407
408                 } else {
409                         // Key Table Full
410                         if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
411                                 //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
412                                 //spin_unlock_irq(&pDevice->lock);
413                                 return -EINVAL;
414
415                         } else {
416                                 // Save Key and configure just before associate/reassociate to BSSID
417                                 // we do not implement now
418                                 //spin_unlock_irq(&pDevice->lock);
419                                 return -EINVAL;
420                         }
421                 }
422         } // BSSID not 0xffffffffffff
423         if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) {
424                 pDevice->byKeyIndex = (unsigned char)param->u.wpa_key.key_index;
425                 pDevice->bTransmitKey = true;
426         }
427         pDevice->bEncryptionEnable = true;
428         //spin_unlock_irq(&pDevice->lock);
429
430 /*
431   DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n",
432   pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0],
433   pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1],
434   pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2],
435   pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3],
436   pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4]
437 );
438 */
439
440         return ret;
441
442 }
443
444
445 /*
446  * Description:
447  *      enable wpa auth & mode
448  *
449  * Parameters:
450  *  In:
451  *      pDevice   -
452  *      param     -
453  *  Out:
454  *
455  * Return Value:
456  *
457  */
458
459 static int wpa_set_wpa(PSDevice pDevice,
460                        struct viawget_wpa_param *param)
461 {
462
463         PSMgmtObject    pMgmt = pDevice->pMgmt;
464         int ret = 0;
465
466         pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
467         pMgmt->bShareKeyAlgorithm = false;
468
469         return ret;
470 }
471
472
473
474
475 /*
476  * Description:
477  *      set disassociate
478  *
479  * Parameters:
480  *  In:
481  *      pDevice   -
482  *      param     -
483  *  Out:
484  *
485  * Return Value:
486  *
487  */
488
489 static int wpa_set_disassociate(PSDevice pDevice,
490                                 struct viawget_wpa_param *param)
491 {
492         PSMgmtObject    pMgmt = pDevice->pMgmt;
493         int ret = 0;
494
495         spin_lock_irq(&pDevice->lock);
496         if (pDevice->bLinkPass) {
497                 if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6))
498                         bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
499         }
500         spin_unlock_irq(&pDevice->lock);
501
502         return ret;
503 }
504
505
506
507 /*
508  * Description:
509  *      enable scan process
510  *
511  * Parameters:
512  *  In:
513  *      pDevice   -
514  *      param     -
515  *  Out:
516  *
517  * Return Value:
518  *
519  */
520
521 static int wpa_set_scan(PSDevice pDevice,
522                         struct viawget_wpa_param *param)
523 {
524         int ret = 0;
525
526         spin_lock_irq(&pDevice->lock);
527         BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
528         bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL);
529         spin_unlock_irq(&pDevice->lock);
530
531         return ret;
532 }
533
534
535
536 /*
537  * Description:
538  *      get bssid
539  *
540  * Parameters:
541  *  In:
542  *      pDevice   -
543  *      param     -
544  *  Out:
545  *
546  * Return Value:
547  *
548  */
549
550 static int wpa_get_bssid(PSDevice pDevice,
551                          struct viawget_wpa_param *param)
552 {
553         PSMgmtObject        pMgmt = pDevice->pMgmt;
554         int ret = 0;
555
556         memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID , 6);
557
558         return ret;
559
560 }
561
562
563 /*
564  * Description:
565  *      get bssid
566  *
567  * Parameters:
568  *  In:
569  *      pDevice   -
570  *      param     -
571  *  Out:
572  *
573  * Return Value:
574  *
575  */
576
577 static int wpa_get_ssid(PSDevice pDevice,
578                         struct viawget_wpa_param *param)
579 {
580         PSMgmtObject        pMgmt = pDevice->pMgmt;
581         PWLAN_IE_SSID       pItemSSID;
582         int ret = 0;
583
584         pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
585
586         memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID , pItemSSID->len);
587         param->u.wpa_associate.ssid_len = pItemSSID->len;
588
589         return ret;
590 }
591
592
593
594 /*
595  * Description:
596  *      get scan results
597  *
598  * Parameters:
599  *  In:
600  *      pDevice   -
601  *      param     -
602  *  Out:
603  *
604  * Return Value:
605  *
606  */
607
608 static int wpa_get_scan(PSDevice pDevice,
609                         struct viawget_wpa_param *param)
610 {
611         struct viawget_scan_result *scan_buf;
612         PSMgmtObject    pMgmt = pDevice->pMgmt;
613         PWLAN_IE_SSID   pItemSSID;
614         PKnownBSS pBSS;
615         unsigned char *pBuf;
616         int ret = 0;
617         u16 count = 0;
618         u16 ii, jj;
619 #if 1
620
621         unsigned char *ptempBSS;
622
623
624
625         ptempBSS = kmalloc(sizeof(KnownBSS), (int)GFP_ATOMIC);
626
627         if (ptempBSS == NULL) {
628
629                 printk("bubble sort kmalloc memory fail@@@\n");
630
631                 ret = -ENOMEM;
632
633                 return ret;
634
635         }
636
637         for (ii = 0; ii < MAX_BSS_NUM; ii++) {
638
639                 for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) {
640
641                         if ((pMgmt->sBSSList[jj].bActive != true) ||
642
643                             ((pMgmt->sBSSList[jj].uRSSI > pMgmt->sBSSList[jj + 1].uRSSI) && (pMgmt->sBSSList[jj + 1].bActive != false))) {
644
645                                 memcpy(ptempBSS, &pMgmt->sBSSList[jj], sizeof(KnownBSS));
646
647                                 memcpy(&pMgmt->sBSSList[jj], &pMgmt->sBSSList[jj + 1], sizeof(KnownBSS));
648
649                                 memcpy(&pMgmt->sBSSList[jj + 1], ptempBSS, sizeof(KnownBSS));
650
651                         }
652
653                 }
654
655         }
656
657         kfree(ptempBSS);
658 #endif
659
660 //******mike:bubble sort by stronger RSSI*****//
661
662
663
664
665         count = 0;
666         pBSS = &(pMgmt->sBSSList[0]);
667         for (ii = 0; ii < MAX_BSS_NUM; ii++) {
668                 pBSS = &(pMgmt->sBSSList[ii]);
669                 if (!pBSS->bActive)
670                         continue;
671                 count++;
672         }
673
674         pBuf = kcalloc(count, sizeof(struct viawget_scan_result), (int)GFP_ATOMIC);
675
676         if (pBuf == NULL) {
677                 ret = -ENOMEM;
678                 return ret;
679         }
680         scan_buf = (struct viawget_scan_result *)pBuf;
681         pBSS = &(pMgmt->sBSSList[0]);
682         for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) {
683                 pBSS = &(pMgmt->sBSSList[ii]);
684                 if (pBSS->bActive) {
685                         if (jj >= count)
686                                 break;
687                         memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN);
688                         pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
689                         memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len);
690                         scan_buf->ssid_len = pItemSSID->len;
691                         scan_buf->freq = frequency_list[pBSS->uChannel-1];
692                         scan_buf->caps = pBSS->wCapInfo;
693                         //scan_buf->caps = pBSS->wCapInfo;
694                         //scan_buf->qual =
695                         //scan_buf->noise =
696                         //scan_buf->level =
697                         //scan_buf->maxrate =
698                         if (pBSS->wWPALen != 0) {
699                                 scan_buf->wpa_ie_len = pBSS->wWPALen;
700                                 memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen);
701                         }
702                         if (pBSS->wRSNLen != 0) {
703                                 scan_buf->rsn_ie_len = pBSS->wRSNLen;
704                                 memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen);
705                         }
706                         scan_buf = (struct viawget_scan_result *)((unsigned char *)scan_buf + sizeof(struct viawget_scan_result));
707                         jj++;
708                 }
709         }
710
711         if (jj < count)
712                 count = jj;
713
714         if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) {
715                 ret = -EFAULT;
716         }
717         param->u.scan_results.scan_count = count;
718         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count)
719
720                 kfree(pBuf);
721         return ret;
722 }
723
724
725
726 /*
727  * Description:
728  *      set associate with AP
729  *
730  * Parameters:
731  *  In:
732  *      pDevice   -
733  *      param     -
734  *  Out:
735  *
736  * Return Value:
737  *
738  */
739
740 static int wpa_set_associate(PSDevice pDevice,
741                              struct viawget_wpa_param *param)
742 {
743         PSMgmtObject    pMgmt = pDevice->pMgmt;
744         PWLAN_IE_SSID   pItemSSID;
745         unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
746         unsigned char abyWPAIE[64];
747         int ret = 0;
748         bool bWepEnabled = false;
749
750         // set key type & algorithm
751         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite);
752         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite);
753         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite);
754         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg);
755         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode);
756         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
757
758
759         if (param->u.wpa_associate.wpa_ie_len) {
760                 if (!param->u.wpa_associate.wpa_ie)
761                         return -EINVAL;
762                 if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE))
763                         return -EINVAL;
764                 if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len))
765                         return -EFAULT;
766         }
767
768         if (param->u.wpa_associate.mode == 1)
769                 pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
770         else
771                 pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
772         // set ssid
773         memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
774         pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
775         pItemSSID->byElementID = WLAN_EID_SSID;
776         pItemSSID->len = param->u.wpa_associate.ssid_len;
777         memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len);
778         // set bssid
779         if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0)
780                 memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6);
781         else {
782                 bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID);
783         }
784
785         if (param->u.wpa_associate.wpa_ie_len == 0) {
786                 if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY)
787                         pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
788                 else
789                         pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
790         } else if (abyWPAIE[0] == RSN_INFO_ELEM) {
791                 if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
792                         pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
793                 else
794                         pMgmt->eAuthenMode = WMAC_AUTH_WPA2;
795         } else {
796                 if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE)
797                         pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
798                 else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
799                         pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
800                 else
801                         pMgmt->eAuthenMode = WMAC_AUTH_WPA;
802         }
803
804         switch (param->u.wpa_associate.pairwise_suite) {
805         case CIPHER_CCMP:
806                 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
807                 break;
808         case CIPHER_TKIP:
809                 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
810                 break;
811         case CIPHER_WEP40:
812         case CIPHER_WEP104:
813                 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
814                 bWepEnabled = true;
815                 break;
816         case CIPHER_NONE:
817                 if (param->u.wpa_associate.group_suite == CIPHER_CCMP)
818                         pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
819                 else
820                         pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
821                 break;
822         default:
823                 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
824         }
825
826 //DavidWang add for WPA_supplicant support open/share mode
827
828         if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) {
829                 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
830                 //pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
831                 pMgmt->bShareKeyAlgorithm = true;
832         } else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) {
833                 if (!bWepEnabled)  pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
834                 else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
835                 //pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
836                 //pMgmt->bShareKeyAlgorithm = false; //20080717-06,<Modify> by chester//Fix Open mode, WEP encryption
837         }
838 //mike save old encryption status
839         pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus;
840
841         if (pDevice->eEncryptionStatus !=  Ndis802_11EncryptionDisabled)
842                 pDevice->bEncryptionEnable = true;
843         else
844                 pDevice->bEncryptionEnable = false;
845         if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) ||
846               ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bWepEnabled == true))))  //DavidWang  //20080717-06,<Modify> by chester//Not to initial WEP
847                 KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
848         spin_lock_irq(&pDevice->lock);
849         pDevice->bLinkPass = false;
850         memset(pMgmt->abyCurrBSSID, 0, 6);
851         pMgmt->eCurrState = WMAC_STATE_IDLE;
852         netif_stop_queue(pDevice->dev);
853         //20080701-02,<Add> by Mike Liu
854 /*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/
855         {
856                 PKnownBSS       pCurr = NULL;
857                 pCurr = BSSpSearchBSSList(pDevice,
858                                           pMgmt->abyDesireBSSID,
859                                           pMgmt->abyDesireSSID,
860                                           pMgmt->eConfigPHYMode
861 );
862
863                 if (pCurr == NULL) {
864                         printk("wpa_set_associate---->hidden mode site survey before associate.......\n");
865                         bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
866                 }
867         }
868 /****************************************************************/
869         bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
870         spin_unlock_irq(&pDevice->lock);
871
872         return ret;
873 }
874
875
876 /*
877  * Description:
878  *      wpa_ioctl main function supported for wpa supplicant
879  *
880  * Parameters:
881  *  In:
882  *      pDevice   -
883  *      iw_point  -
884  *  Out:
885  *
886  * Return Value:
887  *
888  */
889
890 int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
891 {
892         struct viawget_wpa_param *param;
893         int ret = 0;
894         int wpa_ioctl = 0;
895
896         if (p->length < sizeof(struct viawget_wpa_param) ||
897             p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer)
898                 return -EINVAL;
899
900         param = kmalloc((int)p->length, (int)GFP_KERNEL);
901         if (param == NULL)
902                 return -ENOMEM;
903
904         if (copy_from_user(param, p->pointer, p->length)) {
905                 ret = -EFAULT;
906                 goto out;
907         }
908
909         switch (param->cmd) {
910         case VIAWGET_SET_WPA:
911                 ret = wpa_set_wpa(pDevice, param);
912                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n");
913                 break;
914
915         case VIAWGET_SET_KEY:
916                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n");
917                 spin_lock_irq(&pDevice->lock);
918                 ret = wpa_set_keys(pDevice, param, false);
919                 spin_unlock_irq(&pDevice->lock);
920                 break;
921
922         case VIAWGET_SET_SCAN:
923                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n");
924                 ret = wpa_set_scan(pDevice, param);
925                 break;
926
927         case VIAWGET_GET_SCAN:
928                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n");
929                 ret = wpa_get_scan(pDevice, param);
930                 wpa_ioctl = 1;
931                 break;
932
933         case VIAWGET_GET_SSID:
934                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n");
935                 ret = wpa_get_ssid(pDevice, param);
936                 wpa_ioctl = 1;
937                 break;
938
939         case VIAWGET_GET_BSSID:
940                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n");
941                 ret = wpa_get_bssid(pDevice, param);
942                 wpa_ioctl = 1;
943                 break;
944
945         case VIAWGET_SET_ASSOCIATE:
946                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n");
947                 ret = wpa_set_associate(pDevice, param);
948                 break;
949
950         case VIAWGET_SET_DISASSOCIATE:
951                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n");
952                 ret = wpa_set_disassociate(pDevice, param);
953                 break;
954
955         case VIAWGET_SET_DROP_UNENCRYPT:
956                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n");
957                 break;
958
959         case VIAWGET_SET_DEAUTHENTICATE:
960                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n");
961                 break;
962
963         default:
964                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n",
965                         param->cmd);
966                 return -EOPNOTSUPP;
967                 break;
968         }
969
970         if ((ret == 0) && wpa_ioctl) {
971                 if (copy_to_user(p->pointer, param, p->length)) {
972                         ret = -EFAULT;
973                         goto out;
974                 }
975         }
976
977 out:
978         kfree(param);
979
980         return ret;
981 }
982