aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/staging/otus/ioctl.c
blob: 6808e69fb354970376bf93a9b837dac8a85cbb0b (plain) (tree)
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
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


























                                                                           
                          







                                                                
                            









                                                  
                            











                                                  
                           
 
                                        


                                            






































                                                                



                                













                                                                             



                              

























                                                                             



                                                                       



                                                         
 

                                
 
                                              
 
                                                   
 



                                                                      
 


                                                                        
 

                               
 
                                      
 

                                                      
 
                              
 



                                                                        
 


                                                      
 

                                                                      
 

                                      
 

                               
 


                 



                                                                       



                                                         

 


                                                                      
 
                          
 
                                   
 

                                                   
 
                              
 

                                           
 



                                                                      
 
                 

 

                                                                     
                 

 



                                                      

                                                              
 











                                                  
 
 





                                                                   
                                              
 




                                                     
                               











































                                                                               
 
































                                                                       

                                                                         







































































                                                                             




























































                                                                               



                                                           


                                              

                                                   
 
                                                         
 
                                              
 
                 


                                              

                                                  
 






















































                                                                               


                                              

                                                  
 
                                                   
 

                                    
 

                                             
 
                 


                                              

                                                   
 




























                                                   


                                              

                                     
 




























                                                        



















                                                           

                                                   
 








                                                           

                                                           
 






                                                  
















                                                                   
 

                                           
 

                                                 
 











                                                                            
 







































                                                                             
 
                 


                                                                          
                                                      
 






















                                                                         


                                            

                                                      
 




















                                                                             





                                                           

                                                 



                                                                            
                                           
 
                                                   
 

                                    
 
                                                          
 
                         
 
                 


                                              

                                                   
 









































                                                                             




                                                          
         
 


                                            
 
                        
 
                 


                                               

                                                    
 































                                                                             


                                               

                                                    
 



                                                   
 

                                
 

                                    
 
                                                       
 

                                                     
 


                                                                              
 
                                  
 

                                         
 








                                                                        
 
                 





                                                              
                                       






                                                              


                                                   
 

                                    
 

                                                       
 

                                        
 
                                                 




                                              

                                                  
 
                                                   




































                                                                              


                                              

                                                  
 
                                                   
 

                                
 

                                    
 


                                                    
 
                 


                                             

                                                  
 

                                                   
 

                                    
 

                           
 

                                      
 
                                         
 
                 


                                             

                                                  
 
                                                   
 

                                
 

                                    
 


                                                   
 
                 


                                              

                                                   
 

                                                   
 

                                    
 



                                            
 
                                                    
 
                 


                                              

                                                   
 


                                                   
 

                                
 

                                    
 
                                                   
 
                                             
 
                          
 

                                       
 
                                                        
 
                 





                                                          
                                       






                                                          
                                       






                                                          
                                   






                                                          
                                   



                                                

                                                
 





































                                                                            


                                                

                                                
 



















































                                                                             


                                               

                                                  
 

                                                   
 

                                    
 



                                        
 
                                             
 
                 


                                               

                                                  
 

                                                   
 

                                    
 
                                                   
 



                                                             
 
                                                        
 
                 

 
























































































































































































































































































































































































































































































































                                                                               

                                                                            
                                             






                                                                            
                                                         


                                                        

                                                                 



                                                                       
                                      
                  

                         


                         
                      


                                                


                                                               

                                                       


                                                                         
                      


                                                       


                                                                        
                      
                            



                                               






















                                                                       
 



                                                            
 




























































                                                                             







                                                                        
                      

                                                                








                                                                            





                                                                 
               


























































































































                                                                                
































































































                                                                               





































                                                                           




                                                                              














                                                                 
 















                                                                              
 





                                                                            
 





















                                                                            
 
                                            
 








                                                            
 

                                                                       
 


                           
 







                                                                    
 
                             
                        
 
                                
 

                                
 
















                                                                          
 

















                                                                          
                                             




                                                               
 



                                                       
 







                                                 
 
                                                                        
 

                                              
 


                                                                          
 


                                                                     
                                 

                                                                         
 





                                                                       
 


                                                                       
                                 

                                               

                         







                                                                           
 





                                                      
 







                                                                           
 







































































                                                                              
                                         








                                                                              
                                 





















                                                                             
                                 















                                                                             

                                         
                         








































































                                                                               
                 













                                                                             
                              
                 
 




                                                                               
 


























                                                                              
 
