summaryrefslogblamecommitdiffstats
path: root/drivers/staging/otus/ioctl.c
blob: 7a5c1e876b01c9e923d695541f1763f712e76ec6 (plain) (tree)
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913







































































































































































                                                                           
                                                 
























































                                                                       
                                                  



















































































                                                                                                
             



















                                                               
             



















                                                                    
                     






























                                                           
             



















                                                                     
             



















                                                               
             























                                                                            
                     
















                                                                               
                     




















                                                                                                       
                     



























                                                           
                     






















                                                           
                             




















                                                         
                                                 










                                              
                                               































































                                                                          
                                               













                                               
                                               



































                                              
                                               






                                
                                               
















                                     
                                                    
































































































































                                                                                  
                                               

























                                                                
                                               

































                                                                            
                                               














                                               
                                               































































                                                                                       
                                               




































                                                                        
                                               

















































                                                                          
                                               




















                                                   
                                                   











































                                                                              
                                               

















                                                
                                               



















                                              
                                               


















                                               
                                               


















                                               
                                               








                                
                                               







                                         
                                                    









































                                                          
                                               











































                                                                    
                                               





























































                                                                     
                                               



















                                               
                                               



                                
                                               





                                                         
                                                    






                                                                               
                                                

























































































































































































































































































































































































































































































































                                                                                                      
                                                     
















































































































































































                                                                                                                     
                                               





































































































































































































































































                                                                                                                               
                                                 
































































































                                                                                
                                               



                    



































































































































































































































































































































































































































                                                                                                    
/*
 * Copyright (c) 2007-2008 Atheros Communications Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/*                                                                      */
/*  Module Name : ioctl.c                                               */
/*                                                                      */
/*  Abstract                                                            */
/*      This module contains Linux wireless extension related functons. */
/*                                                                      */
/*  NOTES                                                               */
/*     Platform dependent.                                              */
/*                                                                      */
/************************************************************************/
#include <linux/module.h>
#include <linux/if_arp.h>
#include <asm/uaccess.h>

#include "usbdrv.h"

#define ZD_IOCTL_WPA			    (SIOCDEVPRIVATE + 1)
#define ZD_IOCTL_PARAM			    (SIOCDEVPRIVATE + 2)
#define ZD_IOCTL_GETWPAIE		    (SIOCDEVPRIVATE + 3)
#ifdef ZM_ENABLE_CENC
#define ZM_IOCTL_CENC               (SIOCDEVPRIVATE + 4)
#endif //ZM_ENABLE_CENC
#define ZD_PARAM_ROAMING		    0x0001
#define ZD_PARAM_PRIVACY		    0x0002
#define ZD_PARAM_WPA			    0x0003
#define ZD_PARAM_COUNTERMEASURES	0x0004
#define ZD_PARAM_DROPUNENCRYPTED	0x0005
#define ZD_PARAM_AUTH_ALGS		    0x0006
#define ZD_PARAM_WPS_FILTER		    0x0007

#ifdef ZM_ENABLE_CENC
#define P80211_PACKET_CENCFLAG		0x0001
#endif //ZM_ENABLE_CENC
#define P80211_PACKET_SETKEY     	0x0003

#define ZD_CMD_SET_ENCRYPT_KEY		0x0001
#define ZD_CMD_SET_MLME			    0x0002
#define ZD_CMD_SCAN_REQ			    0x0003
#define ZD_CMD_SET_GENERIC_ELEMENT	0x0004
#define ZD_CMD_GET_TSC			    0x0005

#define ZD_CRYPT_ALG_NAME_LEN		16
#define ZD_MAX_KEY_SIZE			    32
#define ZD_MAX_GENERIC_SIZE		    64

#if WIRELESS_EXT > 12
#include <net/iw_handler.h>
#endif

extern u16_t zfLnxGetVapId(zdev_t* dev);

static const u32_t channel_frequency_11A[] =
{
//Even element for Channel Number, Odd for Frequency
    36,5180,
    40,5200,
    44,5220,
    48,5240,
    52,5260,
    56,5280,
    60,5300,
    64,5320,
    100,5500,
    104,5520,
    108,5540,
    112,5560,
    116,5580,
    120,5600,
    124,5620,
    128,5640,
    132,5660,
    136,5680,
    140,5700,
//
    184,4920,
    188,4940,
    192,4960,
    196,4980,
    8,5040,
    12,5060,
    16,5080,
    34,5170,
    38,5190,
    42,5210,
    46,5230,
//
    149,5745,
    153,5765,
    157,5785,
    161,5805,
    165,5825
//
};

int usbdrv_freq2chan(u32_t freq)
{
    /* 2.4G Hz */
    if (freq > 2400 && freq < 3000)
    {
        return ((freq-2412)/5) + 1;
    }
    else
    {
        u16_t ii;
        u16_t num_chan = sizeof(channel_frequency_11A)/sizeof(u32_t);

        for(ii = 1; ii < num_chan; ii += 2)
        {
            if (channel_frequency_11A[ii] == freq)
                return channel_frequency_11A[ii-1];
        }
    }

    return 0;
}

int usbdrv_chan2freq(int chan)
{
    int freq;

    /* If channel number is out of range */
    if (chan > 165 || chan <= 0)
        return -1;

    /* 2.4G band */
    if (chan >= 1 && chan <= 13)
    {
        freq = (2412 + (chan - 1) * 5);
        return freq;
    }
    else if (chan >= 36 && chan <= 165)
    {
        u16_t ii;
        u16_t num_chan = sizeof(channel_frequency_11A)/sizeof(u32_t);

        for(ii = 0; ii < num_chan; ii += 2)
        {
            if (channel_frequency_11A[ii] == chan)
                return channel_frequency_11A[ii+1];
        }

        /* Can't find desired frequency */
        if (ii == num_chan)
           return -1;
    }

    /* Can't find deisred frequency */
    return -1;
}

int usbdrv_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
{
#ifdef ZM_HOSTAPD_SUPPORT
    //struct usbdrv_private *macp = dev->ml_priv;
    char essidbuf[IW_ESSID_MAX_SIZE+1];
    int i;

    if(!netif_running(dev))
        return -EINVAL;

    memset(essidbuf, 0, sizeof(essidbuf));

    printk(KERN_ERR "usbdrv_ioctl_setessid\n");

    //printk("ssidlen=%d\n", erq->length); //for any, it is 1.
    if (erq->flags) {
        if (erq->length > (IW_ESSID_MAX_SIZE+1))
            return -E2BIG;

        if (copy_from_user(essidbuf, erq->pointer, erq->length))
            return -EFAULT;
    }

    //zd_DisasocAll(2);
    //wait_ms(100);

    printk(KERN_ERR "essidbuf: ");

    for(i = 0; i < erq->length; i++)
    {
        printk(KERN_ERR "%02x ", essidbuf[i]);
    }

    printk(KERN_ERR "\n");

    essidbuf[erq->length] = '\0';
    //memcpy(macp->wd.ws.ssid, essidbuf, erq->length);
    //macp->wd.ws.ssidLen = strlen(essidbuf)+2;
    //macp->wd.ws.ssid[1] = strlen(essidbuf); // Update ssid length

    zfiWlanSetSSID(dev, essidbuf, erq->length);
#if 0
    printk(KERN_ERR "macp->wd.ws.ssid: ");

    for(i = 0; i < macp->wd.ws.ssidLen; i++)
    {
        printk(KERN_ERR "%02x ", macp->wd.ws.ssid[i]);
    }

    printk(KERN_ERR "\n");
#endif
    zfiWlanDisable(dev, 0);
    zfiWlanEnable(dev);

#endif

    return 0;
}

int usbdrv_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
{
     //struct usbdrv_private *macp = dev->ml_priv;
     u8_t essidbuf[IW_ESSID_MAX_SIZE+1];
     u8_t len;
     u8_t i;


     //len = macp->wd.ws.ssidLen;
     //memcpy(essidbuf, macp->wd.ws.ssid, macp->wd.ws.ssidLen);
     zfiWlanQuerySSID(dev, essidbuf, &len);

     essidbuf[len] = 0;

     printk(KERN_ERR "ESSID: ");

     for(i = 0; i < len; i++)
     {
         printk(KERN_ERR "%c", essidbuf[i]);
     }

     printk(KERN_ERR "\n");

     erq->flags= 1;
     erq->length = strlen(essidbuf) + 1;

     if (erq->pointer)
         if (copy_to_user(erq->pointer, essidbuf, erq->length))
             return -EFAULT;

     return 0;
}


int usbdrv_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
{

    return 0;
}

#if WIRELESS_EXT > 14
/*
 * Encode a WPA or RSN information element as a custom
 * element using the hostap format.
 */
u32 encode_ie(void *buf, u32 bufsize, const u8 *ie, u32 ielen, const u8 *leader, u32 leader_len)
{
    u8 *p;
    u32 i;

    if (bufsize < leader_len)
        return 0;
    p = buf;
    memcpy(p, leader, leader_len);
    bufsize -= leader_len;
    p += leader_len;
    for (i = 0; i < ielen && bufsize > 2; i++)
        p += sprintf(p, "%02x", ie[i]);
    return (i == ielen ? p - (u8 *)buf : 0);
}
#endif                                            /* WIRELESS_EXT > 14 */

/*------------------------------------------------------------------*/
/*
 * Translate scan data returned from the card to a card independent
 * format that the Wireless Tools will understand
 */
char *usbdrv_translate_scan(struct net_device *dev,
	struct iw_request_info *info, char *current_ev,
        char *end_buf, struct zsBssInfo *list)
{
    struct iw_event iwe;                          /* Temporary buffer */
    u16_t capabilities;
    char *current_val;                            /* For rates */
    char *last_ev;
    int i;
#if WIRELESS_EXT > 14
    char    buf[64*2 + 30];
#endif

    last_ev = current_ev;

/* First entry *MUST* be the AP MAC address */
    iwe.cmd = SIOCGIWAP;
    iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
    memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN);
    current_ev = iwe_stream_add_event(
	info,
	current_ev,
	end_buf, &iwe, IW_EV_ADDR_LEN);

    /* Ran out of buffer */
    if (last_ev == current_ev)
    {
        return end_buf;
    }

    last_ev = current_ev;

/* Other entries will be displayed in the order we give them */

/* Add the ESSID */
    iwe.u.data.length = list->ssid[1];
    if(iwe.u.data.length > 32)
        iwe.u.data.length = 32;
    iwe.cmd = SIOCGIWESSID;
    iwe.u.data.flags = 1;
    current_ev = iwe_stream_add_point(
	info,
	current_ev, end_buf, &iwe, &list->ssid[2]);

    /* Ran out of buffer */
    if (last_ev == current_ev)
    {
        return end_buf;
    }

    last_ev = current_ev;

