PageRenderTime 38ms CodeModel.GetById 4ms app.highlight 28ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/staging/vt6655/wpactl.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 994 lines | 575 code | 169 blank | 250 comment | 156 complexity | c09a6c6e9104360a3d7ff73b048ffb02 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  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
 49static 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;
 57static int          msglevel                =MSG_LEVEL_INFO;
 58
 59/*---------------------  Static Functions  --------------------------*/
 60
 61
 62
 63
 64/*---------------------  Export Variables  --------------------------*/
 65static 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
 92static 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
143static 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
179int 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    	}
243spin_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       	}
284spin_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
460static 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
490static 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
522static 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
551static 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
578static 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
609static 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
750static 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);
791else
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;
857if (!((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
902int 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
989out:
990	kfree(param);
991
992	return ret;
993}
994