cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

r8192U_wx.c (26102B)


      1// SPDX-License-Identifier: GPL-2.0
      2/******************************************************************************
      3 *
      4 * This file contains wireless extension handlers.
      5 *
      6 * This is part of rtl8180 OpenSource driver.
      7 * Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
      8 *
      9 * Parts of this driver are based on the GPL part
     10 * of the official realtek driver.
     11 *
     12 * Parts of this driver are based on the rtl8180 driver skeleton
     13 * from Patric Schenke & Andres Salomon.
     14 *
     15 * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
     16 *
     17 * We want to thank the Authors of those projects and the Ndiswrapper
     18 * project Authors.
     19 *
     20 *****************************************************************************/
     21
     22#include <linux/string.h>
     23#include "r8192U.h"
     24#include "r8192U_hw.h"
     25
     26#include "ieee80211/dot11d.h"
     27#include "r8192U_wx.h"
     28
     29#define RATE_COUNT 12
     30static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
     31	6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
     32
     33#ifndef ENETDOWN
     34#define ENETDOWN 1
     35#endif
     36
     37static int r8192_wx_get_freq(struct net_device *dev,
     38			     struct iw_request_info *a,
     39			     union iwreq_data *wrqu, char *b)
     40{
     41	struct r8192_priv *priv = ieee80211_priv(dev);
     42
     43	return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
     44}
     45
     46static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
     47			     union iwreq_data *wrqu, char *b)
     48{
     49	struct r8192_priv *priv = ieee80211_priv(dev);
     50
     51	return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
     52}
     53
     54static int r8192_wx_get_rate(struct net_device *dev,
     55			     struct iw_request_info *info,
     56			     union iwreq_data *wrqu, char *extra)
     57{
     58	struct r8192_priv *priv = ieee80211_priv(dev);
     59
     60	return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
     61}
     62
     63static int r8192_wx_set_rate(struct net_device *dev,
     64			     struct iw_request_info *info,
     65			     union iwreq_data *wrqu, char *extra)
     66{
     67	int ret;
     68	struct r8192_priv *priv = ieee80211_priv(dev);
     69
     70	mutex_lock(&priv->wx_mutex);
     71
     72	ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
     73
     74	mutex_unlock(&priv->wx_mutex);
     75
     76	return ret;
     77}
     78
     79static int r8192_wx_set_rts(struct net_device *dev,
     80			    struct iw_request_info *info,
     81			    union iwreq_data *wrqu, char *extra)
     82{
     83	int ret;
     84	struct r8192_priv *priv = ieee80211_priv(dev);
     85
     86	mutex_lock(&priv->wx_mutex);
     87
     88	ret = ieee80211_wx_set_rts(priv->ieee80211, info, wrqu, extra);
     89
     90	mutex_unlock(&priv->wx_mutex);
     91
     92	return ret;
     93}
     94
     95static int r8192_wx_get_rts(struct net_device *dev,
     96			    struct iw_request_info *info,
     97			    union iwreq_data *wrqu, char *extra)
     98{
     99	struct r8192_priv *priv = ieee80211_priv(dev);
    100
    101	return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra);
    102}
    103
    104static int r8192_wx_set_power(struct net_device *dev,
    105			      struct iw_request_info *info,
    106			      union iwreq_data *wrqu, char *extra)
    107{
    108	int ret;
    109	struct r8192_priv *priv = ieee80211_priv(dev);
    110
    111	mutex_lock(&priv->wx_mutex);
    112
    113	ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
    114
    115	mutex_unlock(&priv->wx_mutex);
    116
    117	return ret;
    118}
    119
    120static int r8192_wx_get_power(struct net_device *dev,
    121			      struct iw_request_info *info,
    122			      union iwreq_data *wrqu, char *extra)
    123{
    124	struct r8192_priv *priv = ieee80211_priv(dev);
    125
    126	return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
    127}
    128
    129static int r8192_wx_force_reset(struct net_device *dev,
    130				struct iw_request_info *info,
    131				union iwreq_data *wrqu, char *extra)
    132{
    133	struct r8192_priv *priv = ieee80211_priv(dev);
    134
    135	mutex_lock(&priv->wx_mutex);
    136
    137	netdev_dbg(dev, "%s(): force reset ! extra is %d\n", __func__, *extra);
    138	priv->force_reset = *extra;
    139	mutex_unlock(&priv->wx_mutex);
    140	return 0;
    141}
    142
    143static int r8192_wx_set_rawtx(struct net_device *dev,
    144			      struct iw_request_info *info,
    145			      union iwreq_data *wrqu, char *extra)
    146{
    147	struct r8192_priv *priv = ieee80211_priv(dev);
    148	int ret;
    149
    150	mutex_lock(&priv->wx_mutex);
    151
    152	ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
    153
    154	mutex_unlock(&priv->wx_mutex);
    155
    156	return ret;
    157}
    158
    159static int r8192_wx_set_crcmon(struct net_device *dev,
    160			       struct iw_request_info *info,
    161			       union iwreq_data *wrqu, char *extra)
    162{
    163	struct r8192_priv *priv = ieee80211_priv(dev);
    164	int *parms = (int *)extra;
    165	int enable = (parms[0] > 0);
    166
    167	mutex_lock(&priv->wx_mutex);
    168
    169	if (enable)
    170		priv->crcmon = 1;
    171	else
    172		priv->crcmon = 0;
    173
    174	DMESG("bad CRC in monitor mode are %s",
    175	      priv->crcmon ? "accepted" : "rejected");
    176
    177	mutex_unlock(&priv->wx_mutex);
    178
    179	return 0;
    180}
    181
    182static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
    183			     union iwreq_data *wrqu, char *b)
    184{
    185	struct r8192_priv *priv = ieee80211_priv(dev);
    186	int ret;
    187
    188	mutex_lock(&priv->wx_mutex);
    189
    190	ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
    191
    192	rtl8192_set_rxconf(dev);
    193
    194	mutex_unlock(&priv->wx_mutex);
    195	return ret;
    196}
    197
    198struct  iw_range_with_scan_capa {
    199	/* Informative stuff (to choose between different interface) */
    200	__u32           throughput;     /* To give an idea... */
    201	/* In theory this value should be the maximum benchmarked
    202	 * TCP/IP throughput, because with most of these devices the
    203	 * bit rate is meaningless (overhead an co) to estimate how
    204	 * fast the connection will go and pick the fastest one.
    205	 * I suggest people to play with Netperf or any benchmark...
    206	 */
    207
    208	/* NWID (or domain id) */
    209	__u32           min_nwid;       /* Minimal NWID we are able to set */
    210	__u32           max_nwid;       /* Maximal NWID we are able to set */
    211
    212	/* Old Frequency (backward compat - moved lower ) */
    213	__u16           old_num_channels;
    214	__u8            old_num_frequency;
    215
    216	/* Scan capabilities */
    217	__u8            scan_capa;
    218};
    219
    220static int rtl8180_wx_get_range(struct net_device *dev,
    221				struct iw_request_info *info,
    222				union iwreq_data *wrqu, char *extra)
    223{
    224	struct iw_range *range = (struct iw_range *)extra;
    225	struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
    226	struct r8192_priv *priv = ieee80211_priv(dev);
    227	u16 val;
    228	int i;
    229
    230	wrqu->data.length = sizeof(*range);
    231	memset(range, 0, sizeof(*range));
    232
    233	/* Let's try to keep this struct in the same order as in
    234	 * linux/include/wireless.h
    235	 */
    236
    237	/* TODO: See what values we can set, and remove the ones we can't
    238	 * set, or fill them with some default data.
    239	 */
    240
    241	/* ~5 Mb/s real (802.11b) */
    242	range->throughput = 5 * 1000 * 1000;
    243
    244	/* TODO: Not used in 802.11b? */
    245	/* range->min_nwid; */	/* Minimal NWID we are able to set */
    246	/* TODO: Not used in 802.11b? */
    247	/* range->max_nwid; */	/* Maximal NWID we are able to set */
    248
    249	/* Old Frequency (backward compat - moved lower ) */
    250	/* range->old_num_channels; */
    251	/* range->old_num_frequency; */
    252	/* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
    253	if (priv->rf_set_sens)
    254		range->sensitivity = priv->max_sens;	/* signal level threshold range */
    255
    256	range->max_qual.qual = 100;
    257	/* TODO: Find real max RSSI and stick here */
    258	range->max_qual.level = 0;
    259	range->max_qual.noise = 0x100 - 98;
    260	range->max_qual.updated = 7; /* Updated all three */
    261
    262	range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
    263	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
    264	range->avg_qual.level = 0x100 - 78;
    265	range->avg_qual.noise = 0;
    266	range->avg_qual.updated = 7; /* Updated all three */
    267
    268	range->num_bitrates = RATE_COUNT;
    269
    270	for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
    271		range->bitrate[i] = rtl8180_rates[i];
    272
    273	range->min_frag = MIN_FRAG_THRESHOLD;
    274	range->max_frag = MAX_FRAG_THRESHOLD;
    275
    276	range->min_pmp = 0;
    277	range->max_pmp = 5000000;
    278	range->min_pmt = 0;
    279	range->max_pmt = 65535 * 1000;
    280	range->pmp_flags = IW_POWER_PERIOD;
    281	range->pmt_flags = IW_POWER_TIMEOUT;
    282	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
    283
    284	range->we_version_compiled = WIRELESS_EXT;
    285	range->we_version_source = 16;
    286
    287	/* range->retry_capa; */	/* What retry options are supported */
    288	/* range->retry_flags; */	/* How to decode max/min retry limit */
    289	/* range->r_time_flags; */	/* How to decode max/min retry life */
    290	/* range->min_retry; */		/* Minimal number of retries */
    291	/* range->max_retry; */		/* Maximal number of retries */
    292	/* range->min_r_time; */	/* Minimal retry lifetime */
    293	/* range->max_r_time; */	/* Maximal retry lifetime */
    294
    295	for (i = 0, val = 0; i < 14; i++) {
    296		/* Include only legal frequencies for some countries */
    297		if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i + 1]) {
    298			range->freq[val].i = i + 1;
    299			range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
    300			range->freq[val].e = 1;
    301			val++;
    302		} else {
    303			/* FIXME: do we need to set anything for channels */
    304			/* we don't use ? */
    305		}
    306
    307		if (val == IW_MAX_FREQUENCIES)
    308			break;
    309	}
    310	range->num_frequency = val;
    311	range->num_channels = val;
    312	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
    313			  IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
    314	tmp->scan_capa = 0x01;
    315	return 0;
    316}
    317
    318static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
    319			     union iwreq_data *wrqu, char *b)
    320{
    321	struct r8192_priv *priv = ieee80211_priv(dev);
    322	struct ieee80211_device *ieee = priv->ieee80211;
    323	int ret = 0;
    324
    325	if (!priv->up)
    326		return -ENETDOWN;
    327
    328	if (priv->ieee80211->LinkDetectInfo.bBusyTraffic)
    329		return -EAGAIN;
    330	if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
    331		struct iw_scan_req *req = (struct iw_scan_req *)b;
    332
    333		if (req->essid_len) {
    334			int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE);
    335
    336			ieee->current_network.ssid_len = len;
    337			memcpy(ieee->current_network.ssid, req->essid, len);
    338		}
    339	}
    340
    341	mutex_lock(&priv->wx_mutex);
    342	if (priv->ieee80211->state != IEEE80211_LINKED) {
    343		priv->ieee80211->scanning = 0;
    344		ieee80211_softmac_scan_syncro(priv->ieee80211);
    345		ret = 0;
    346	} else {
    347		ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
    348	}
    349	mutex_unlock(&priv->wx_mutex);
    350	return ret;
    351}
    352
    353static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
    354			     union iwreq_data *wrqu, char *b)
    355{
    356	int ret;
    357	struct r8192_priv *priv = ieee80211_priv(dev);
    358
    359	if (!priv->up)
    360		return -ENETDOWN;
    361
    362	mutex_lock(&priv->wx_mutex);
    363
    364	ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
    365
    366	mutex_unlock(&priv->wx_mutex);
    367
    368	return ret;
    369}
    370
    371static int r8192_wx_set_essid(struct net_device *dev,
    372			      struct iw_request_info *a,
    373			      union iwreq_data *wrqu, char *b)
    374{
    375	struct r8192_priv *priv = ieee80211_priv(dev);
    376	int ret;
    377
    378	mutex_lock(&priv->wx_mutex);
    379
    380	ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
    381
    382	mutex_unlock(&priv->wx_mutex);
    383
    384	return ret;
    385}
    386
    387static int r8192_wx_get_essid(struct net_device *dev,
    388			      struct iw_request_info *a,
    389			      union iwreq_data *wrqu, char *b)
    390{
    391	int ret;
    392	struct r8192_priv *priv = ieee80211_priv(dev);
    393
    394	mutex_lock(&priv->wx_mutex);
    395
    396	ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
    397
    398	mutex_unlock(&priv->wx_mutex);
    399
    400	return ret;
    401}
    402
    403static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
    404			     union iwreq_data *wrqu, char *b)
    405{
    406	int ret;
    407	struct r8192_priv *priv = ieee80211_priv(dev);
    408
    409	mutex_lock(&priv->wx_mutex);
    410
    411	ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
    412
    413	mutex_unlock(&priv->wx_mutex);
    414	return ret;
    415}
    416
    417static int r8192_wx_get_name(struct net_device *dev,
    418			     struct iw_request_info *info,
    419			     union iwreq_data *wrqu, char *extra)
    420{
    421	struct r8192_priv *priv = ieee80211_priv(dev);
    422
    423	return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
    424}
    425
    426static int r8192_wx_set_frag(struct net_device *dev,
    427			     struct iw_request_info *info,
    428			     union iwreq_data *wrqu, char *extra)
    429{
    430	struct r8192_priv *priv = ieee80211_priv(dev);
    431
    432	if (wrqu->frag.disabled) {
    433		priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
    434	} else {
    435		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
    436		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
    437			return -EINVAL;
    438
    439		priv->ieee80211->fts = wrqu->frag.value & ~0x1;
    440	}
    441
    442	return 0;
    443}
    444
    445static int r8192_wx_get_frag(struct net_device *dev,
    446			     struct iw_request_info *info,
    447			     union iwreq_data *wrqu, char *extra)
    448{
    449	struct r8192_priv *priv = ieee80211_priv(dev);
    450
    451	wrqu->frag.value = priv->ieee80211->fts;
    452	wrqu->frag.fixed = 0;	/* no auto select */
    453	wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
    454
    455	return 0;
    456}
    457
    458static int r8192_wx_set_wap(struct net_device *dev,
    459			    struct iw_request_info *info,
    460			    union iwreq_data *awrq,
    461			    char *extra)
    462{
    463	int ret;
    464	struct r8192_priv *priv = ieee80211_priv(dev);
    465	/* struct sockaddr *temp = (struct sockaddr *)awrq; */
    466	mutex_lock(&priv->wx_mutex);
    467
    468	ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
    469
    470	mutex_unlock(&priv->wx_mutex);
    471
    472	return ret;
    473}
    474
    475static int r8192_wx_get_wap(struct net_device *dev,
    476			    struct iw_request_info *info,
    477			    union iwreq_data *wrqu, char *extra)
    478{
    479	struct r8192_priv *priv = ieee80211_priv(dev);
    480
    481	return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
    482}
    483
    484static int r8192_wx_get_enc(struct net_device *dev,
    485			    struct iw_request_info *info,
    486			    union iwreq_data *wrqu, char *key)
    487{
    488	struct r8192_priv *priv = ieee80211_priv(dev);
    489
    490	return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
    491}
    492
    493static int r8192_wx_set_enc(struct net_device *dev,
    494			    struct iw_request_info *info,
    495			    union iwreq_data *wrqu, char *key)
    496{
    497	struct r8192_priv *priv = ieee80211_priv(dev);
    498	struct ieee80211_device *ieee = priv->ieee80211;
    499	int ret;
    500	u32 hwkey[4] = {0, 0, 0, 0};
    501	u8 mask = 0xff;
    502	u32 key_idx = 0;
    503	u8 zero_addr[4][6] = {	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    504				{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
    505				{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
    506				{0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
    507	int i;
    508
    509	if (!priv->up)
    510		return -ENETDOWN;
    511
    512	mutex_lock(&priv->wx_mutex);
    513
    514	RT_TRACE(COMP_SEC, "Setting SW wep key");
    515	ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
    516
    517	mutex_unlock(&priv->wx_mutex);
    518
    519	/* sometimes, the length is zero while we do not type key value */
    520	if (wrqu->encoding.length != 0) {
    521		for (i = 0; i < 4; i++) {
    522			hwkey[i] |=  key[4 * i + 0] & mask;
    523			if (i == 1 && (4 * i + 1) == wrqu->encoding.length)
    524				mask = 0x00;
    525			if (i == 3 && (4 * i + 1) == wrqu->encoding.length)
    526				mask = 0x00;
    527			hwkey[i] |= (key[4 * i + 1] & mask) << 8;
    528			hwkey[i] |= (key[4 * i + 2] & mask) << 16;
    529			hwkey[i] |= (key[4 * i + 3] & mask) << 24;
    530		}
    531
    532		#define CONF_WEP40  0x4
    533		#define CONF_WEP104 0x14
    534
    535		switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
    536		case 0:
    537			key_idx = ieee->tx_keyidx;
    538			break;
    539		case 1:
    540			key_idx = 0;
    541			break;
    542		case 2:
    543			key_idx = 1;
    544			break;
    545		case 3:
    546			key_idx = 2;
    547			break;
    548		case 4:
    549			key_idx	= 3;
    550			break;
    551		default:
    552			break;
    553		}
    554
    555		if (wrqu->encoding.length == 0x5) {
    556			ieee->pairwise_key_type = KEY_TYPE_WEP40;
    557			EnableHWSecurityConfig8192(dev);
    558
    559			setKey(dev,
    560			       key_idx,                /* EntryNo */
    561			       key_idx,                /* KeyIndex */
    562			       KEY_TYPE_WEP40,         /* KeyType */
    563			       zero_addr[key_idx],
    564			       0,                      /* DefaultKey */
    565			       hwkey);                 /* KeyContent */
    566		} else if (wrqu->encoding.length == 0xd) {
    567			ieee->pairwise_key_type = KEY_TYPE_WEP104;
    568			EnableHWSecurityConfig8192(dev);
    569
    570			setKey(dev,
    571			       key_idx,                /* EntryNo */
    572			       key_idx,                /* KeyIndex */
    573			       KEY_TYPE_WEP104,        /* KeyType */
    574			       zero_addr[key_idx],
    575			       0,                      /* DefaultKey */
    576			       hwkey);                 /* KeyContent */
    577		} else {
    578			netdev_warn(dev, "wrong type in WEP, not WEP40 and WEP104\n");
    579		}
    580	}
    581
    582	return ret;
    583}
    584
    585static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa,
    586				  union iwreq_data *wrqu, char *p)
    587{
    588	struct r8192_priv *priv = ieee80211_priv(dev);
    589	int *parms = (int *)p;
    590	int mode = parms[0];
    591
    592	priv->ieee80211->active_scan = mode;
    593
    594	return 1;
    595}
    596
    597static int r8192_wx_set_retry(struct net_device *dev,
    598			      struct iw_request_info *info,
    599			      union iwreq_data *wrqu, char *extra)
    600{
    601	struct r8192_priv *priv = ieee80211_priv(dev);
    602	int err = 0;
    603
    604	mutex_lock(&priv->wx_mutex);
    605
    606	if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
    607	    wrqu->retry.disabled){
    608		err = -EINVAL;
    609		goto exit;
    610	}
    611	if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
    612		err = -EINVAL;
    613		goto exit;
    614	}
    615
    616	if (wrqu->retry.value > R8180_MAX_RETRY) {
    617		err = -EINVAL;
    618		goto exit;
    619	}
    620	if (wrqu->retry.flags & IW_RETRY_MAX) {
    621		priv->retry_rts = wrqu->retry.value;
    622		DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
    623
    624	} else {
    625		priv->retry_data = wrqu->retry.value;
    626		DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
    627	}
    628
    629	/* FIXME !
    630	 * We might try to write directly the TX config register
    631	 * or to restart just the (R)TX process.
    632	 * I'm unsure if whole reset is really needed
    633	 */
    634
    635	rtl8192_commit(dev);
    636exit:
    637	mutex_unlock(&priv->wx_mutex);
    638
    639	return err;
    640}
    641
    642static int r8192_wx_get_retry(struct net_device *dev,
    643			      struct iw_request_info *info,
    644			      union iwreq_data *wrqu, char *extra)
    645{
    646	struct r8192_priv *priv = ieee80211_priv(dev);
    647
    648	wrqu->retry.disabled = 0; /* can't be disabled */
    649
    650	if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
    651	    IW_RETRY_LIFETIME)
    652		return -EINVAL;
    653
    654	if (wrqu->retry.flags & IW_RETRY_MAX) {
    655		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
    656		wrqu->retry.value = priv->retry_rts;
    657	} else {
    658		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
    659		wrqu->retry.value = priv->retry_data;
    660	}
    661
    662	return 0;
    663}
    664
    665static int r8192_wx_get_sens(struct net_device *dev,
    666			     struct iw_request_info *info,
    667			     union iwreq_data *wrqu, char *extra)
    668{
    669	struct r8192_priv *priv = ieee80211_priv(dev);
    670
    671	if (!priv->rf_set_sens)
    672		return -1; /* we have not this support for this radio */
    673	wrqu->sens.value = priv->sens;
    674	return 0;
    675}
    676
    677static int r8192_wx_set_sens(struct net_device *dev,
    678			     struct iw_request_info *info,
    679			     union iwreq_data *wrqu, char *extra)
    680{
    681	struct r8192_priv *priv = ieee80211_priv(dev);
    682	short err = 0;
    683
    684	mutex_lock(&priv->wx_mutex);
    685	if (!priv->rf_set_sens) {
    686		err = -1; /* we have not this support for this radio */
    687		goto exit;
    688	}
    689	if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
    690		priv->sens = wrqu->sens.value;
    691	else
    692		err = -EINVAL;
    693
    694exit:
    695	mutex_unlock(&priv->wx_mutex);
    696
    697	return err;
    698}
    699
    700/* hw security need to reorganized. */
    701static int r8192_wx_set_enc_ext(struct net_device *dev,
    702				struct iw_request_info *info,
    703				union iwreq_data *wrqu, char *extra)
    704{
    705	int ret = 0;
    706	struct r8192_priv *priv = ieee80211_priv(dev);
    707	struct ieee80211_device *ieee = priv->ieee80211;
    708
    709	mutex_lock(&priv->wx_mutex);
    710	ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
    711
    712	{
    713		u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    714		u8 zero[6] = {0};
    715		u32 key[4] = {0};
    716		struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
    717		struct iw_point *encoding = &wrqu->encoding;
    718		u8 idx = 0, alg = 0, group = 0;
    719
    720		if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
    721			/* none is not allowed to use hwsec WB 2008.07.01 */
    722			goto end_hw_sec;
    723
    724		/* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */
    725		alg =  (ext->alg == IW_ENCODE_ALG_CCMP) ? KEY_TYPE_CCMP : ext->alg;
    726		idx = encoding->flags & IW_ENCODE_INDEX;
    727		if (idx)
    728			idx--;
    729		group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
    730
    731		if ((!group) || (ieee->iw_mode == IW_MODE_ADHOC) || (alg ==  KEY_TYPE_WEP40)) {
    732			if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
    733				alg = KEY_TYPE_WEP104;
    734			ieee->pairwise_key_type = alg;
    735			EnableHWSecurityConfig8192(dev);
    736		}
    737		memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */
    738
    739		if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
    740			setKey(dev,
    741			       idx,	/* EntryNao */
    742			       idx,	/* KeyIndex */
    743			       alg,	/* KeyType */
    744			       zero,	/* MacAddr */
    745			       0,	/* DefaultKey */
    746			       key);	/* KeyContent */
    747		} else if (group) {
    748			ieee->group_key_type = alg;
    749			setKey(dev,
    750			       idx,	/* EntryNo */
    751			       idx,	/* KeyIndex */
    752			       alg,	/* KeyType */
    753			       broadcast_addr,	/* MacAddr */
    754			       0,		/* DefaultKey */
    755			       key);		/* KeyContent */
    756		} else {	/* pairwise key */
    757			setKey(dev,
    758			       4,	/* EntryNo */
    759			       idx,	/* KeyIndex */
    760			       alg,	/* KeyType */
    761			       (u8 *)ieee->ap_mac_addr,/* MacAddr */
    762			       0,			/* DefaultKey */
    763			       key);			/* KeyContent */
    764		}
    765	}
    766
    767end_hw_sec:
    768
    769	mutex_unlock(&priv->wx_mutex);
    770	return ret;
    771}
    772
    773static int r8192_wx_set_auth(struct net_device *dev,
    774			     struct iw_request_info *info,
    775			     union iwreq_data *data, char *extra)
    776{
    777	int ret = 0;
    778	struct r8192_priv *priv = ieee80211_priv(dev);
    779
    780	mutex_lock(&priv->wx_mutex);
    781	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &data->param, extra);
    782	mutex_unlock(&priv->wx_mutex);
    783	return ret;
    784}
    785
    786static int r8192_wx_set_mlme(struct net_device *dev,
    787			     struct iw_request_info *info,
    788			     union iwreq_data *wrqu, char *extra)
    789{
    790	int ret = 0;
    791	struct r8192_priv *priv = ieee80211_priv(dev);
    792
    793	mutex_lock(&priv->wx_mutex);
    794	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
    795
    796	mutex_unlock(&priv->wx_mutex);
    797	return ret;
    798}
    799
    800static int r8192_wx_set_gen_ie(struct net_device *dev,
    801			       struct iw_request_info *info,
    802			       union iwreq_data *data, char *extra)
    803{
    804	int ret = 0;
    805	struct r8192_priv *priv = ieee80211_priv(dev);
    806
    807	mutex_lock(&priv->wx_mutex);
    808	ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
    809	mutex_unlock(&priv->wx_mutex);
    810	return ret;
    811}
    812
    813static int dummy(struct net_device *dev, struct iw_request_info *a,
    814		 union iwreq_data *wrqu, char *b)
    815{
    816	return -1;
    817}
    818
    819static iw_handler r8192_wx_handlers[] = {
    820	NULL,                     /* SIOCSIWCOMMIT */
    821	r8192_wx_get_name,	  /* SIOCGIWNAME */
    822	dummy,                    /* SIOCSIWNWID */
    823	dummy,                    /* SIOCGIWNWID */
    824	r8192_wx_set_freq,        /* SIOCSIWFREQ */
    825	r8192_wx_get_freq,        /* SIOCGIWFREQ */
    826	r8192_wx_set_mode,        /* SIOCSIWMODE */
    827	r8192_wx_get_mode,        /* SIOCGIWMODE */
    828	r8192_wx_set_sens,        /* SIOCSIWSENS */
    829	r8192_wx_get_sens,        /* SIOCGIWSENS */
    830	NULL,                     /* SIOCSIWRANGE */
    831	rtl8180_wx_get_range,	  /* SIOCGIWRANGE */
    832	NULL,                     /* SIOCSIWPRIV */
    833	NULL,                     /* SIOCGIWPRIV */
    834	NULL,                     /* SIOCSIWSTATS */
    835	NULL,                     /* SIOCGIWSTATS */
    836	dummy,                    /* SIOCSIWSPY */
    837	dummy,                    /* SIOCGIWSPY */
    838	NULL,                     /* SIOCGIWTHRSPY */
    839	NULL,                     /* SIOCWIWTHRSPY */
    840	r8192_wx_set_wap,	  /* SIOCSIWAP */
    841	r8192_wx_get_wap,         /* SIOCGIWAP */
    842	r8192_wx_set_mlme,                     /* MLME-- */
    843	dummy,                     /* SIOCGIWAPLIST -- deprecated */
    844	r8192_wx_set_scan,        /* SIOCSIWSCAN */
    845	r8192_wx_get_scan,        /* SIOCGIWSCAN */
    846	r8192_wx_set_essid,       /* SIOCSIWESSID */
    847	r8192_wx_get_essid,       /* SIOCGIWESSID */
    848	dummy,                    /* SIOCSIWNICKN */
    849	dummy,                    /* SIOCGIWNICKN */
    850	NULL,                     /* -- hole -- */
    851	NULL,                     /* -- hole -- */
    852	r8192_wx_set_rate,        /* SIOCSIWRATE */
    853	r8192_wx_get_rate,        /* SIOCGIWRATE */
    854	r8192_wx_set_rts,                    /* SIOCSIWRTS */
    855	r8192_wx_get_rts,                    /* SIOCGIWRTS */
    856	r8192_wx_set_frag,        /* SIOCSIWFRAG */
    857	r8192_wx_get_frag,        /* SIOCGIWFRAG */
    858	dummy,                    /* SIOCSIWTXPOW */
    859	dummy,                    /* SIOCGIWTXPOW */
    860	r8192_wx_set_retry,       /* SIOCSIWRETRY */
    861	r8192_wx_get_retry,       /* SIOCGIWRETRY */
    862	r8192_wx_set_enc,         /* SIOCSIWENCODE */
    863	r8192_wx_get_enc,         /* SIOCGIWENCODE */
    864	r8192_wx_set_power,                    /* SIOCSIWPOWER */
    865	r8192_wx_get_power,                    /* SIOCGIWPOWER */
    866	NULL,			/*---hole---*/
    867	NULL,			/*---hole---*/
    868	r8192_wx_set_gen_ie, /* NULL, */		/* SIOCSIWGENIE */
    869	NULL,			/* SIOCSIWGENIE */
    870
    871	r8192_wx_set_auth,/* NULL, */			/* SIOCSIWAUTH */
    872	NULL,/* r8192_wx_get_auth, */ /* NULL, */	/* SIOCSIWAUTH */
    873	r8192_wx_set_enc_ext,			/* SIOCSIWENCODEEXT */
    874	NULL,/* r8192_wx_get_enc_ext, *//* NULL, */			/* SIOCSIWENCODEEXT */
    875	NULL,			/* SIOCSIWPMKSA */
    876	NULL,			 /*---hole---*/
    877
    878};
    879
    880static const struct iw_priv_args r8192_private_args[] = {
    881	{
    882		SIOCIWFIRSTPRIV + 0x0,
    883		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
    884	},
    885	{
    886		SIOCIWFIRSTPRIV + 0x1,
    887		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
    888
    889	},
    890	{
    891		SIOCIWFIRSTPRIV + 0x2,
    892		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
    893	},
    894	{
    895		SIOCIWFIRSTPRIV + 0x3,
    896		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
    897	}
    898};
    899
    900static iw_handler r8192_private_handler[] = {
    901	r8192_wx_set_crcmon,
    902	r8192_wx_set_scan_type,
    903	r8192_wx_set_rawtx,
    904	r8192_wx_force_reset,
    905};
    906
    907struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
    908{
    909	struct r8192_priv *priv = ieee80211_priv(dev);
    910	struct ieee80211_device *ieee = priv->ieee80211;
    911	struct iw_statistics *wstats = &priv->wstats;
    912	int tmp_level = 0;
    913	int tmp_qual = 0;
    914	int tmp_noise = 0;
    915
    916	if (ieee->state < IEEE80211_LINKED) {
    917		wstats->qual.qual = 0;
    918		wstats->qual.level = 0;
    919		wstats->qual.noise = 0;
    920		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
    921		return wstats;
    922	}
    923
    924	tmp_level = (&ieee->current_network)->stats.rssi;
    925	tmp_qual = (&ieee->current_network)->stats.signal;
    926	tmp_noise = (&ieee->current_network)->stats.noise;
    927
    928	wstats->qual.level = tmp_level;
    929	wstats->qual.qual = tmp_qual;
    930	wstats->qual.noise = tmp_noise;
    931	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
    932	return wstats;
    933}
    934
    935const struct iw_handler_def  r8192_wx_handlers_def = {
    936	.standard = r8192_wx_handlers,
    937	.num_standard = ARRAY_SIZE(r8192_wx_handlers),
    938	.private = r8192_private_handler,
    939	.num_private = ARRAY_SIZE(r8192_private_handler),
    940	.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
    941	.get_wireless_stats = r8192_get_wireless_stats,
    942	.private_args = (struct iw_priv_args *)r8192_private_args,
    943};