/* Add mode */
    iwe.cmd = SIOCGIWMODE;
    capabilities = (list->capability[1] << 8) + list->capability[0];
    if(capabilities & (0x01 | 0x02))
    {
        if(capabilities & 0x01)
            iwe.u.mode = IW_MODE_MASTER;
        else
            iwe.u.mode = IW_MODE_ADHOC;
        current_ev = iwe_stream_add_event(
		info,
		current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
    }

    /* Ran out of buffer */
    if (last_ev == current_ev)
    {
        return end_buf;
    }

    last_ev = current_ev;

/* Add frequency */
    iwe.cmd = SIOCGIWFREQ;
    iwe.u.freq.m = list->channel;
/* Channel frequency in KHz */
    if (iwe.u.freq.m > 14)
    {
        if ((184 <= iwe.u.freq.m) && (iwe.u.freq.m<=196))
              iwe.u.freq.m = 4000 + iwe.u.freq.m * 5;
        else
              iwe.u.freq.m = 5000 + iwe.u.freq.m * 5;
    }
    else
    {
        if (iwe.u.freq.m == 14)
              iwe.u.freq.m = 2484;
        else
              iwe.u.freq.m = 2412 + (iwe.u.freq.m - 1) * 5;
    }
    iwe.u.freq.e = 6;
    current_ev = iwe_stream_add_event(
	info,
    	current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);

    /* Ran out of buffer */
    if (last_ev == current_ev)
    {
        return end_buf;
    }

    last_ev = current_ev;

/* Add quality statistics */
    iwe.cmd = IWEVQUAL;
#if WIRELESS_EXT > 18
    iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
                        |IW_QUAL_NOISE_UPDATED;
#endif
    iwe.u.qual.level = list->signalStrength;
    iwe.u.qual.noise = 0;
    iwe.u.qual.qual = list->signalQuality;
    current_ev = iwe_stream_add_event(
	info,
	current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);

    /* Ran out of buffer */
    if (last_ev == current_ev)
    {
        return end_buf;
    }

    last_ev = current_ev;

/* Add encryption capability */

    iwe.cmd = SIOCGIWENCODE;
    if(capabilities & 0x10)
        iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
    else
        iwe.u.data.flags = IW_ENCODE_DISABLED;

    iwe.u.data.length = 0;
    current_ev = iwe_stream_add_point(
	info,
	current_ev, end_buf, &iwe, list->ssid);

    /* Ran out of buffer */
    if (last_ev == current_ev)
    {
        return end_buf;
    }

    last_ev = current_ev;

/* Rate : stuffing multiple values in a single event require a bit
 * more of magic */
    current_val = current_ev + IW_EV_LCP_LEN;

    iwe.cmd = SIOCGIWRATE;
/* Those two flags are ignored... */
    iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;

    for(i = 0 ; i < list->supportedRates[1] ; i++)
    {
/* Bit rate given in 500 kb/s units (+ 0x80) */
        iwe.u.bitrate.value = ((list->supportedRates[i+2] & 0x7f) * 500000);
/* Add new value to event */
        current_val = iwe_stream_add_value(
		info,
		current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);

        /* Ran out of buffer */
        if (last_ev == current_val)
        {
            return end_buf;
        }

        last_ev = current_val;
    }

    for (i = 0 ; i < list->extSupportedRates[1] ; i++)
    {
/* Bit rate given in 500 kb/s units (+ 0x80) */
        iwe.u.bitrate.value = ((list->extSupportedRates[i+2] & 0x7f) * 500000);
/* Add new value to event */
        current_val = iwe_stream_add_value(
		info,
		current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);

        /* Ran out of buffer */
        if (last_ev == current_val)
        {
            return end_buf;
        }

        last_ev = current_ev;
    }

/* Check if we added any event */
    if((current_val - current_ev) > IW_EV_LCP_LEN)
        current_ev = current_val;
#if WIRELESS_EXT > 14
#define IEEE80211_ELEMID_RSN 0x30
    memset(&iwe, 0, sizeof(iwe));
    iwe.cmd = IWEVCUSTOM;
    snprintf(buf, sizeof(buf), "bcn_int=%d", (list->beaconInterval[1] << 8) + list->beaconInterval[0]);
    iwe.u.data.length = strlen(buf);
    current_ev = iwe_stream_add_point(
		info,
		current_ev, end_buf, &iwe, buf);

    /* Ran out of buffer */
    if (last_ev == current_ev)
    {
        return end_buf;
    }

    last_ev = current_ev;

    if (list->wpaIe[1] != 0)
    {
        static const char rsn_leader[] = "rsn_ie=";
        static const char wpa_leader[] = "wpa_ie=";

        memset(&iwe, 0, sizeof(iwe));
        iwe.cmd = IWEVCUSTOM;
        if (list->wpaIe[0] == IEEE80211_ELEMID_RSN)
            iwe.u.data.length = encode_ie(buf, sizeof(buf),
                list->wpaIe, list->wpaIe[1]+2,
                rsn_leader, sizeof(rsn_leader)-1);
        else
            iwe.u.data.length = encode_ie(buf, sizeof(buf),
                list->wpaIe, list->wpaIe[1]+2,
                wpa_leader, sizeof(wpa_leader)-1);

        if (iwe.u.data.length != 0)
            current_ev = iwe_stream_add_point(
		info,
		current_ev, end_buf, &iwe, buf);

        /* Ran out of buffer */
        if (last_ev == current_ev)
        {
            return end_buf;
        }

        last_ev = current_ev;
    }
    if (list->rsnIe[1] != 0)
    {
        static const char rsn_leader[] = "rsn_ie=";
        memset(&iwe, 0, sizeof(iwe));
        iwe.cmd = IWEVCUSTOM;

        if (list->rsnIe[0] == IEEE80211_ELEMID_RSN)
        {
            iwe.u.data.length = encode_ie(buf, sizeof(buf),
                list->rsnIe, list->rsnIe[1]+2,
                rsn_leader, sizeof(rsn_leader)-1);
            if (iwe.u.data.length != 0)
                current_ev = iwe_stream_add_point(
			info,
			current_ev, end_buf,  &iwe, buf);

            /* Ran out of buffer */
            if (last_ev == current_ev)
            {
                return end_buf;
            }

            last_ev = current_ev;
        }
    }
#endif
/* The other data in the scan result are not really
 * interesting, so for now drop it */
    return current_ev;
}

int usbdrvwext_giwname(struct net_device *dev,
            struct iw_request_info *info,
            union iwreq_data *wrq, char *extra)
{
    //struct usbdrv_private *macp = dev->ml_priv;

    strcpy(wrq->name, "IEEE 802.11-MIMO");

    return 0;
}

int usbdrvwext_siwfreq(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_freq *freq, char *extra)
{
    u32_t FreqKHz;
    struct usbdrv_private *macp = dev->ml_priv;

    if(!netif_running(dev))
        return -EINVAL;

    if (freq->e > 1)
        return -EINVAL;

    if (freq->e == 1)
    {
        FreqKHz = (freq->m / 100000);

        if (FreqKHz > 4000000)
        {
            if (FreqKHz > 5825000)
                FreqKHz = 5825000;
            else if (FreqKHz < 4920000)
                FreqKHz = 4920000;
            else if (FreqKHz < 5000000)
                FreqKHz = (((FreqKHz - 4000000) / 5000) * 5000) + 4000000;
            else
                FreqKHz = (((FreqKHz - 5000000) / 5000) * 5000) + 5000000;
        }
        else
        {
            if (FreqKHz > 2484000)
                FreqKHz = 2484000;
            else if (FreqKHz < 2412000)
                FreqKHz = 2412000;
            else
                FreqKHz = (((FreqKHz - 2412000) / 5000) * 5000) + 2412000;
        }

    }
    else
    {
        FreqKHz = usbdrv_chan2freq(freq->m);

        if (FreqKHz != -1)
            FreqKHz *= 1000;
        else
            FreqKHz = 2412000;
    }

    //printk("freq->m: %d, freq->e: %d\n", freq->m, freq->e);
    //printk("FreqKHz: %d\n", FreqKHz);

    if (macp->DeviceOpened == 1)
    {
        zfiWlanSetFrequency(dev, FreqKHz, 0); // Immediate
        //u8_t wpaieLen,wpaie[50];
        //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen);
        zfiWlanDisable(dev, 0);
        zfiWlanEnable(dev);
        //if (wpaieLen > 2)
        //    zfiWlanSetWpaIe(dev, wpaie, wpaieLen);
    }

    return 0;
}

int usbdrvwext_giwfreq(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_freq *freq, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;

    if (macp->DeviceOpened != 1)
        return 0;

    freq->m = zfiWlanQueryFrequency(dev);
    freq->e = 3;

    return 0;
}

int usbdrvwext_siwmode(struct net_device *dev,
            struct iw_request_info *info,
            union iwreq_data *wrq, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;
    u8_t WlanMode;

    if(!netif_running(dev))
        return -EINVAL;

    if (macp->DeviceOpened != 1)
        return 0;

    switch(wrq->mode)
    {
        case IW_MODE_MASTER:
            WlanMode = ZM_MODE_AP;
            break;
        case IW_MODE_INFRA:
            WlanMode = ZM_MODE_INFRASTRUCTURE;
            break;
        case IW_MODE_ADHOC:
            WlanMode = ZM_MODE_IBSS;
            break;
        default:
            WlanMode = ZM_MODE_IBSS;
            break;
    }

    zfiWlanSetWlanMode(dev,WlanMode);
    zfiWlanDisable(dev, 1);
    zfiWlanEnable(dev);

    return 0;
}

int usbdrvwext_giwmode(struct net_device *dev,
            struct iw_request_info *info,
            __u32 *mode, char *extra)
{
    unsigned long irqFlag;
    struct usbdrv_private *macp = dev->ml_priv;

    if(!netif_running(dev))
        return -EINVAL;

    if (macp->DeviceOpened != 1)
        return 0;

    spin_lock_irqsave(&macp->cs_lock, irqFlag);

    switch(zfiWlanQueryWlanMode(dev))
    {
        case ZM_MODE_AP:
            *mode = IW_MODE_MASTER;
            break;
        case ZM_MODE_INFRASTRUCTURE:
            *mode = IW_MODE_INFRA;
            break;
        case ZM_MODE_IBSS:
            *mode = IW_MODE_ADHOC;
            break;
        default:
            *mode = IW_MODE_ADHOC;
            break;
    }

    spin_unlock_irqrestore(&macp->cs_lock, irqFlag);

    return 0;
}

int usbdrvwext_siwsens(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_param *sens, char *extra)
{
	return 0;
}

int usbdrvwext_giwsens(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_param *sens, char *extra)
{
	sens->value = 0;
	sens->fixed = 1;

	return 0;
}