/*
 * 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 <linux/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

#include <net/iw_handler.h>

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;
}

/*
 * 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);
}

/*
 * 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;
	char    buf[64*2 + 30];

	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;
	iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
				| IW_QUAL_NOISE_UPDATED;
	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;
		#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;
		}
	}
	/* 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;

	range->txpower_capa = IW_TXPOW_DBM;
	/* XXX what about min/max_pmp, min/max_pmt, etc. */

	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;

	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;
	/* B,G Bands */
	for (i = 1; i <= 14; i++) {
		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);
	/* A Bands */
	for (i = 0; i < num_band_a; i++) {
		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(KERN_WARNING "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(KERN_WARNING "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(KERN_WARNING "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 (current_ev == end_buf) {
			kfree(pBssList);
			data->length = current_ev - extra;
			return -E2BIG;
		}
	}

	/* 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(KERN_WARNING "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;
	int 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:
		/* ZM_ENABLE_CENC */
		keyLen = 32;
		break;
	#endif
	case ZM_NO_WEP:
		keyLen = 0;
		break;
	default:
		keyLen = 0;
		printk(KERN_ERR "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;
*				 *//* XXX needed by ic_reset *//*
*				vap->iv_ic->ic_flags |= IEEE80211_F_WME;
*			}
*			else {
*				*//* XXX needed by ic_reset *//*
*				vap->iv_flags &= ~IEEE80211_F_WME;
*				vap->iv_ic->ic_flags &= ~IEEE80211_F_WME;
*			}
*			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_WARNING
				"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_WARNING
			"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_WARNING
				"ZM_IOCTL_TEST:len=%d\n", zdreq->addr);
		/* zfiWlanReadReg(dev, 0x10f400); */
		/* zfiWlanReadReg(dev, 0x10f404); */
		printk(KERN_WARNING "IOCTL TEST\n");
		#if 1
		/* print packet */
		for (i = 0; i < zdreq->addr; i++) {
			if ((i&0x7) == 0)
				printk(KERN_WARNING "\n");
			printk(KERN_WARNING "%02X ",
					(unsigned char)zdreq->data[i]);
		}
		printk(KERN_WARNING "\n");
		#endif

		/* For Test?? 1 to 0 by CWYang(-) */
		#if 0
			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(KERN_WARNING
			"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(KERN_WARNING
			"Current Signal Strength : %02d\n", buffer[0]);
	}
		break;
		/* CWYang(+) */
	case ZM_IOCTL_SIGNAL_QUALITY: {
		u8_t buffer[2];
		zfiWlanQuerySignalInfo(dev, &buffer[0]);
		printk(KERN_WARNING
			"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;
	int ii;

	/* 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;

			/* del group key */
			if (zdparm->sta_addr[0] & 1) {
				/* 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) {
			printk(KERN_WARNING
						"Otus: Key Context:\n");
			for (ii = 0; ii < keyInfo.keyLength; ) {
				printk(KERN_WARNING
						"0x%02x ", keyInfo.key[ii]);
				if ((++ii % 16) == 0)
					printk(KERN_WARNING "\n");
			}
			printk(KERN_WARNING "\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(KERN_WARNING
				" -------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(KERN_WARNING
				" -------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);
		*/
		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, val = 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;
	/* set_auth */
	case SIOCIWFIRSTPRIV + 0x2: {
		/* printk("CWY - SIOCIWFIRSTPRIV + 0x2(set_auth)\n"); */
		if (!capable(CAP_NET_ADMIN)) {
			err = -EPERM;
			break;
		}
		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;
	/* get_auth */
	case SIOCIWFIRSTPRIV + 0x3: {
		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;
	/* debug command */
	case ZDAPIOCTL:
		if (copy_from_user(&zdreq, ifr->ifr_data, sizeof(zdreq))) {
			printk(KERN_ERR "usbdrv : copy_from_user error\n");
			return -EFAULT;
		}

		/* printk(KERN_WARNING
		* "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);
			}
			/* WPA or WPAPSK */
			if ((macp->supIe[21] == 0x50) ||
				(macp->supIe[22] == 0xf2)) {
				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);
				}
			}
			//WPA2 or WPA2PSK
			if ((macp->supIe[17] == 0xf) ||
				(macp->supIe[18] == 0xac)) {
				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;
}