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