int usbdrvwext_giwrange(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_point *data, char *extra)
{
    struct iw_range *range = (struct iw_range *) extra;
    int i, val;
    //int num_band_a;
    u16_t channels[60];
    u16_t channel_num;

    if(!netif_running(dev))
        return -EINVAL;

#if WIRELESS_EXT > 9
    range->txpower_capa = IW_TXPOW_DBM;
// XXX what about min/max_pmp, min/max_pmt, etc.
#endif

#if WIRELESS_EXT > 10
    range->we_version_compiled = WIRELESS_EXT;
    range->we_version_source = 13;

    range->retry_capa = IW_RETRY_LIMIT;
    range->retry_flags = IW_RETRY_LIMIT;
    range->min_retry = 0;
    range->max_retry = 255;
#endif                                        /* WIRELESS_EXT > 10 */

    channel_num = zfiWlanQueryAllowChannels(dev, channels);

    /* Gurantee reported channel numbers is less or equal to IW_MAX_FREQUENCIES */
    if (channel_num > IW_MAX_FREQUENCIES)
        channel_num = IW_MAX_FREQUENCIES;

    val = 0;

    for (i = 0; i < channel_num; i++)
    {
        range->freq[val].i = usbdrv_freq2chan(channels[i]);
        range->freq[val].m = channels[i];
        range->freq[val].e = 6;
        val++;
    }

    range->num_channels = channel_num;
    range->num_frequency = channel_num;

#if 0
    range->num_channels = 14; // Only 2.4G

/* XXX need to filter against the regulatory domain &| active set */
    val = 0;
    for (i = 1; i <= 14; i++) // B,G Bands
    {
        range->freq[val].i = i;
        if (i == 14)
              range->freq[val].m = 2484000;
        else
              range->freq[val].m = (2412+(i-1)*5)*1000;
        range->freq[val].e = 3;
        val++;
    }

    num_band_a = (IW_MAX_FREQUENCIES - val);

    for (i = 0; i < num_band_a; i++) // A Bands
    {
        range->freq[val].i = channel_frequency_11A[2 * i];
        range->freq[val].m = channel_frequency_11A[2 * i + 1] * 1000;
        range->freq[val].e = 3;
        val++;
    }
    // MIMO Rate Not Defined Now
    //For 802.11a, there are too more frequency. We can't return them all
    range->num_frequency = val;
#endif

/* Max of /proc/net/wireless */
    range->max_qual.qual = 100; //??                  //92;
    range->max_qual.level = 154; //??
    range->max_qual.noise = 154; //??
    range->sensitivity = 3; //??

// XXX these need to be nsd-specific!
    range->min_rts = 0;
    range->max_rts = 2347;
    range->min_frag = 256;
    range->max_frag = 2346;
    range->max_encoding_tokens = 4/*NUM_WEPKEYS*/; //??
    range->num_encoding_sizes = 2; //??

    range->encoding_size[0] = 5; //??               //WEP Key Encoding Size
    range->encoding_size[1] = 13;//??

// XXX what about num_bitrates/throughput?
    range->num_bitrates = 0; //??

/* estimated max throughput */
// XXX need to cap it if we're running at ~2Mbps..

    range->throughput = 300000000;

    return 0;
}

int usbdrvwext_siwap(struct net_device *dev, struct iw_request_info *info,
        struct sockaddr *MacAddr, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;

    if(!netif_running(dev))
        return -EINVAL;

    if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode
        zfiWlanSetMacAddress(dev,(u16_t *)&MacAddr->sa_data[0]);
    else                                 //STA Mode
        zfiWlanSetBssid(dev,&MacAddr->sa_data[0]);

    if (macp->DeviceOpened == 1)
    {
        //u8_t wpaieLen,wpaie[80];
        //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen);
        zfiWlanDisable(dev, 0);
        zfiWlanEnable(dev);
        //if (wpaieLen > 2)
        //    zfiWlanSetWpaIe(dev, wpaie, wpaieLen);
    }

    return 0;
}

