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