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