int usbdrvwext_giwap(struct net_device *dev,
            struct iw_request_info *info,
            struct sockaddr *MacAddr, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;

    if (macp->DeviceOpened != 1)
        return 0;

    if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode
        zfiWlanQueryMacAddress(dev, &MacAddr->sa_data[0]);
    else                                 //STA Mode
    {
        if (macp->adapterState == ZM_STATUS_MEDIA_CONNECT)
        {
            zfiWlanQueryBssid(dev, &MacAddr->sa_data[0]);
        }
        else
        {
            u8_t zero_addr[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            memcpy(&MacAddr->sa_data[0], zero_addr, sizeof(zero_addr));
        }
    }

    return 0;
}

int usbdrvwext_iwaplist(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_point *data, char *extra)
{
    //Don't know how to do yet--CWYang(+)
    return 0;

}

int usbdrvwext_siwscan(struct net_device *dev, struct iw_request_info *info,
        struct iw_point *data, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;

    if (macp->DeviceOpened != 1)
        return 0;

    printk("CWY - usbdrvwext_siwscan\n");

    zfiWlanScan(dev);

    return 0;
}

int usbdrvwext_giwscan(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_point *data, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;
    //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
    char *current_ev = extra;
    char *end_buf;
    int i;
    //struct zsBssList BssList;
    struct zsBssListV1 *pBssList = kmalloc(sizeof(struct zsBssListV1), GFP_KERNEL);
    //BssList = wd->sta.pBssList;
    //zmw_get_wlan_dev(dev);

    if (macp->DeviceOpened != 1)
        return 0;

    if (data->length == 0)
    {
       end_buf = extra + IW_SCAN_MAX_DATA;
    }
    else
    {
        end_buf = extra + data->length;
    }

    printk("giwscan - Report Scan Results\n");
    //printk("giwscan - BssList Sreucture Len : %d\n", sizeof(BssList));
    //printk("giwscan - BssList Count : %d\n", wd->sta.pBssList->bssCount);
    //printk("giwscan - UpdateBssList Count : %d\n", wd->sta.pUpdateBssList->bssCount);
    zfiWlanQueryBssListV1(dev, pBssList);
    //zfiWlanQueryBssList(dev, &BssList);

/* Read and parse all entries */
    printk("giwscan - pBssList->bssCount : %d\n", pBssList->bssCount);
    //printk("giwscan - BssList.bssCount : %d\n", BssList.bssCount);

    for (i = 0; i < pBssList->bssCount; i++)
    {
/* Translate to WE format this entry */
        //current_ev = usbdrv_translate_scan(dev, info, current_ev,
        //    extra + IW_SCAN_MAX_DATA, &pBssList->bssInfo[i]);
        current_ev = usbdrv_translate_scan(dev, info, current_ev,
            end_buf, &pBssList->bssInfo[i]);

#if WIRELESS_EXT > 16
        if (current_ev == end_buf)
        {
            kfree(pBssList);
            data->length = current_ev - extra;
            return -E2BIG;
        }
#endif
    }

/* Length of data */
    data->length = (current_ev - extra);
    data->flags = 0;                              /* todo */

    kfree(pBssList);

    return 0;
}

int usbdrvwext_siwessid(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_point *essid, char *extra)
{
    char EssidBuf[IW_ESSID_MAX_SIZE+1];
    struct usbdrv_private *macp = dev->ml_priv;

    if(!netif_running(dev))
        return -EINVAL;

    if (essid->flags == 1)
    {
        if (essid->length > (IW_ESSID_MAX_SIZE+1))
            return -E2BIG;

        if (copy_from_user(&EssidBuf, essid->pointer, essid->length))
            return -EFAULT;

        EssidBuf[essid->length] = '\0';
        //printk("siwessid - Set Essid : %s\n",EssidBuf);
        //printk("siwessid - Essid Len : %d\n",essid->length);
        //printk("siwessid - Essid Flag : %x\n",essid->flags);
        if (macp->DeviceOpened == 1)
        {
            zfiWlanSetSSID(dev, EssidBuf, strlen(EssidBuf));
            zfiWlanSetFrequency(dev, zfiWlanQueryFrequency(dev), FALSE);
            zfiWlanSetEncryMode(dev, zfiWlanQueryEncryMode(dev));
            //u8_t wpaieLen,wpaie[50];
            //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen);
            zfiWlanDisable(dev, 0);
            zfiWlanEnable(dev);
            //if (wpaieLen > 2)
            //    zfiWlanSetWpaIe(dev, wpaie, wpaieLen);
        }
    }

    return 0;
}

int usbdrvwext_giwessid(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_point *essid, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;
    u8_t EssidLen;
    char EssidBuf[IW_ESSID_MAX_SIZE+1];
    int ssid_len;

    if(!netif_running(dev))
        return -EINVAL;

    if (macp->DeviceOpened != 1)
        return 0;

    zfiWlanQuerySSID(dev, &EssidBuf[0], &EssidLen);

    /* Convert type from unsigned char to char */
    ssid_len = (int)EssidLen;

    /* Make sure the essid length is not greater than IW_ESSID_MAX_SIZE */
    if (ssid_len > IW_ESSID_MAX_SIZE)
        ssid_len = IW_ESSID_MAX_SIZE;

    EssidBuf[ssid_len] = '\0';

    essid->flags = 1;
    essid->length = strlen(EssidBuf);

    memcpy(extra, EssidBuf, essid->length);
    // wireless.c in Kernel would handle copy_to_user -- line 679
    /*if (essid->pointer)
    {
        if ( copy_to_user(essid->pointer, EssidBuf, essid->length) )
        {
            printk("giwessid - copy_to_user Fail\n");
            return -EFAULT;
        }
    }*/

    return 0;
}

int usbdrvwext_siwnickn(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_point *data, char *nickname)
{
    //Exist but junk--CWYang(+)
	return 0;
}

int usbdrvwext_giwnickn(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_point *data, char *nickname)
{
    struct usbdrv_private *macp = dev->ml_priv;
    u8_t EssidLen;
    char EssidBuf[IW_ESSID_MAX_SIZE+1];

    if (macp->DeviceOpened != 1)
        return 0;

    zfiWlanQuerySSID(dev, &EssidBuf[0], &EssidLen);
    EssidBuf[EssidLen] = 0;

    data->flags = 1;
    data->length = strlen(EssidBuf);

    memcpy(nickname, EssidBuf, data->length);

	return 0;
}

int usbdrvwext_siwrate(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_param *frq, char *extra)
{
	struct usbdrv_private *macp = dev->ml_priv;
    //Array to Define Rate Number that Send to Driver
    u16_t zcIndextoRateBG[16] = {1000, 2000, 5500, 11000, 0, 0, 0, 0, 48000,
                               24000, 12000, 6000, 54000, 36000, 18000, 9000};
    u16_t zcRateToMCS[] = {0xff, 0, 1, 2, 3, 0xb, 0xf, 0xa, 0xe, 0x9, 0xd,
                           0x8, 0xc};
    u8_t i,RateIndex = 4;
    u16_t RateKbps;

    //printk("frq->disabled : 0x%x\n",frq->disabled);
    //printk("frq->value : 0x%x\n",frq->value);

    RateKbps = frq->value / 1000;
    //printk("RateKbps : %d\n", RateKbps);
    for (i = 0; i < 16; i++)
    {
        if (RateKbps == zcIndextoRateBG[i])
            RateIndex = i;
    }
    if (zcIndextoRateBG[RateIndex] == 0)
        RateIndex = 0xff;
    //printk("RateIndex : %x\n", RateIndex);
    for (i = 0; i < 13; i++)
        if (RateIndex == zcRateToMCS[i])
            break;
    //printk("Index : %x\n", i);
    if (RateKbps == 65000)
    {
        RateIndex = 20;
        printk("RateIndex : %d\n", RateIndex);
    }
    if (macp->DeviceOpened == 1)
    {
        zfiWlanSetTxRate(dev, i);
        //zfiWlanDisable(dev);
        //zfiWlanEnable(dev);
    }

    return 0;
}

int usbdrvwext_giwrate(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_param *frq, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;

    if(!netif_running(dev))
        return -EINVAL;

    if (macp->DeviceOpened != 1)
        return 0;

    frq->fixed = 0;
    frq->disabled = 0;
    frq->value = zfiWlanQueryRxRate(dev) * 1000;

    return 0;
}

int usbdrvwext_siwrts(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_param *rts, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;
    int val = rts->value;

    if (macp->DeviceOpened != 1)
        return 0;

    if (rts->disabled)
        val = 2347;

    if ((val < 0) || (val > 2347))
        return -EINVAL;

    zfiWlanSetRtsThreshold(dev,val);

    return 0;
}

int usbdrvwext_giwrts(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_param *rts, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;

    if(!netif_running(dev))
        return -EINVAL;

    if (macp->DeviceOpened != 1)
        return 0;

    rts->value = zfiWlanQueryRtsThreshold(dev);
    rts->disabled = (rts->value >= 2347);
    rts->fixed = 1;

    return 0;

}

int usbdrvwext_siwfrag(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_param *frag, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;
    u16_t fragThreshold;

    if (macp->DeviceOpened != 1)
        return 0;

    if (frag->disabled)
        fragThreshold = 0;
    else
        fragThreshold = frag->value;

    zfiWlanSetFragThreshold(dev,fragThreshold);

    return 0;
}

int usbdrvwext_giwfrag(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_param *frag, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;
    u16 val;
    unsigned long irqFlag;

    if(!netif_running(dev))
        return -EINVAL;

    if (macp->DeviceOpened != 1)
        return 0;

    spin_lock_irqsave(&macp->cs_lock, irqFlag);

    val = zfiWlanQueryFragThreshold(dev);

    frag->value = val;

    frag->disabled = (val >= 2346);
    frag->fixed = 1;

    spin_unlock_irqrestore(&macp->cs_lock, irqFlag);

    return 0;
}

int usbdrvwext_siwtxpow(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_param *rrq, char *extra)
{
    //Not support yet--CWYng(+)
	return 0;
}

int usbdrvwext_giwtxpow(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_param *rrq, char *extra)
{
    //Not support yet--CWYng(+)
	return 0;
}

int usbdrvwext_siwretry(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_param *rrq, char *extra)
{
    //Do nothing--CWYang(+)
	return 0;
}

int usbdrvwext_giwretry(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_param *rrq, char *extra)
{
    //Do nothing--CWYang(+)
	return 0;
}

int usbdrvwext_siwencode(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_point *erq, char *key)
{
    struct zsKeyInfo keyInfo;
    int i, WepState = ZM_ENCRYPTION_WEP_DISABLED;
    struct usbdrv_private *macp = dev->ml_priv;

    if(!netif_running(dev))
        return -EINVAL;

    if ((erq->flags & IW_ENCODE_DISABLED) == 0)
    {
        keyInfo.key = key;
        keyInfo.keyLength = erq->length;
        keyInfo.keyIndex = (erq->flags & IW_ENCODE_INDEX) - 1;
        if (keyInfo.keyIndex >= 4)
            keyInfo.keyIndex = 0;
        keyInfo.flag = ZM_KEY_FLAG_DEFAULT_KEY;

        zfiWlanSetKey(dev, keyInfo);
        WepState = ZM_ENCRYPTION_WEP_ENABLED;
    }
    else
    {
        for (i = 1; i < 4; i++)
            zfiWlanRemoveKey(dev, 0, i);
        WepState = ZM_ENCRYPTION_WEP_DISABLED;
        //zfiWlanSetEncryMode(dev, ZM_NO_WEP);
    }

    if (macp->DeviceOpened == 1)
    {
        zfiWlanSetWepStatus(dev, WepState);
        zfiWlanSetFrequency(dev, zfiWlanQueryFrequency(dev), FALSE);
        //zfiWlanSetEncryMode(dev, zfiWlanQueryEncryMode(dev));
        //u8_t wpaieLen,wpaie[50];
        //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen);
        zfiWlanDisable(dev, 0);
        zfiWlanEnable(dev);
        //if (wpaieLen > 2)
        //    zfiWlanSetWpaIe(dev, wpaie, wpaieLen);
    }

    return 0;
}

int usbdrvwext_giwencode(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_point *erq, char *key)
{
    struct usbdrv_private *macp = dev->ml_priv;
    u8_t EncryptionMode;
    u8_t keyLen = 0;

    if (macp->DeviceOpened != 1)
        return 0;

    EncryptionMode = zfiWlanQueryEncryMode(dev);

    if (EncryptionMode)
    {
        erq->flags = IW_ENCODE_ENABLED;
    }
    else
    {
        erq->flags = IW_ENCODE_DISABLED;
    }

/* We can't return the key, so set the proper flag and return zero */
    erq->flags |= IW_ENCODE_NOKEY;
    memset(key, 0, 16);

/* Copy the key to the user buffer */
    switch(EncryptionMode)
    {
        case ZM_WEP64:
            keyLen = 5;
            break;
        case ZM_WEP128:
            keyLen = 13;
            break;
        case ZM_WEP256:
            keyLen = 29;
            break;
        case ZM_AES:
            keyLen = 16;
            break;
        case ZM_TKIP:
            keyLen = 32;
            break;
#ifdef ZM_ENABLE_CENC
        case ZM_CENC:
            keyLen = 32;
            break;
#endif //ZM_ENABLE_CENC
        case ZM_NO_WEP:
            keyLen = 0;
            break;
        default :
            keyLen = 0;
            printk("Unknown EncryMode\n");
            break;

    }
    erq->length = keyLen;

    return 0;
}

int usbdrvwext_siwpower(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_param *frq, char *extra)
{
    struct usbdrv_private *macp = dev->ml_priv;
    u8_t PSMode;

    if (macp->DeviceOpened != 1)
        return 0;

    if (frq->disabled)
        PSMode = ZM_STA_PS_NONE;
    else
        PSMode = ZM_STA_PS_MAX;

    zfiWlanSetPowerSaveMode(dev,PSMode);

    return 0;
}

int usbdrvwext_giwpower(struct net_device *dev,
            struct iw_request_info *info,
            struct iw_param *frq, char *extra)
{
    unsigned long irqFlag;
    struct usbdrv_private *macp = dev->ml_priv;

    if (macp->DeviceOpened != 1)
        return 0;

    spin_lock_irqsave(&macp->cs_lock, irqFlag);

    if (zfiWlanQueryPowerSaveMode(dev) == ZM_STA_PS_NONE)
        frq->disabled = 1;
    else
        frq->disabled = 0;

    spin_unlock_irqrestore(&macp->cs_lock, irqFlag);

    return 0;
}

//int usbdrvwext_setparam(struct net_device *dev, struct iw_request_info *info,
//		   	 void *w, char *extra)
//{
//	struct ieee80211vap *vap = dev->ml_priv;
//	struct ieee80211com *ic = vap->iv_ic;
//	struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
//	int *i = (int *) extra;
//	int param = i[0];		/* parameter id is 1st */
//	int value = i[1];		/* NB: most values are TYPE_INT */
//	int retv = 0;
//	int j, caps;
//	const struct ieee80211_authenticator *auth;
//	const struct ieee80211_aclator *acl;
//
//	switch (param) {
//	case IEEE80211_PARAM_AUTHMODE:
//		switch (value) {
//		case IEEE80211_AUTH_WPA:	/* WPA */
//		case IEEE80211_AUTH_8021X:	/* 802.1x */
//		case IEEE80211_AUTH_OPEN:	/* open */
//		case IEEE80211_AUTH_SHARED:	/* shared-key */
//		case IEEE80211_AUTH_AUTO:	/* auto */
//			auth = ieee80211_authenticator_get(value);
//			if (auth == NULL)
//				return -EINVAL;
//			break;
//		default:
//			return -EINVAL;
//		}
//		switch (value) {
//		case IEEE80211_AUTH_WPA:	/* WPA w/ 802.1x */
//			vap->iv_flags |= IEEE80211_F_PRIVACY;
//			value = IEEE80211_AUTH_8021X;
//			break;
//		case IEEE80211_AUTH_OPEN:	/* open */
//			vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
//			break;
//		case IEEE80211_AUTH_SHARED:	/* shared-key */
//		case IEEE80211_AUTH_AUTO:	/* auto */
//		case IEEE80211_AUTH_8021X:	/* 802.1x */
//			vap->iv_flags &= ~IEEE80211_F_WPA;
//			/* both require a key so mark the PRIVACY capability */
//			vap->iv_flags |= IEEE80211_F_PRIVACY;
//			break;
//		}
//		/* NB: authenticator attach/detach happens on state change */
//		vap->iv_bss->ni_authmode = value;
//		/* XXX mixed/mode/usage? */
//		vap->iv_auth = auth;
//		retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_PROTMODE:
//		if (value > IEEE80211_PROT_RTSCTS)
//			return -EINVAL;
//		ic->ic_protmode = value;
//		/* NB: if not operating in 11g this can wait */
//		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
//		    IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
//			retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_MCASTCIPHER:
//		if ((vap->iv_caps & cipher2cap(value)) == 0 &&
//		    !ieee80211_crypto_available(value))
//			return -EINVAL;
//		rsn->rsn_mcastcipher = value;
//		if (vap->iv_flags & IEEE80211_F_WPA)
//			retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_MCASTKEYLEN:
//		if (!(0 < value && value < IEEE80211_KEYBUF_SIZE))
//			return -EINVAL;
//		/* XXX no way to verify driver capability */
//		rsn->rsn_mcastkeylen = value;
//		if (vap->iv_flags & IEEE80211_F_WPA)
//			retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_UCASTCIPHERS:
//		/*
//		 * Convert cipher set to equivalent capabilities.
//		 * NB: this logic intentionally ignores unknown and
//		 * unsupported ciphers so folks can specify 0xff or
//		 * similar and get all available ciphers.
//		 */
//		caps = 0;
//		for (j = 1; j < 32; j++)	/* NB: skip WEP */
//			if ((value & (1<<j)) &&
//			    ((vap->iv_caps & cipher2cap(j)) ||
//			     ieee80211_crypto_available(j)))
//				caps |= 1<<j;
//		if (caps == 0)			/* nothing available */
//			return -EINVAL;
//		/* XXX verify ciphers ok for unicast use? */
//		/* XXX disallow if running as it'll have no effect */
//		rsn->rsn_ucastcipherset = caps;
//		if (vap->iv_flags & IEEE80211_F_WPA)
//			retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_UCASTCIPHER:
//		if ((rsn->rsn_ucastcipherset & cipher2cap(value)) == 0)
//			return -EINVAL;
//		rsn->rsn_ucastcipher = value;
//		break;
//	case IEEE80211_PARAM_UCASTKEYLEN:
//		if (!(0 < value && value < IEEE80211_KEYBUF_SIZE))
//			return -EINVAL;
//		/* XXX no way to verify driver capability */
//		rsn->rsn_ucastkeylen = value;
//		break;
//	case IEEE80211_PARAM_KEYMGTALGS:
//		/* XXX check */
//		rsn->rsn_keymgmtset = value;
//		if (vap->iv_flags & IEEE80211_F_WPA)
//			retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_RSNCAPS:
//		/* XXX check */
//		rsn->rsn_caps = value;
//		if (vap->iv_flags & IEEE80211_F_WPA)
//			retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_WPA:
//		if (value > 3)
//			return -EINVAL;
//		/* XXX verify ciphers available */
//		vap->iv_flags &= ~IEEE80211_F_WPA;
//		switch (value) {
//		case 1:
//			vap->iv_flags |= IEEE80211_F_WPA1;
//			break;
//		case 2:
//			vap->iv_flags |= IEEE80211_F_WPA2;
//			break;
//		case 3:
//			vap->iv_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
//			break;
//		}
//		retv = ENETRESET;		/* XXX? */
//		break;
//	case IEEE80211_PARAM_ROAMING:
//		if (!(IEEE80211_ROAMING_DEVICE <= value &&
//		    value <= IEEE80211_ROAMING_MANUAL))
//			return -EINVAL;
//		ic->ic_roaming = value;
//		break;
//	case IEEE80211_PARAM_PRIVACY:
//		if (value) {
//			/* XXX check for key state? */
//			vap->iv_flags |= IEEE80211_F_PRIVACY;
//		} else
//			vap->iv_flags &= ~IEEE80211_F_PRIVACY;
//		break;
//	case IEEE80211_PARAM_DROPUNENCRYPTED:
//		if (value)
//			vap->iv_flags |= IEEE80211_F_DROPUNENC;
//		else
//			vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
//		break;
//	case IEEE80211_PARAM_COUNTERMEASURES:
//		if (value) {
//			if ((vap->iv_flags & IEEE80211_F_WPA) == 0)
//				return -EINVAL;
//			vap->iv_flags |= IEEE80211_F_COUNTERM;
//		} else
//			vap->iv_flags &= ~IEEE80211_F_COUNTERM;
//		break;
//	case IEEE80211_PARAM_DRIVER_CAPS:
//		vap->iv_caps = value;		/* NB: for testing */
//		break;
//	case IEEE80211_PARAM_MACCMD:
//		acl = vap->iv_acl;
//		switch (value) {
//		case IEEE80211_MACCMD_POLICY_OPEN:
//		case IEEE80211_MACCMD_POLICY_ALLOW:
//		case IEEE80211_MACCMD_POLICY_DENY:
//			if (acl == NULL) {
//				acl = ieee80211_aclator_get("mac");
//				if (acl == NULL || !acl->iac_attach(vap))
//					return -EINVAL;
//				vap->iv_acl = acl;
//			}
//			acl->iac_setpolicy(vap, value);
//			break;
//		case IEEE80211_MACCMD_FLUSH:
//			if (acl != NULL)
//				acl->iac_flush(vap);
//			/* NB: silently ignore when not in use */
//			break;
//		case IEEE80211_MACCMD_DETACH:
//			if (acl != NULL) {
//				vap->iv_acl = NULL;
//				acl->iac_detach(vap);
//			}
//			break;
//		}
//		break;
//	case IEEE80211_PARAM_WMM:
//		if (ic->ic_caps & IEEE80211_C_WME){
//			if (value) {
//				vap->iv_flags |= IEEE80211_F_WME;
//				vap->iv_ic->ic_flags |= IEEE80211_F_WME; /* XXX needed by ic_reset */
//			}
//			else {
//				vap->iv_flags &= ~IEEE80211_F_WME;
//				vap->iv_ic->ic_flags &= ~IEEE80211_F_WME; /* XXX needed by ic_reset */
//			}
//			retv = ENETRESET;	/* Renegotiate for capabilities */
//		}
//		break;
//	case IEEE80211_PARAM_HIDESSID:
//		if (value)
//			vap->iv_flags |= IEEE80211_F_HIDESSID;
//		else
//			vap->iv_flags &= ~IEEE80211_F_HIDESSID;
//		retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_APBRIDGE:
//		if (value == 0)
//			vap->iv_flags |= IEEE80211_F_NOBRIDGE;
//		else
//			vap->iv_flags &= ~IEEE80211_F_NOBRIDGE;
//		break;
//	case IEEE80211_PARAM_INACT:
//		vap->iv_inact_run = value / IEEE80211_INACT_WAIT;
//		break;
//	case IEEE80211_PARAM_INACT_AUTH:
//		vap->iv_inact_auth = value / IEEE80211_INACT_WAIT;
//		break;
//	case IEEE80211_PARAM_INACT_INIT:
//		vap->iv_inact_init = value / IEEE80211_INACT_WAIT;
//		break;
//	case IEEE80211_PARAM_ABOLT:
//		caps = 0;
//		/*
//		 * Map abolt settings to capability bits;
//		 * this also strips unknown/unwanted bits.
//		 */
//		if (value & IEEE80211_ABOLT_TURBO_PRIME)
//			caps |= IEEE80211_ATHC_TURBOP;
//		if (value & IEEE80211_ABOLT_COMPRESSION)
//			caps |= IEEE80211_ATHC_COMP;
//		if (value & IEEE80211_ABOLT_FAST_FRAME)
//			caps |= IEEE80211_ATHC_FF;
//		if (value & IEEE80211_ABOLT_XR)
//			caps |= IEEE80211_ATHC_XR;
//		if (value & IEEE80211_ABOLT_AR)
//			caps |= IEEE80211_ATHC_AR;
//		if (value & IEEE80211_ABOLT_BURST)
//			caps |= IEEE80211_ATHC_BURST;
//        if (value & IEEE80211_ABOLT_WME_ELE)
//            caps |= IEEE80211_ATHC_WME;
//		/* verify requested capabilities are supported */
//		if ((caps & ic->ic_ath_cap) != caps)
//			return -EINVAL;
//		if (vap->iv_ath_cap != caps) {
//			if ((vap->iv_ath_cap ^ caps) & IEEE80211_ATHC_TURBOP) {
//				if (ieee80211_set_turbo(dev,  caps & IEEE80211_ATHC_TURBOP))
//					return -EINVAL;
//				ieee80211_scan_flush(ic);
//			}
//			vap->iv_ath_cap = caps;
//			ic->ic_athcapsetup(vap->iv_ic, vap->iv_ath_cap);
//			retv = ENETRESET;
//		}
//		break;
//	case IEEE80211_PARAM_DTIM_PERIOD:
//		if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
//		    vap->iv_opmode != IEEE80211_M_IBSS)
//			return -EINVAL;
//		if (IEEE80211_DTIM_MIN <= value &&
//		    value <= IEEE80211_DTIM_MAX) {
//			vap->iv_dtim_period = value;
//			retv = ENETRESET;		/* requires restart */
//		} else
//			retv = EINVAL;
//		break;
//	case IEEE80211_PARAM_BEACON_INTERVAL:
//		if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
//		    vap->iv_opmode != IEEE80211_M_IBSS)
//			return -EINVAL;
//		if (IEEE80211_BINTVAL_MIN <= value &&
//		    value <= IEEE80211_BINTVAL_MAX) {
//			ic->ic_lintval = value;		/* XXX multi-bss */
//			retv = ENETRESET;		/* requires restart */
//		} else
//			retv = EINVAL;
//		break;
//	case IEEE80211_PARAM_DOTH:
//		if (value) {
//			ic->ic_flags |= IEEE80211_F_DOTH;
//		}
//		else
//			ic->ic_flags &= ~IEEE80211_F_DOTH;
//		retv = ENETRESET;	/* XXX: need something this drastic? */
//		break;
//	case IEEE80211_PARAM_PWRTARGET:
//		ic->ic_curchanmaxpwr = value;
//		break;
//	case IEEE80211_PARAM_GENREASSOC:
//		IEEE80211_SEND_MGMT(vap->iv_bss, IEEE80211_FC0_SUBTYPE_REASSOC_REQ, 0);
//		break;
//	case IEEE80211_PARAM_COMPRESSION:
//		retv = ieee80211_setathcap(vap, IEEE80211_ATHC_COMP, value);
//		break;
//    case IEEE80211_PARAM_WMM_AGGRMODE:
//        retv = ieee80211_setathcap(vap, IEEE80211_ATHC_WME, value);
//        break;
//	case IEEE80211_PARAM_FF:
//		retv = ieee80211_setathcap(vap, IEEE80211_ATHC_FF, value);
//		break;
//	case IEEE80211_PARAM_TURBO:
//		retv = ieee80211_setathcap(vap, IEEE80211_ATHC_TURBOP, value);
//		if (retv == ENETRESET) {
//			if(ieee80211_set_turbo(dev,value))
//					return -EINVAL;
//			ieee80211_scan_flush(ic);
//		}
//		break;
//	case IEEE80211_PARAM_XR:
//		retv = ieee80211_setathcap(vap, IEEE80211_ATHC_XR, value);
//		break;
//	case IEEE80211_PARAM_BURST:
//		retv = ieee80211_setathcap(vap, IEEE80211_ATHC_BURST, value);
//		break;
//	case IEEE80211_PARAM_AR:
//		retv = ieee80211_setathcap(vap, IEEE80211_ATHC_AR, value);
//		break;
//	case IEEE80211_PARAM_PUREG:
//		if (value)
//			vap->iv_flags |= IEEE80211_F_PUREG;
//		else
//			vap->iv_flags &= ~IEEE80211_F_PUREG;
//		/* NB: reset only if we're operating on an 11g channel */
//		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
//		    IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
//			retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_WDS:
//		if (value)
//			vap->iv_flags_ext |= IEEE80211_FEXT_WDS;
//		else
//			vap->iv_flags_ext &= ~IEEE80211_FEXT_WDS;
//		break;
//	case IEEE80211_PARAM_BGSCAN:
//		if (value) {
//			if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0)
//				return -EINVAL;
//			vap->iv_flags |= IEEE80211_F_BGSCAN;
//		} else {
//			/* XXX racey? */
//			vap->iv_flags &= ~IEEE80211_F_BGSCAN;
//			ieee80211_cancel_scan(vap);	/* anything current */
//		}
//		break;
//	case IEEE80211_PARAM_BGSCAN_IDLE:
//		if (value >= IEEE80211_BGSCAN_IDLE_MIN)
//			vap->iv_bgscanidle = value*HZ/1000;
//		else
//			retv = EINVAL;
//		break;
//	case IEEE80211_PARAM_BGSCAN_INTERVAL:
//		if (value >= IEEE80211_BGSCAN_INTVAL_MIN)
//			vap->iv_bgscanintvl = value*HZ;
//		else
//			retv = EINVAL;
//		break;
//	case IEEE80211_PARAM_MCAST_RATE:
//		/* units are in KILObits per second */
//		if (value >= 256 && value <= 54000)
//			vap->iv_mcast_rate = value;
//		else
//			retv = EINVAL;
//		break;
//	case IEEE80211_PARAM_COVERAGE_CLASS:
//		if (value >= 0 && value <= IEEE80211_COVERAGE_CLASS_MAX) {
//			ic->ic_coverageclass = value;
//			if (IS_UP_AUTO(vap))
//				ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
//			retv = 0;
//		}
//		else
//			retv = EINVAL;
//		break;
//	case IEEE80211_PARAM_COUNTRY_IE:
//		if (value)
//			ic->ic_flags_ext |= IEEE80211_FEXT_COUNTRYIE;
//		else
//			ic->ic_flags_ext &= ~IEEE80211_FEXT_COUNTRYIE;
//		retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_REGCLASS:
//		if (value)
//			ic->ic_flags_ext |= IEEE80211_FEXT_REGCLASS;
//		else
//			ic->ic_flags_ext &= ~IEEE80211_FEXT_REGCLASS;
//		retv = ENETRESET;
//		break;
//	case IEEE80211_PARAM_SCANVALID:
//		vap->iv_scanvalid = value*HZ;
//		break;
//	case IEEE80211_PARAM_ROAM_RSSI_11A:
//		vap->iv_roam.rssi11a = value;
//		break;
//	case IEEE80211_PARAM_ROAM_RSSI_11B:
//		vap->iv_roam.rssi11bOnly = value;
//		break;
//	case IEEE80211_PARAM_ROAM_RSSI_11G:
//		vap->iv_roam.rssi11b = value;
//		break;
//	case IEEE80211_PARAM_ROAM_RATE_11A:
//		vap->iv_roam.rate11a = value;
//		break;
//	case IEEE80211_PARAM_ROAM_RATE_11B:
//		vap->iv_roam.rate11bOnly = value;
//		break;
//	case IEEE80211_PARAM_ROAM_RATE_11G:
//		vap->iv_roam.rate11b = value;
//		break;
//	case IEEE80211_PARAM_UAPSDINFO:
//		if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
//			if (ic->ic_caps & IEEE80211_C_UAPSD) {
//				if (value)
//					IEEE80211_VAP_UAPSD_ENABLE(vap);
//				else
//					IEEE80211_VAP_UAPSD_DISABLE(vap);
//				retv = ENETRESET;
//			}
//		}
//		else if (vap->iv_opmode == IEEE80211_M_STA) {
//			vap->iv_uapsdinfo = value;
//			IEEE80211_VAP_UAPSD_ENABLE(vap);
//			retv = ENETRESET;
//		}
//		break;
//	case IEEE80211_PARAM_SLEEP:
//		/* XXX: Forced sleep for testing. Does not actually place the
//		 *      HW in sleep mode yet. this only makes sense for STAs.
//		 */
//		if (value) {
//			/* goto sleep */
//			IEEE80211_VAP_GOTOSLEEP(vap);
//		}
//		else {
//			/* wakeup */
//			IEEE80211_VAP_WAKEUP(vap);
//		}
//		ieee80211_send_nulldata(ieee80211_ref_node(vap->iv_bss));
//		break;
//	case IEEE80211_PARAM_QOSNULL:
//		/* Force a QoS Null for testing. */
//		ieee80211_send_qosnulldata(vap->iv_bss, value);
//		break;
//	case IEEE80211_PARAM_PSPOLL:
//		/* Force a PS-POLL for testing. */
//		ieee80211_send_pspoll(vap->iv_bss);
//		break;
//	case IEEE80211_PARAM_EOSPDROP:
//		if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
//			if (value) IEEE80211_VAP_EOSPDROP_ENABLE(vap);
//			else IEEE80211_VAP_EOSPDROP_DISABLE(vap);
//		}
//		break;
//	case IEEE80211_PARAM_MARKDFS:
//		if (value)
//			ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS;
//		else
//			ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS;
//		break;
//	case IEEE80211_PARAM_CHANBW:
//		switch (value) {
//			case 0:
//				ic->ic_chanbwflag = 0;
//				break;
//			case 1:
//				ic->ic_chanbwflag = IEEE80211_CHAN_HALF;
//				break;
//			case 2:
//				ic->ic_chanbwflag = IEEE80211_CHAN_QUARTER;
//				break;
//			default:
//				retv = EINVAL;
//				break;
//		}
//		break;
//	case IEEE80211_PARAM_SHORTPREAMBLE:
//		if (value) {
//			ic->ic_caps |= IEEE80211_C_SHPREAMBLE;
//		} else {
//			ic->ic_caps &= ~IEEE80211_C_SHPREAMBLE;
//		}
//		retv = ENETRESET;
//		break;
//	default:
//		retv = EOPNOTSUPP;
//		break;
//	}
//	/* XXX should any of these cause a rescan? */
//	if (retv == ENETRESET)
//		retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;
//	return -retv;
//}

int usbdrvwext_setmode(struct net_device *dev, struct iw_request_info *info,
		   	 void *w, char *extra)
{
	return 0;
}

int usbdrvwext_getmode(struct net_device *dev, struct iw_request_info *info,
			void *w, char *extra)
{
	//struct usbdrv_private *macp = dev->ml_priv;
	struct iw_point *wri = (struct iw_point *)extra;
	char mode[8];

    strcpy(mode,"11g");
	return (copy_to_user(wri->pointer, mode, 6) ? -EFAULT : 0);
}

int zfLnxPrivateIoctl(struct net_device *dev, struct zdap_ioctl* zdreq)
{
	//void* regp = macp->regp;
	u16_t cmd;
	//u32_t temp;
	u32_t* p;
	u32_t i;

	cmd = zdreq->cmd;
	switch(cmd)
	{
	case ZM_IOCTL_REG_READ:
		zfiDbgReadReg(dev, zdreq->addr);
		break;

	case ZM_IOCTL_REG_WRITE:
		zfiDbgWriteReg(dev, zdreq->addr, zdreq->value);
		break;

	case ZM_IOCTL_MEM_READ:
		p = (u32_t *) bus_to_virt(zdreq->addr);
		printk(KERN_DEBUG "usbdrv: read memory addr: 0x%08x value: 0x%08x\n", zdreq->addr, *p);
		break;

	case ZM_IOCTL_MEM_WRITE:
		p = (u32_t *) bus_to_virt(zdreq->addr);
		*p = zdreq->value;
		printk(KERN_DEBUG "usbdrv: write value: 0x%08x to memory addr: 0x%08x\n", zdreq->value, zdreq->addr);
		break;

	case ZM_IOCTL_TALLY :
		zfiWlanShowTally(dev);
		if (zdreq->addr)
			zfiWlanResetTally(dev);
		break;

	case ZM_IOCTL_TEST :
            printk(KERN_DEBUG "ZM_IOCTL_TEST:len=%d\n", zdreq->addr);
            //zfiWlanReadReg(dev, 0x10f400);
            //zfiWlanReadReg(dev, 0x10f404);
            printk("IOCTL TEST\n");
            #if 1
            //print packet
            for (i=0; i<zdreq->addr; i++)
            {
                if ((i&0x7) == 0)
                {
                    printk("\n");
                }
                printk("%02X ", (unsigned char)zdreq->data[i]);
            }
            printk("\n");
            #endif


            #if 0 //For Test?? 1 to 0 by CWYang(-)
            {
            struct sk_buff* s;

            /* Allocate a skb */
            s = alloc_skb(2000, GFP_ATOMIC);

            /* Copy data to skb */
            for (i=0; i<zdreq->addr; i++)
            {
                s->data[i] = zdreq->data[i];
            }
            s->len = zdreq->addr;

            /* Call zfIdlRecv() */
            zfiRecv80211(dev, s, NULL);
            }
            #endif

            break;


/****************************** ZDCONFIG ******************************/
        case ZM_IOCTL_FRAG :
            zfiWlanSetFragThreshold(dev, zdreq->addr);
            break;

        case ZM_IOCTL_RTS :
            zfiWlanSetRtsThreshold(dev, zdreq->addr);
            break;

        case ZM_IOCTL_SCAN :
            zfiWlanScan(dev);
            break;

        case ZM_IOCTL_KEY :
            {
                u8_t key[29];
                struct zsKeyInfo keyInfo;
                u32_t i;

                for (i=0; i<29; i++)
                {
                    key[i] = 0;
                }

                for (i=0; i<zdreq->addr; i++)
                {
                    key[i] = zdreq->data[i];
                }

                printk("key len=%d, key=%02x%02x%02x%02x%02x...\n",
                        zdreq->addr, key[0], key[1], key[2], key[3], key[4]);

                keyInfo.keyLength = zdreq->addr;
                keyInfo.keyIndex = 0;
                keyInfo.flag = 0;
                keyInfo.key = key;
                zfiWlanSetKey(dev, keyInfo);
            }
            break;

        case ZM_IOCTL_RATE :
            zfiWlanSetTxRate(dev, zdreq->addr);
            break;

        case ZM_IOCTL_ENCRYPTION_MODE :
            zfiWlanSetEncryMode(dev, zdreq->addr);

            zfiWlanDisable(dev, 0);
            zfiWlanEnable(dev);
            break;
        //CWYang(+)
        case ZM_IOCTL_SIGNAL_STRENGTH :
            {
                u8_t buffer[2];
                zfiWlanQuerySignalInfo(dev, &buffer[0]);
                printk("Current Signal Strength : %02d\n", buffer[0]);
            }
            break;
        //CWYang(+)
        case ZM_IOCTL_SIGNAL_QUALITY :
            {
                u8_t buffer[2];
                zfiWlanQuerySignalInfo(dev, &buffer[0]);
                printk("Current Signal Quality : %02d\n", buffer[1]);
            }
            break;

	case ZM_IOCTL_SET_PIBSS_MODE:
		if (zdreq->addr == 1)
			zfiWlanSetWlanMode(dev, ZM_MODE_PSEUDO);
		else
			zfiWlanSetWlanMode(dev, ZM_MODE_INFRASTRUCTURE);

		zfiWlanDisable(dev, 0);
		zfiWlanEnable(dev);

		break;
/****************************** ZDCONFIG ******************************/

	default :
		printk(KERN_ERR "usbdrv: error command = %x\n", cmd);
		break;
	}

	return 0;
}

int usbdrv_wpa_ioctl(struct net_device *dev, struct athr_wlan_param *zdparm)
{
    int ret = 0;
    u8_t bc_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
    u8_t mac_addr[80];
    struct zsKeyInfo keyInfo;
    struct usbdrv_private *macp = dev->ml_priv;
    u16_t vapId = 0;

    //zmw_get_wlan_dev(dev);

    switch(zdparm->cmd)
    {
        case ZD_CMD_SET_ENCRYPT_KEY:

            /* Set up key information */
            keyInfo.keyLength = zdparm->u.crypt.key_len;
            keyInfo.keyIndex = zdparm->u.crypt.idx;
            if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode
                keyInfo.flag = ZM_KEY_FLAG_AUTHENTICATOR;
            else
                keyInfo.flag = 0;
            keyInfo.key = zdparm->u.crypt.key;
            keyInfo.initIv = zdparm->u.crypt.seq;
            keyInfo.macAddr = (u16_t *)zdparm->sta_addr;

            /* Identify the MAC address information */
            if (memcmp(zdparm->sta_addr, bc_addr, sizeof(bc_addr)) == 0)
            {
                keyInfo.flag |= ZM_KEY_FLAG_GK;
            }
            else
            {
                keyInfo.flag |= ZM_KEY_FLAG_PK;
            }

            if (!strcmp(zdparm->u.crypt.alg, "NONE"))
            {
                //u8_t zero_mac[]={0,0,0,0,0,0};

                /* Set key length to zero */
                keyInfo.keyLength = 0;

                if (zdparm->sta_addr[0] & 1)//del group key
                {
                    //if (macp->cardSetting.WPAIeLen==0)
                    //{//802.1x dynamic WEP
                    //    mDynKeyMode = 0;
                    //    mKeyFormat[0] = 0;
                    //    mPrivacyInvoked[0]=FALSE;
                    //    mCap[0] &= ~CAP_PRIVACY;
                    //    macp->cardSetting.EncryOnOff[0]=0;
                    //}
                    //mWpaBcKeyLen = mGkInstalled = 0;
                }
                else
                {
                    //if (memcmp(zero_mac,zdparm->sta_addr, 6)==0)
                    //{
                    //    mDynKeyMode=0;
                    //    mKeyFormat[0]=0;
                    //    pSetting->DynKeyMode=0;
                    //    pSetting->EncryMode[0]=0;
                    //    mDynKeyMode=0;
                    //}
                }

                printk(KERN_ERR "Set Encryption Type NONE\n");
                return ret;
            }
            else if (!strcmp(zdparm->u.crypt.alg, "TKIP"))
            {
                zfiWlanSetEncryMode(dev, ZM_TKIP);
                //Linux Supplicant will inverse Tx/Rx key
                //So we inverse it back //CWYang(+)
                //zfMemoryCopy(&temp[0], &keyInfo.key[16], 8);
                //zfMemoryCopy(&keyInfo.key[16], keyInfo.key[24], 8);
                //zfMemoryCopy(&keyInfo.key[24], &temp[0], 8);
                //u8_t temp;
                //int k;
                //for (k = 0; k < 8; k++)
                //{
                //    temp = keyInfo.key[16 + k];
                //    keyInfo.key[16 + k] = keyInfo.key[24 + k];
                //    keyInfo.key[24 + k] = temp;
                //}
                //CamEncryType = ZM_TKIP;
                ////if (idx == 0)
                //{// Pairwise key
                //    mKeyFormat[0] = CamEncryType;
                //    mDynKeyMode = pSetting->DynKeyMode = DYN_KEY_TKIP;
                //}
            }
            else if (!strcmp(zdparm->u.crypt.alg, "CCMP"))
            {
                zfiWlanSetEncryMode(dev, ZM_AES);
                //CamEncryType = ZM_AES;
                ////if (idx == 0)
                //{// Pairwise key
                //    mKeyFormat[0] = CamEncryType;
                //    mDynKeyMode = pSetting->DynKeyMode = DYN_KEY_AES;
                //}
            }
            else if (!strcmp(zdparm->u.crypt.alg, "WEP"))
            {
                if (keyInfo.keyLength == 5)
                { // WEP 64
                    zfiWlanSetEncryMode(dev, ZM_WEP64);
                //    CamEncryType = ZM_WEP64;
                //    tmpDynKeyMode=DYN_KEY_WEP64;
                }
                else if (keyInfo.keyLength == 13)
                {//keylen=13, WEP 128
                    zfiWlanSetEncryMode(dev, ZM_WEP128);
                //    CamEncryType = ZM_WEP128;
                //    tmpDynKeyMode=DYN_KEY_WEP128;
                }
                else
                {
                    zfiWlanSetEncryMode(dev, ZM_WEP256);
                }

                // For Dynamic WEP key (Non-WPA Radius), the key ID range: 0-3
                // In WPA/RSN mode, the key ID range: 1-3, usually, a broadcast key.
                // For WEP key setting: we set mDynKeyMode and mKeyFormat in following case:
                //   1. For 802.1x dynamically generated WEP key method.
                //   2. For WPA/RSN mode, but key id == 0. (But this is an impossible case)
                // So, only check case 1.
                //if (macp->cardSetting.WPAIeLen==0)
                //{
                //    mKeyFormat[0] = CamEncryType;
                //    mDynKeyMode = pSetting->DynKeyMode = tmpDynKeyMode;
                //    mPrivacyInvoked[0]=TRUE;
                //    mCap[0] |= CAP_PRIVACY;
                //    macp->cardSetting.EncryOnOff[0]=1;
                //}
            }

            /* DUMP key context */
//#ifdef WPA_DEBUG
            if (keyInfo.keyLength > 0)
            {
                int ii;
                printk("Otus: Key Context:\n");
                for(ii = 0; ii < keyInfo.keyLength;)
                {
                    printk("0x%02x ", keyInfo.key[ii]);
                    if((++ii % 16) == 0)
                        printk("\n");
                }
                printk("\n");
            }
//#endif

            /* Set encrypt mode */
            //zfiWlanSetEncryMode(dev, CamEncryType);
            vapId = zfLnxGetVapId(dev);
            if (vapId == 0xffff)
                keyInfo.vapId = 0;
            else
                keyInfo.vapId = vapId + 1;
            keyInfo.vapAddr[0] = keyInfo.macAddr[0];
            keyInfo.vapAddr[1] = keyInfo.macAddr[1];
            keyInfo.vapAddr[2] = keyInfo.macAddr[2];

            zfiWlanSetKey(dev, keyInfo);

            //zfiWlanDisable(dev);
            //zfiWlanEnable(dev);
            break;

        case ZD_CMD_SET_MLME:
            printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SET_MLME\n");

            /* Translate STA's address */
            sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", zdparm->sta_addr[0], zdparm->sta_addr[1],
                zdparm->sta_addr[2], zdparm->sta_addr[3], zdparm->sta_addr[4], zdparm->sta_addr[5]);

            switch(zdparm->u.mlme.cmd)
            {
                case MLME_STA_DEAUTH:
                    printk(" -------Call zfiWlanDeauth, reason:%d\n",zdparm->u.mlme.reason_code);
                    if(zfiWlanDeauth(dev, (u16_t*) zdparm->sta_addr, zdparm->u.mlme.reason_code) != 0)
                        printk(KERN_ERR "Can't deauthencate STA: %s\n", mac_addr);
                    else
                        printk(KERN_ERR "Deauthenticate STA: %s with reason code: %d\n", mac_addr, zdparm->u.mlme.reason_code);
                    break;

                case MLME_STA_DISASSOC:
                    printk(" -------Call zfiWlanDeauth, reason:%d\n",zdparm->u.mlme.reason_code);
                    if(zfiWlanDeauth(dev, (u16_t*) zdparm->sta_addr, zdparm->u.mlme.reason_code) != 0)
                        printk(KERN_ERR "Can't disassociate STA: %s\n", mac_addr);
                    else
                        printk(KERN_ERR "Disassociate STA: %s with reason code: %d\n", mac_addr, zdparm->u.mlme.reason_code);
                    break;

                default:
                    printk(KERN_ERR "MLME command: 0x%04x not support\n", zdparm->u.mlme.cmd);
                    break;
            }

            break;

        case ZD_CMD_SCAN_REQ:
            printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SCAN_REQ\n");
            break;

        case ZD_CMD_SET_GENERIC_ELEMENT:
            printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SET_GENERIC_ELEMENT\n");

            /* Copy the WPA IE */
            //zm_msg1_mm(ZM_LV_0, "CWY - wpaie Length : ", zdparm->u.generic_elem.len);
            printk(KERN_ERR "wpaie Length : %d\n", zdparm->u.generic_elem.len);
            if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode
            {
                zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len);
            }
            else
            {
                macp->supLen = zdparm->u.generic_elem.len;
                memcpy(macp->supIe, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len);
            }
            zfiWlanSetWpaSupport(dev, 1);
            //zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len);
            {
                int ii;
                u8_t len = zdparm->u.generic_elem.len;
                u8_t *wpaie = (u8_t *)zdparm->u.generic_elem.data;

                printk(KERN_ERR "wd->ap.wpaLen: %d\n", len);

                /* DUMP WPA IE */
                for(ii = 0; ii < len;)
                {
                    printk(KERN_ERR "0x%02x ", wpaie[ii]);

                    if((++ii % 16) == 0)
                        printk(KERN_ERR "\n");
                }
                printk(KERN_ERR "\n");
            }

//            #ifdef ZM_HOSTAPD_SUPPORT
            //if (wd->wlanMode == ZM_MODE_AP)
            //{// Update Beacon FIFO in the next TBTT.
            //    memcpy(&mWPAIe, pSetting->WPAIe, pSetting->WPAIeLen);
            //    printk(KERN_ERR "Copy WPA IE into mWPAIe\n");
            //}
//            #endif
            break;

//        #ifdef ZM_HOSTAPD_SUPPORT
        case ZD_CMD_GET_TSC:
            printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_GET_TSC\n");
            break;
//        #endif

        default:
            printk(KERN_ERR "usbdrv_wpa_ioctl default: 0x%04x\n", zdparm->cmd);
            ret = -EINVAL;
            break;
    }

    return ret;
}

