Merge branch 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
[pandora-kernel.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 deamon
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 deamon
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      }
238     else {
239         spin_unlock_irq(&pDevice->lock);
240         if (param->u.wpa_key.key &&
241             copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)) {
242             spin_lock_irq(&pDevice->lock);
243             return -EINVAL;
244         }
245 spin_lock_irq(&pDevice->lock);
246         }
247
248     dwKeyIndex = (unsigned long)(param->u.wpa_key.key_index);
249
250         if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
251         if (dwKeyIndex > 3) {
252             return -EINVAL;
253         }
254         else {
255             if (param->u.wpa_key.set_tx) {
256                 pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
257                 pDevice->bTransmitKey = true;
258                         dwKeyIndex |= (1 << 31);
259             }
260             KeybSetDefaultKey(&(pDevice->sKey),
261                                 dwKeyIndex & ~(BIT30 | USE_KEYRSC),
262                                 param->u.wpa_key.key_len,
263                                 NULL,
264                                 abyKey,
265                                 KEY_CTL_WEP,
266                                 pDevice->PortOffset,
267                                 pDevice->byLocalID);
268
269         }
270         pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
271         pDevice->bEncryptionEnable = true;
272         return ret;
273         }
274
275             //spin_unlock_irq(&pDevice->lock);
276         if(param->u.wpa_key.seq && fcpfkernel) {
277            memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
278                 }
279        else {
280                 spin_unlock_irq(&pDevice->lock);
281         if (param->u.wpa_key.seq &&
282             copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)) {
283             spin_lock_irq(&pDevice->lock);
284             return -EINVAL;
285         }
286 spin_lock_irq(&pDevice->lock);
287 }
288
289         if (param->u.wpa_key.seq_len > 0) {
290                 for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) {
291                      if (ii < 4)
292                             LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8));
293                          else
294                             HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8));
295                  //KeyRSC |= (abySeq[ii] << (ii * 8));
296                 }
297                 dwKeyIndex |= 1 << 29;
298         }
299
300     if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) {
301         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return  dwKeyIndex > 3\n");
302         return -EINVAL;
303     }
304
305         if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) {
306         pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
307     }
308
309         if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) {
310         pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
311     }
312
313         if (param->u.wpa_key.set_tx)
314                 dwKeyIndex |= (1 << 31);
315
316
317     if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
318         byKeyDecMode = KEY_CTL_CCMP;
319     else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
320         byKeyDecMode = KEY_CTL_TKIP;
321     else
322         byKeyDecMode = KEY_CTL_WEP;
323
324     // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled
325     if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
326         if (param->u.wpa_key.key_len == MAX_KEY_LEN)
327             byKeyDecMode = KEY_CTL_TKIP;
328         else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
329             byKeyDecMode = KEY_CTL_WEP;
330         else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
331             byKeyDecMode = KEY_CTL_WEP;
332     } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
333         if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
334             byKeyDecMode = KEY_CTL_WEP;
335         else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
336             byKeyDecMode = KEY_CTL_WEP;
337     }
338
339     // Check TKIP key length
340     if ((byKeyDecMode == KEY_CTL_TKIP) &&
341         (param->u.wpa_key.key_len != MAX_KEY_LEN)) {
342         // TKIP Key must be 256 bits
343         //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n"));
344         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n");
345         return -EINVAL;
346     }
347     // Check AES key length
348     if ((byKeyDecMode == KEY_CTL_CCMP) &&
349         (param->u.wpa_key.key_len != AES_KEY_LEN)) {
350         // AES Key must be 128 bits
351         //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - AES Key must be 128 bits\n"));
352         return -EINVAL;
353     }
354
355    // spin_lock_irq(&pDevice->lock);
356     if (is_broadcast_ether_addr(&param->addr[0]) || (param->addr == NULL)) {
357         // If is_broadcast_ether_addr, set the key as every key entry's group key.
358         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n");
359
360         if ((KeybSetAllGroupKey(&(pDevice->sKey),
361                             dwKeyIndex,
362                             param->u.wpa_key.key_len,
363                             (PQWORD) &(KeyRSC),
364                             (unsigned char *)abyKey,
365                             byKeyDecMode,
366                             pDevice->PortOffset,
367                             pDevice->byLocalID) == true) &&
368             (KeybSetDefaultKey(&(pDevice->sKey),
369                             dwKeyIndex,
370                             param->u.wpa_key.key_len,
371                             (PQWORD) &(KeyRSC),
372                             (unsigned char *)abyKey,
373                             byKeyDecMode,
374                             pDevice->PortOffset,
375                             pDevice->byLocalID) == true) ) {
376              DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n");
377
378         } else {
379             //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n"));
380            // spin_unlock_irq(&pDevice->lock);
381             return -EINVAL;
382         }
383
384     } else {
385         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n");
386         // BSSID not 0xffffffffffff
387         // Pairwise Key can't be WEP
388         if (byKeyDecMode == KEY_CTL_WEP) {
389             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n");
390             //spin_unlock_irq(&pDevice->lock);
391             return -EINVAL;
392         }
393
394         dwKeyIndex |= (1 << 30); // set pairwise key
395         if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
396             //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n"));
397             //spin_unlock_irq(&pDevice->lock);
398             return -EINVAL;
399         }
400         if (KeybSetKey(&(pDevice->sKey),
401                        &param->addr[0],
402                        dwKeyIndex,
403                        param->u.wpa_key.key_len,
404                        (PQWORD) &(KeyRSC),
405                        (unsigned char *)abyKey,
406                         byKeyDecMode,
407                         pDevice->PortOffset,
408                         pDevice->byLocalID) == true) {
409             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
410
411         } else {
412             // Key Table Full
413             if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
414                 //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
415                 //spin_unlock_irq(&pDevice->lock);
416                 return -EINVAL;
417
418             } else {
419                 // Save Key and configure just before associate/reassociate to BSSID
420                 // we do not implement now
421                 //spin_unlock_irq(&pDevice->lock);
422                 return -EINVAL;
423             }
424         }
425     } // BSSID not 0xffffffffffff
426     if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) {
427         pDevice->byKeyIndex = (unsigned char)param->u.wpa_key.key_index;
428         pDevice->bTransmitKey = true;
429     }
430     pDevice->bEncryptionEnable = true;
431     //spin_unlock_irq(&pDevice->lock);
432
433 /*
434     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n",
435                pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0],
436                pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1],
437                pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2],
438                pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3],
439                pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4]
440               );
441 */
442
443         return ret;
444
445 }
446
447
448 /*
449  * Description:
450  *      enable wpa auth & mode
451  *
452  * Parameters:
453  *  In:
454  *      pDevice   -
455  *      param     -
456  *  Out:
457  *
458  * Return Value:
459  *
460  */
461
462 static int wpa_set_wpa(PSDevice pDevice,
463                                      struct viawget_wpa_param *param)
464 {
465
466     PSMgmtObject    pMgmt = pDevice->pMgmt;
467         int ret = 0;
468
469     pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
470     pMgmt->bShareKeyAlgorithm = false;
471
472     return ret;
473 }
474
475
476
477
478  /*
479  * Description:
480  *      set disassociate
481  *
482  * Parameters:
483  *  In:
484  *      pDevice   -
485  *      param     -
486  *  Out:
487  *
488  * Return Value:
489  *
490  */
491
492 static int wpa_set_disassociate(PSDevice pDevice,
493                                      struct viawget_wpa_param *param)
494 {
495     PSMgmtObject    pMgmt = pDevice->pMgmt;
496         int ret = 0;
497
498     spin_lock_irq(&pDevice->lock);
499     if (pDevice->bLinkPass) {
500         if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6))
501             bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
502     }
503     spin_unlock_irq(&pDevice->lock);
504
505     return ret;
506 }
507
508
509
510 /*
511  * Description:
512  *      enable scan process
513  *
514  * Parameters:
515  *  In:
516  *      pDevice   -
517  *      param     -
518  *  Out:
519  *
520  * Return Value:
521  *
522  */
523
524 static int wpa_set_scan(PSDevice pDevice,
525                                      struct viawget_wpa_param *param)
526 {
527         int ret = 0;
528
529     spin_lock_irq(&pDevice->lock);
530     BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass);
531     bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
532     spin_unlock_irq(&pDevice->lock);
533
534     return ret;
535 }
536
537
538
539 /*
540  * Description:
541  *      get bssid
542  *
543  * Parameters:
544  *  In:
545  *      pDevice   -
546  *      param     -
547  *  Out:
548  *
549  * Return Value:
550  *
551  */
552
553 static int wpa_get_bssid(PSDevice pDevice,
554                                      struct viawget_wpa_param *param)
555 {
556     PSMgmtObject        pMgmt = pDevice->pMgmt;
557         int ret = 0;
558
559         memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID , 6);
560
561     return ret;
562
563 }
564
565
566 /*
567  * Description:
568  *      get bssid
569  *
570  * Parameters:
571  *  In:
572  *      pDevice   -
573  *      param     -
574  *  Out:
575  *
576  * Return Value:
577  *
578  */
579
580 static int wpa_get_ssid(PSDevice pDevice,
581                                      struct viawget_wpa_param *param)
582 {
583     PSMgmtObject        pMgmt = pDevice->pMgmt;
584         PWLAN_IE_SSID       pItemSSID;
585         int ret = 0;
586
587     pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
588
589         memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID , pItemSSID->len);
590         param->u.wpa_associate.ssid_len = pItemSSID->len;
591
592     return ret;
593 }
594
595
596
597 /*
598  * Description:
599  *      get scan results
600  *
601  * Parameters:
602  *  In:
603  *      pDevice   -
604  *      param     -
605  *  Out:
606  *
607  * Return Value:
608  *
609  */
610
611 static int wpa_get_scan(PSDevice pDevice,
612                                      struct viawget_wpa_param *param)
613 {
614         struct viawget_scan_result *scan_buf;
615     PSMgmtObject    pMgmt = pDevice->pMgmt;
616     PWLAN_IE_SSID   pItemSSID;
617     PKnownBSS pBSS;
618         unsigned char *pBuf;
619         int ret = 0;
620         u16 count = 0;
621         u16 ii, jj;
622 #if 1
623
624     unsigned char *ptempBSS;
625
626
627
628     ptempBSS = kmalloc(sizeof(KnownBSS), (int)GFP_ATOMIC);
629
630     if (ptempBSS == NULL) {
631
632        printk("bubble sort kmalloc memory fail@@@\n");
633
634         ret = -ENOMEM;
635
636         return ret;
637
638     }
639
640     for (ii = 0; ii < MAX_BSS_NUM; ii++) {
641
642          for(jj=0;jj<MAX_BSS_NUM-ii-1;jj++) {
643
644            if((pMgmt->sBSSList[jj].bActive!=true) ||
645
646                 ((pMgmt->sBSSList[jj].uRSSI>pMgmt->sBSSList[jj+1].uRSSI) &&(pMgmt->sBSSList[jj+1].bActive!=false))) {
647
648                  memcpy(ptempBSS,&pMgmt->sBSSList[jj],sizeof(KnownBSS));
649
650                  memcpy(&pMgmt->sBSSList[jj],&pMgmt->sBSSList[jj+1],sizeof(KnownBSS));
651
652                  memcpy(&pMgmt->sBSSList[jj+1],ptempBSS,sizeof(KnownBSS));
653
654               }
655
656          }
657
658     }
659
660   kfree(ptempBSS);
661
662  // printk("bubble sort result:\n");
663
664   //for (ii = 0; ii < MAX_BSS_NUM; ii++)
665
666   //    printk("%d [%s]:RSSI=%d\n",ii,((PWLAN_IE_SSID)(pMgmt->sBSSList[ii].abySSID))->abySSID,
667
668   //                                                                 pMgmt->sBSSList[ii].uRSSI);
669
670  #endif
671
672 //******mike:bubble sort by stronger RSSI*****//
673
674
675
676
677         count = 0;
678         pBSS = &(pMgmt->sBSSList[0]);
679     for (ii = 0; ii < MAX_BSS_NUM; ii++) {
680         pBSS = &(pMgmt->sBSSList[ii]);
681         if (!pBSS->bActive)
682             continue;
683         count++;
684     }
685
686     pBuf = kcalloc(count, sizeof(struct viawget_scan_result), (int)GFP_ATOMIC);
687
688     if (pBuf == NULL) {
689         ret = -ENOMEM;
690         return ret;
691     }
692     scan_buf = (struct viawget_scan_result *)pBuf;
693         pBSS = &(pMgmt->sBSSList[0]);
694     for (ii = 0, jj = 0; ii < MAX_BSS_NUM ; ii++) {
695         pBSS = &(pMgmt->sBSSList[ii]);
696         if (pBSS->bActive) {
697             if (jj >= count)
698                 break;
699             memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN);
700             pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
701                     memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len);
702                     scan_buf->ssid_len = pItemSSID->len;
703             scan_buf->freq = frequency_list[pBSS->uChannel-1];
704           scan_buf->caps = pBSS->wCapInfo;
705             //scan_buf->caps = pBSS->wCapInfo;
706             //scan_buf->qual =
707             //scan_buf->noise =
708             //scan_buf->level =
709             //scan_buf->maxrate =
710             if (pBSS->wWPALen != 0) {
711                 scan_buf->wpa_ie_len = pBSS->wWPALen;
712                 memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen);
713             }
714             if (pBSS->wRSNLen != 0) {
715                 scan_buf->rsn_ie_len = pBSS->wRSNLen;
716                 memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen);
717             }
718             scan_buf = (struct viawget_scan_result *)((unsigned char *)scan_buf + sizeof(struct viawget_scan_result));
719             jj ++;
720         }
721     }
722
723     if (jj < count)
724         count = jj;
725
726     if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) {
727                 ret = -EFAULT;
728         }
729         param->u.scan_results.scan_count = count;
730     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count)
731
732     kfree(pBuf);
733     return ret;
734 }
735
736
737
738 /*
739  * Description:
740  *      set associate with AP
741  *
742  * Parameters:
743  *  In:
744  *      pDevice   -
745  *      param     -
746  *  Out:
747  *
748  * Return Value:
749  *
750  */
751
752 static int wpa_set_associate(PSDevice pDevice,
753                                      struct viawget_wpa_param *param)
754 {
755     PSMgmtObject    pMgmt = pDevice->pMgmt;
756     PWLAN_IE_SSID   pItemSSID;
757     unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
758     unsigned char abyWPAIE[64];
759     int ret = 0;
760     bool bWepEnabled=false;
761
762         // set key type & algorithm
763     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite);
764     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite);
765     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite);
766     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg);
767     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode);
768     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
769
770
771         if (param->u.wpa_associate.wpa_ie_len) {
772                 if (!param->u.wpa_associate.wpa_ie)
773                         return -EINVAL;
774                 if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE))
775                         return -EINVAL;
776                 if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len))
777                         return -EFAULT;
778         }
779
780         if (param->u.wpa_associate.mode == 1)
781             pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
782         else
783             pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
784     // set ssid
785         memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
786     pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
787     pItemSSID->byElementID = WLAN_EID_SSID;
788         pItemSSID->len = param->u.wpa_associate.ssid_len;
789         memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len);
790         // set bssid
791     if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0)
792         memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6);
793 else
794 {
795    bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID);
796 }
797
798     if (param->u.wpa_associate.wpa_ie_len == 0) {
799             if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY)
800             pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
801             else
802             pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
803         } else if (abyWPAIE[0] == RSN_INFO_ELEM) {
804                 if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
805                         pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
806                 else
807                         pMgmt->eAuthenMode = WMAC_AUTH_WPA2;
808         } else {
809                 if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE)
810                         pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
811                 else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
812                     pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
813                 else
814                     pMgmt->eAuthenMode = WMAC_AUTH_WPA;
815         }
816
817         switch (param->u.wpa_associate.pairwise_suite) {
818         case CIPHER_CCMP:
819                 pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
820                 break;
821         case CIPHER_TKIP:
822                 pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
823                 break;
824         case CIPHER_WEP40:
825         case CIPHER_WEP104:
826                 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
827                 bWepEnabled=true;
828                 break;
829         case CIPHER_NONE:
830                 if (param->u.wpa_associate.group_suite == CIPHER_CCMP)
831                         pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
832                 else
833                         pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
834                 break;
835         default:
836                 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
837         }
838
839 //DavidWang add for WPA_supplicant support open/share mode
840
841       if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) {
842             pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
843             //pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
844             pMgmt->bShareKeyAlgorithm = true;
845              }
846      else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) {
847           if(!bWepEnabled)  pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
848         else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
849             //pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
850             //pMgmt->bShareKeyAlgorithm = false; //20080717-06,<Modify> by chester//Fix Open mode, WEP encrytion
851            }
852 //mike save old encryption status
853         pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus;
854
855     if (pDevice->eEncryptionStatus !=  Ndis802_11EncryptionDisabled)
856         pDevice->bEncryptionEnable = true;
857     else
858         pDevice->bEncryptionEnable = false;
859 if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) ||
860       ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bWepEnabled==true))) )  //DavidWang  //20080717-06,<Modify> by chester//Not to initial WEP
861     KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
862     spin_lock_irq(&pDevice->lock);
863     pDevice->bLinkPass = false;
864     memset(pMgmt->abyCurrBSSID, 0, 6);
865     pMgmt->eCurrState = WMAC_STATE_IDLE;
866     netif_stop_queue(pDevice->dev);
867         //20080701-02,<Add> by Mike Liu
868 /*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/
869 {
870    PKnownBSS       pCurr = NULL;
871     pCurr = BSSpSearchBSSList(pDevice,
872                               pMgmt->abyDesireBSSID,
873                               pMgmt->abyDesireSSID,
874                               pMgmt->eConfigPHYMode
875                               );
876
877     if (pCurr == NULL){
878     printk("wpa_set_associate---->hidden mode site survey before associate.......\n");
879     bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID);
880   }
881 }
882 /****************************************************************/
883     bScheduleCommand((void *) pDevice, WLAN_CMD_SSID, NULL);
884     spin_unlock_irq(&pDevice->lock);
885
886     return ret;
887 }
888
889
890 /*
891  * Description:
892  *      wpa_ioctl main function supported for wpa supplicant
893  *
894  * Parameters:
895  *  In:
896  *      pDevice   -
897  *      iw_point  -
898  *  Out:
899  *
900  * Return Value:
901  *
902  */
903
904 int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
905 {
906         struct viawget_wpa_param *param;
907         int ret = 0;
908         int wpa_ioctl = 0;
909
910         if (p->length < sizeof(struct viawget_wpa_param) ||
911             p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer)
912                 return -EINVAL;
913
914         param = kmalloc((int)p->length, (int)GFP_KERNEL);
915         if (param == NULL)
916                 return -ENOMEM;
917
918         if (copy_from_user(param, p->pointer, p->length)) {
919                 ret = -EFAULT;
920                 goto out;
921         }
922
923         switch (param->cmd) {
924         case VIAWGET_SET_WPA:
925         ret = wpa_set_wpa(pDevice, param);
926             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n");
927                 break;
928
929         case VIAWGET_SET_KEY:
930             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n");
931             spin_lock_irq(&pDevice->lock);
932         ret = wpa_set_keys(pDevice, param, false);
933         spin_unlock_irq(&pDevice->lock);
934                 break;
935
936         case VIAWGET_SET_SCAN:
937             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n");
938         ret = wpa_set_scan(pDevice, param);
939                 break;
940
941         case VIAWGET_GET_SCAN:
942             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n");
943         ret = wpa_get_scan(pDevice, param);
944                 wpa_ioctl = 1;
945                 break;
946
947         case VIAWGET_GET_SSID:
948             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n");
949         ret = wpa_get_ssid(pDevice, param);
950                 wpa_ioctl = 1;
951                 break;
952
953         case VIAWGET_GET_BSSID:
954             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n");
955         ret = wpa_get_bssid(pDevice, param);
956                 wpa_ioctl = 1;
957                 break;
958
959         case VIAWGET_SET_ASSOCIATE:
960             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n");
961         ret = wpa_set_associate(pDevice, param);
962                 break;
963
964         case VIAWGET_SET_DISASSOCIATE:
965             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n");
966         ret = wpa_set_disassociate(pDevice, param);
967                 break;
968
969         case VIAWGET_SET_DROP_UNENCRYPT:
970             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n");
971                 break;
972
973     case VIAWGET_SET_DEAUTHENTICATE:
974             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n");
975                 break;
976
977         default:
978             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n",
979                        param->cmd);
980                 return -EOPNOTSUPP;
981                 break;
982         }
983
984         if ((ret == 0) && wpa_ioctl) {
985                 if (copy_to_user(p->pointer, param, p->length)) {
986                         ret = -EFAULT;
987                         goto out;
988                 }
989         }
990
991 out:
992         kfree(param);
993
994         return ret;
995 }
996