#ifdef ZM_ENABLE_CENC
int usbdrv_cenc_ioctl(struct net_device *dev, struct zydas_cenc_param *zdparm)
{
    //struct usbdrv_private *macp = dev->ml_priv;
    struct zsKeyInfo keyInfo;
    u16_t apId;
    u8_t bc_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
    int ret = 0;
    int ii;

    /* Get the AP Id */
    apId = zfLnxGetVapId(dev);

    if (apId == 0xffff)
    {
        apId = 0;
    }
    else
    {
        apId = apId+1;
    }

    switch (zdparm->cmd)
    {
        case ZM_CMD_CENC_SETCENC:
            printk(KERN_ERR "ZM_CMD_CENC_SETCENC\n");
            printk(KERN_ERR "length: %d\n", zdparm->len);
            printk(KERN_ERR "policy: %d\n", zdparm->u.info.cenc_policy);
            break;
        case ZM_CMD_CENC_SETKEY:
            //ret = wai_ioctl_setkey(vap, ioctl_msg);
            printk(KERN_ERR "ZM_CMD_CENC_SETKEY\n");

            printk(KERN_ERR "MAC address= ");
            for(ii = 0; ii < 6; ii++)
            {
                printk(KERN_ERR "0x%02x ", zdparm->u.crypt.sta_addr[ii]);
            }
            printk(KERN_ERR "\n");

            printk(KERN_ERR "Key Index: %d\n", zdparm->u.crypt.keyid);
            printk(KERN_ERR "Encryption key= ");
            for(ii = 0; ii < 16; ii++)
            {
                printk(KERN_ERR "0x%02x ", zdparm->u.crypt.key[ii]);
            }
            printk(KERN_ERR "\n");

            printk(KERN_ERR "MIC key= ");
            for(ii = 16; ii < ZM_CENC_KEY_SIZE; ii++)
            {
                printk(KERN_ERR "0x%02x ", zdparm->u.crypt.key[ii]);
            }
            printk(KERN_ERR "\n");

            /* Set up key information */
            keyInfo.keyLength = ZM_CENC_KEY_SIZE;
            keyInfo.keyIndex = zdparm->u.crypt.keyid;
            keyInfo.flag = ZM_KEY_FLAG_AUTHENTICATOR | ZM_KEY_FLAG_CENC;
            keyInfo.key = zdparm->u.crypt.key;
            keyInfo.macAddr = (u16_t *)zdparm->u.crypt.sta_addr;

            /* Identify the MAC address information */
            if (memcmp(zdparm->u.crypt.sta_addr, bc_addr, sizeof(bc_addr)) == 0)
            {
                keyInfo.flag |= ZM_KEY_FLAG_GK;
                keyInfo.vapId = apId;
                memcpy(keyInfo.vapAddr, dev->dev_addr, ETH_ALEN);
            }
            else
            {
                keyInfo.flag |= ZM_KEY_FLAG_PK;
            }

            zfiWlanSetKey(dev, keyInfo);

            break;
        case ZM_CMD_CENC_REKEY:
            //ret = wai_ioctl_rekey(vap, ioctl_msg);
            printk(KERN_ERR "ZM_CMD_CENC_REKEY\n");
            break;
        default:
            ret = -EOPNOTSUPP;
            break;

    }

    //if (retv == ENETRESET)
    //    retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;

    return ret;
}
#endif //ZM_ENABLE_CENC
/////////////////////////////////////////
int usbdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
//    struct usbdrv_private *macp;
//    void *regp;
    struct zdap_ioctl zdreq;
    struct iwreq *wrq = (struct iwreq *)ifr;
    struct athr_wlan_param zdparm;
    struct usbdrv_private *macp = dev->ml_priv;

    int err = 0;
    int changed = 0;

//    regp = macp->regp;

    if(!netif_running(dev))
        return -EINVAL;

    switch (cmd)
    {
            case SIOCGIWNAME:
            strcpy(wrq->u.name, "IEEE 802.11-DS");
            break;

        case SIOCGIWAP:
            err = usbdrvwext_giwap(dev, NULL, &wrq->u.ap_addr, NULL);
            break;


        case SIOCSIWAP:
            err = usbdrvwext_siwap(dev, NULL, &wrq->u.ap_addr, NULL);
            break;


        case SIOCGIWMODE:
            err = usbdrvwext_giwmode(dev, NULL, &wrq->u.mode, NULL);
            break;


        case SIOCSIWESSID:
            printk(KERN_ERR "CWY - usbdrvwext_siwessid\n");
            //err = usbdrv_ioctl_setessid(dev, &wrq->u.essid);
            err = usbdrvwext_siwessid(dev, NULL, &wrq->u.essid, NULL);

            if (! err)
                changed = 1;
            break;


        case SIOCGIWESSID:
            err = usbdrvwext_giwessid(dev, NULL, &wrq->u.essid, NULL);
            break;


        case SIOCSIWRTS:

            err = usbdrv_ioctl_setrts(dev, &wrq->u.rts);
            if (! err)
                changed = 1;
            break;


		case SIOCIWFIRSTPRIV + 0x2: /* set_auth */
		{
			//printk("CWY - SIOCIWFIRSTPRIV + 0x2 (set_auth)\n");
			if (! capable(CAP_NET_ADMIN))
			{
				err = -EPERM;
				break;
			}
			{
				int val = *( (int *) wrq->u.name );
				if ((val < 0) || (val > 2))
				{
					err = -EINVAL;
					break;
				}
				else
				{
					zfiWlanSetAuthenticationMode(dev, val);

                    if (macp->DeviceOpened == 1)
                    {
                        zfiWlanDisable(dev, 0);
                        zfiWlanEnable(dev);
                    }

					err = 0;
					changed = 1;
				}
			}
		}
			break;

		case SIOCIWFIRSTPRIV + 0x3: /* get_auth */
		{
		    int AuthMode = ZM_AUTH_MODE_OPEN;

			//printk("CWY - SIOCIWFIRSTPRIV + 0x3 (get_auth)\n");

			if (wrq->u.data.pointer)
			{
				wrq->u.data.flags = 1;

				AuthMode = zfiWlanQueryAuthenticationMode(dev, 0);
				if (AuthMode == ZM_AUTH_MODE_OPEN)
				{
					wrq->u.data.length = 12;

					if (copy_to_user(wrq->u.data.pointer, "open system", 12))
					{
						return -EFAULT;
					}
				}
				else if (AuthMode == ZM_AUTH_MODE_SHARED_KEY)
				{
					wrq->u.data.length = 11;

					if (copy_to_user(wrq->u.data.pointer, "shared key", 11))
					{
						return -EFAULT;
					}
				}
				else if (AuthMode == ZM_AUTH_MODE_AUTO)
				{
					wrq->u.data.length = 10;

					if (copy_to_user(wrq->u.data.pointer, "auto mode", 10))
					{
						return -EFAULT;
					}
				}
				else
				{
					return -EFAULT;
				}
			}
		}
			break;


        case ZDAPIOCTL:    //debug command
            if (copy_from_user(&zdreq, ifr->ifr_data, sizeof (zdreq)))
            {
                printk(KERN_ERR "usbdrv: copy_from_user error\n");
                return -EFAULT;
            }

            //printk(KERN_DEBUG "usbdrv: cmd=%2x, reg=0x%04lx, value=0x%08lx\n",
            //        zdreq.cmd, zdreq.addr, zdreq.value);

			zfLnxPrivateIoctl(dev, &zdreq);

            err = 0;
            break;

        case ZD_IOCTL_WPA:
            if (copy_from_user(&zdparm, ifr->ifr_data, sizeof(struct athr_wlan_param)))
            {
                printk(KERN_ERR "usbdrv: copy_from_user error\n");
                return -EFAULT;
            }

            usbdrv_wpa_ioctl(dev, &zdparm);
            err = 0;
            break;

        case ZD_IOCTL_PARAM:
        {
            int *p;
            int op;
            int arg;

            /* Point to the name field and retrieve the
             * op and arg elements.          */
            p = (int *)wrq->u.name;
            op = *p++;
            arg = *p;

            if(op == ZD_PARAM_ROAMING)
            {
                printk(KERN_ERR "************* ZD_PARAM_ROAMING: %d\n", arg);
                //macp->cardSetting.ap_scan=(U8)arg;
            }
            if(op == ZD_PARAM_PRIVACY)
            {
                printk(KERN_ERR "ZD_IOCTL_PRIVACY: ");

                /* Turn on the privacy invoke flag */
                if(arg)
                {
                //    mCap[0] |= CAP_PRIVACY;
                //    macp->cardSetting.EncryOnOff[0] = 1;
                    printk(KERN_ERR "enable\n");

                }
                else
                {
                //    mCap[0] &= ~CAP_PRIVACY;
                //    macp->cardSetting.EncryOnOff[0] = 0;
                    printk(KERN_ERR "disable\n");
                }
                                //changed=1;
            }
            if(op == ZD_PARAM_WPA)
            {
                printk(KERN_ERR "ZD_PARAM_WPA: ");

                if(arg)
                {
                    printk(KERN_ERR "enable\n");

                    if (zfiWlanQueryWlanMode(dev) != ZM_MODE_AP)
                    {
                        printk(KERN_ERR "Station Mode\n");
                        //zfiWlanQueryWpaIe(dev, (u8_t *)&wpaIe, &wpalen);
                        //printk("wpaIe : %2x,%2x,%2x\n", wpaIe[21], wpaIe[22], wpaIe[23]);
                        //printk("rsnIe : %2x,%2x,%2x\n", wpaIe[17], wpaIe[18], wpaIe[19]);
                        if ((macp->supIe[21] == 0x50) &&
                            (macp->supIe[22] == 0xf2) &&
                            (macp->supIe[23] == 0x2))
                        {
                            printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPAPSK\n");
                            //wd->sta.authMode = ZM_AUTH_MODE_WPAPSK;
                            //wd->ws.authMode = ZM_AUTH_MODE_WPAPSK;
                            zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPAPSK);
                        }
                        else if ((macp->supIe[21] == 0x50) &&
                                 (macp->supIe[22] == 0xf2) &&
                                 (macp->supIe[23] == 0x1))
                        {
                            printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA\n");
                            //wd->sta.authMode = ZM_AUTH_MODE_WPA;
                            //wd->ws.authMode = ZM_AUTH_MODE_WPA;
                            zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA);
                        }
                        else if ((macp->supIe[17] == 0xf) &&
                                 (macp->supIe[18] == 0xac) &&
                                 (macp->supIe[19] == 0x2))
                        {
                            printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA2PSK\n");
                            //wd->sta.authMode = ZM_AUTH_MODE_WPA2PSK;
                            //wd->ws.authMode = ZM_AUTH_MODE_WPA2PSK;
                            zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA2PSK);
                        }
                        else if ((macp->supIe[17] == 0xf) &&
                                 (macp->supIe[18] == 0xac) &&
                                 (macp->supIe[19] == 0x1))
                        {
                            printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA2\n");
                            //wd->sta.authMode = ZM_AUTH_MODE_WPA2;
                            //wd->ws.authMode = ZM_AUTH_MODE_WPA2;
                            zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA2);
                        }
                        if ((macp->supIe[21] == 0x50) || (macp->supIe[22] == 0xf2))//WPA or WPAPSK
                        {
                            if (macp->supIe[11] == 0x2)
                            {
                                printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_TKIP\n");
                                //wd->sta.wepStatus = ZM_ENCRYPTION_TKIP;
                                //wd->ws.wepStatus = ZM_ENCRYPTION_TKIP;
                                zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_TKIP);
                            }
                            else
                            {
                                printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_AES\n");
                                //wd->sta.wepStatus = ZM_ENCRYPTION_AES;
                                //wd->ws.wepStatus = ZM_ENCRYPTION_AES;
                                zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_AES);
                            }
                        }
                        if ((macp->supIe[17] == 0xf) || (macp->supIe[18] == 0xac)) //WPA2 or WPA2PSK
                        {
                            if (macp->supIe[13] == 0x2)
                            {
                                printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_TKIP\n");
                                //wd->sta.wepStatus = ZM_ENCRYPTION_TKIP;
                                //wd->ws.wepStatus = ZM_ENCRYPTION_TKIP;
                                zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_TKIP);
                            }
                            else
                            {
                                printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_AES\n");
                                //wd->sta.wepStatus = ZM_ENCRYPTION_AES;
                                //wd->ws.wepStatus = ZM_ENCRYPTION_AES;
                                zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_AES);
                            }
                        }
                    }
                    zfiWlanSetWpaSupport(dev, 1);
                }
                else
                {
                    /* Reset the WPA related variables */
                    printk(KERN_ERR "disable\n");

                    zfiWlanSetWpaSupport(dev, 0);
                    zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_OPEN);
                    zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_WEP_DISABLED);

                    /* Now we only set the length in the WPA IE
                     * field to zero.                         */
                    //macp->cardSetting.WPAIe[1] = 0;
                }
            }
            if(op == ZD_PARAM_COUNTERMEASURES)
            {
                printk(KERN_ERR "================ZD_PARAM_COUNTERMEASURES: ");

                if(arg)
                {
                //    mCounterMeasureState=1;
                    printk(KERN_ERR "enable\n");
                }
                else
                {
                //    mCounterMeasureState=0;
                    printk(KERN_ERR "disable\n");
                }
            }
            if(op == ZD_PARAM_DROPUNENCRYPTED)
            {
                printk(KERN_ERR "ZD_PARAM_DROPUNENCRYPTED: ");

                if(arg)
                {
                    printk(KERN_ERR "enable\n");
                }
                else
                {
                    printk(KERN_ERR "disable\n");
                }
            }
            if(op == ZD_PARAM_AUTH_ALGS)
            {
                printk(KERN_ERR "ZD_PARAM_AUTH_ALGS: ");

                if(arg == 0)
                {
                    printk(KERN_ERR "OPEN_SYSTEM\n");
                }
                else
                {
                    printk(KERN_ERR "SHARED_KEY\n");
                }
            }
            if(op == ZD_PARAM_WPS_FILTER)
            {
                printk(KERN_ERR "ZD_PARAM_WPS_FILTER: ");

                if(arg)
                {
                //    mCounterMeasureState=1;
                    macp->forwardMgmt = 1;
                    printk(KERN_ERR "enable\n");
                }
                else
                {
                //    mCounterMeasureState=0;
                    macp->forwardMgmt = 0;
                    printk(KERN_ERR "disable\n");
                }
            }
        }
            err = 0;
            break;

        case ZD_IOCTL_GETWPAIE:
        {
            struct ieee80211req_wpaie req_wpaie;
            u16_t apId, i, j;

            /* Get the AP Id */
            apId = zfLnxGetVapId(dev);

            if (apId == 0xffff)
            {
                apId = 0;
            }
            else
            {
                apId = apId+1;
            }

            if (copy_from_user(&req_wpaie, ifr->ifr_data, sizeof(struct ieee80211req_wpaie))){
                printk(KERN_ERR "usbdrv: copy_from_user error\n");
                return -EFAULT;
            }

            for(i = 0; i < ZM_OAL_MAX_STA_SUPPORT; i++)
            {
                for(j = 0; j < IEEE80211_ADDR_LEN; j++)
                {
                    if (macp->stawpaie[i].wpa_macaddr[j] != req_wpaie.wpa_macaddr[j])
                        break;
                }
                if (j == 6)
                    break;
            }
            if (i < ZM_OAL_MAX_STA_SUPPORT)
            {
                //printk("ZD_IOCTL_GETWPAIE - sta index = %d\n", i);
                memcpy(req_wpaie.wpa_ie, macp->stawpaie[i].wpa_ie, IEEE80211_MAX_IE_SIZE);
            }

            if (copy_to_user(wrq->u.data.pointer, &req_wpaie, sizeof(struct ieee80211req_wpaie)))
            {
                    return -EFAULT;
            }
        }

            err = 0;
            break;
#ifdef ZM_ENABLE_CENC
        case ZM_IOCTL_CENC:
            if (copy_from_user(&macp->zd_wpa_req, ifr->ifr_data, sizeof(struct athr_wlan_param)))
            {
                printk(KERN_ERR "usbdrv: copy_from_user error\n");
                return -EFAULT;
            }

            usbdrv_cenc_ioctl(dev, (struct zydas_cenc_param *)&macp->zd_wpa_req);
            err = 0;
            break;
#endif //ZM_ENABLE_CENC
        default:
            err = -EOPNOTSUPP;
            break;
    }


    return err;
}