Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /******************************************************************************
0003  *
0004  * This file contains wireless extension handlers.
0005  *
0006  * This is part of rtl8180 OpenSource driver.
0007  * Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
0008  *
0009  * Parts of this driver are based on the GPL part
0010  * of the official realtek driver.
0011  *
0012  * Parts of this driver are based on the rtl8180 driver skeleton
0013  * from Patric Schenke & Andres Salomon.
0014  *
0015  * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
0016  *
0017  * We want to thank the Authors of those projects and the Ndiswrapper
0018  * project Authors.
0019  *
0020  *****************************************************************************/
0021 
0022 #include <linux/string.h>
0023 #include "r8192U.h"
0024 #include "r8192U_hw.h"
0025 
0026 #include "ieee80211/dot11d.h"
0027 #include "r8192U_wx.h"
0028 
0029 #define RATE_COUNT 12
0030 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
0031     6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
0032 
0033 #ifndef ENETDOWN
0034 #define ENETDOWN 1
0035 #endif
0036 
0037 static int r8192_wx_get_freq(struct net_device *dev,
0038                  struct iw_request_info *a,
0039                  union iwreq_data *wrqu, char *b)
0040 {
0041     struct r8192_priv *priv = ieee80211_priv(dev);
0042 
0043     return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
0044 }
0045 
0046 static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
0047                  union iwreq_data *wrqu, char *b)
0048 {
0049     struct r8192_priv *priv = ieee80211_priv(dev);
0050 
0051     return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
0052 }
0053 
0054 static int r8192_wx_get_rate(struct net_device *dev,
0055                  struct iw_request_info *info,
0056                  union iwreq_data *wrqu, char *extra)
0057 {
0058     struct r8192_priv *priv = ieee80211_priv(dev);
0059 
0060     return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
0061 }
0062 
0063 static int r8192_wx_set_rate(struct net_device *dev,
0064                  struct iw_request_info *info,
0065                  union iwreq_data *wrqu, char *extra)
0066 {
0067     int ret;
0068     struct r8192_priv *priv = ieee80211_priv(dev);
0069 
0070     mutex_lock(&priv->wx_mutex);
0071 
0072     ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
0073 
0074     mutex_unlock(&priv->wx_mutex);
0075 
0076     return ret;
0077 }
0078 
0079 static int r8192_wx_set_rts(struct net_device *dev,
0080                 struct iw_request_info *info,
0081                 union iwreq_data *wrqu, char *extra)
0082 {
0083     int ret;
0084     struct r8192_priv *priv = ieee80211_priv(dev);
0085 
0086     mutex_lock(&priv->wx_mutex);
0087 
0088     ret = ieee80211_wx_set_rts(priv->ieee80211, info, wrqu, extra);
0089 
0090     mutex_unlock(&priv->wx_mutex);
0091 
0092     return ret;
0093 }
0094 
0095 static int r8192_wx_get_rts(struct net_device *dev,
0096                 struct iw_request_info *info,
0097                 union iwreq_data *wrqu, char *extra)
0098 {
0099     struct r8192_priv *priv = ieee80211_priv(dev);
0100 
0101     return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra);
0102 }
0103 
0104 static int r8192_wx_set_power(struct net_device *dev,
0105                   struct iw_request_info *info,
0106                   union iwreq_data *wrqu, char *extra)
0107 {
0108     int ret;
0109     struct r8192_priv *priv = ieee80211_priv(dev);
0110 
0111     mutex_lock(&priv->wx_mutex);
0112 
0113     ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
0114 
0115     mutex_unlock(&priv->wx_mutex);
0116 
0117     return ret;
0118 }
0119 
0120 static int r8192_wx_get_power(struct net_device *dev,
0121                   struct iw_request_info *info,
0122                   union iwreq_data *wrqu, char *extra)
0123 {
0124     struct r8192_priv *priv = ieee80211_priv(dev);
0125 
0126     return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
0127 }
0128 
0129 static int r8192_wx_force_reset(struct net_device *dev,
0130                 struct iw_request_info *info,
0131                 union iwreq_data *wrqu, char *extra)
0132 {
0133     struct r8192_priv *priv = ieee80211_priv(dev);
0134 
0135     mutex_lock(&priv->wx_mutex);
0136 
0137     netdev_dbg(dev, "%s(): force reset ! extra is %d\n", __func__, *extra);
0138     priv->force_reset = *extra;
0139     mutex_unlock(&priv->wx_mutex);
0140     return 0;
0141 }
0142 
0143 static int r8192_wx_set_rawtx(struct net_device *dev,
0144                   struct iw_request_info *info,
0145                   union iwreq_data *wrqu, char *extra)
0146 {
0147     struct r8192_priv *priv = ieee80211_priv(dev);
0148     int ret;
0149 
0150     mutex_lock(&priv->wx_mutex);
0151 
0152     ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
0153 
0154     mutex_unlock(&priv->wx_mutex);
0155 
0156     return ret;
0157 }
0158 
0159 static int r8192_wx_set_crcmon(struct net_device *dev,
0160                    struct iw_request_info *info,
0161                    union iwreq_data *wrqu, char *extra)
0162 {
0163     struct r8192_priv *priv = ieee80211_priv(dev);
0164     int *parms = (int *)extra;
0165     int enable = (parms[0] > 0);
0166 
0167     mutex_lock(&priv->wx_mutex);
0168 
0169     if (enable)
0170         priv->crcmon = 1;
0171     else
0172         priv->crcmon = 0;
0173 
0174     DMESG("bad CRC in monitor mode are %s",
0175           priv->crcmon ? "accepted" : "rejected");
0176 
0177     mutex_unlock(&priv->wx_mutex);
0178 
0179     return 0;
0180 }
0181 
0182 static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
0183                  union iwreq_data *wrqu, char *b)
0184 {
0185     struct r8192_priv *priv = ieee80211_priv(dev);
0186     int ret;
0187 
0188     mutex_lock(&priv->wx_mutex);
0189 
0190     ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
0191 
0192     rtl8192_set_rxconf(dev);
0193 
0194     mutex_unlock(&priv->wx_mutex);
0195     return ret;
0196 }
0197 
0198 struct  iw_range_with_scan_capa {
0199     /* Informative stuff (to choose between different interface) */
0200     __u32           throughput;     /* To give an idea... */
0201     /* In theory this value should be the maximum benchmarked
0202      * TCP/IP throughput, because with most of these devices the
0203      * bit rate is meaningless (overhead an co) to estimate how
0204      * fast the connection will go and pick the fastest one.
0205      * I suggest people to play with Netperf or any benchmark...
0206      */
0207 
0208     /* NWID (or domain id) */
0209     __u32           min_nwid;       /* Minimal NWID we are able to set */
0210     __u32           max_nwid;       /* Maximal NWID we are able to set */
0211 
0212     /* Old Frequency (backward compat - moved lower ) */
0213     __u16           old_num_channels;
0214     __u8            old_num_frequency;
0215 
0216     /* Scan capabilities */
0217     __u8            scan_capa;
0218 };
0219 
0220 static int rtl8180_wx_get_range(struct net_device *dev,
0221                 struct iw_request_info *info,
0222                 union iwreq_data *wrqu, char *extra)
0223 {
0224     struct iw_range *range = (struct iw_range *)extra;
0225     struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
0226     struct r8192_priv *priv = ieee80211_priv(dev);
0227     u16 val;
0228     int i;
0229 
0230     wrqu->data.length = sizeof(*range);
0231     memset(range, 0, sizeof(*range));
0232 
0233     /* Let's try to keep this struct in the same order as in
0234      * linux/include/wireless.h
0235      */
0236 
0237     /* TODO: See what values we can set, and remove the ones we can't
0238      * set, or fill them with some default data.
0239      */
0240 
0241     /* ~5 Mb/s real (802.11b) */
0242     range->throughput = 5 * 1000 * 1000;
0243 
0244     /* TODO: Not used in 802.11b? */
0245     /* range->min_nwid; */  /* Minimal NWID we are able to set */
0246     /* TODO: Not used in 802.11b? */
0247     /* range->max_nwid; */  /* Maximal NWID we are able to set */
0248 
0249     /* Old Frequency (backward compat - moved lower ) */
0250     /* range->old_num_channels; */
0251     /* range->old_num_frequency; */
0252     /* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
0253     if (priv->rf_set_sens)
0254         range->sensitivity = priv->max_sens;    /* signal level threshold range */
0255 
0256     range->max_qual.qual = 100;
0257     /* TODO: Find real max RSSI and stick here */
0258     range->max_qual.level = 0;
0259     range->max_qual.noise = 0x100 - 98;
0260     range->max_qual.updated = 7; /* Updated all three */
0261 
0262     range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
0263     /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
0264     range->avg_qual.level = 0x100 - 78;
0265     range->avg_qual.noise = 0;
0266     range->avg_qual.updated = 7; /* Updated all three */
0267 
0268     range->num_bitrates = RATE_COUNT;
0269 
0270     for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
0271         range->bitrate[i] = rtl8180_rates[i];
0272 
0273     range->min_frag = MIN_FRAG_THRESHOLD;
0274     range->max_frag = MAX_FRAG_THRESHOLD;
0275 
0276     range->min_pmp = 0;
0277     range->max_pmp = 5000000;
0278     range->min_pmt = 0;
0279     range->max_pmt = 65535 * 1000;
0280     range->pmp_flags = IW_POWER_PERIOD;
0281     range->pmt_flags = IW_POWER_TIMEOUT;
0282     range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
0283 
0284     range->we_version_compiled = WIRELESS_EXT;
0285     range->we_version_source = 16;
0286 
0287     /* range->retry_capa; */    /* What retry options are supported */
0288     /* range->retry_flags; */   /* How to decode max/min retry limit */
0289     /* range->r_time_flags; */  /* How to decode max/min retry life */
0290     /* range->min_retry; */     /* Minimal number of retries */
0291     /* range->max_retry; */     /* Maximal number of retries */
0292     /* range->min_r_time; */    /* Minimal retry lifetime */
0293     /* range->max_r_time; */    /* Maximal retry lifetime */
0294 
0295     for (i = 0, val = 0; i < 14; i++) {
0296         /* Include only legal frequencies for some countries */
0297         if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i + 1]) {
0298             range->freq[val].i = i + 1;
0299             range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
0300             range->freq[val].e = 1;
0301             val++;
0302         } else {
0303             /* FIXME: do we need to set anything for channels */
0304             /* we don't use ? */
0305         }
0306 
0307         if (val == IW_MAX_FREQUENCIES)
0308             break;
0309     }
0310     range->num_frequency = val;
0311     range->num_channels = val;
0312     range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
0313               IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
0314     tmp->scan_capa = 0x01;
0315     return 0;
0316 }
0317 
0318 static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
0319                  union iwreq_data *wrqu, char *b)
0320 {
0321     struct r8192_priv *priv = ieee80211_priv(dev);
0322     struct ieee80211_device *ieee = priv->ieee80211;
0323     int ret = 0;
0324 
0325     if (!priv->up)
0326         return -ENETDOWN;
0327 
0328     if (priv->ieee80211->LinkDetectInfo.bBusyTraffic)
0329         return -EAGAIN;
0330     if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
0331         struct iw_scan_req *req = (struct iw_scan_req *)b;
0332 
0333         if (req->essid_len) {
0334             int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE);
0335 
0336             ieee->current_network.ssid_len = len;
0337             memcpy(ieee->current_network.ssid, req->essid, len);
0338         }
0339     }
0340 
0341     mutex_lock(&priv->wx_mutex);
0342     if (priv->ieee80211->state != IEEE80211_LINKED) {
0343         priv->ieee80211->scanning = 0;
0344         ieee80211_softmac_scan_syncro(priv->ieee80211);
0345         ret = 0;
0346     } else {
0347         ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
0348     }
0349     mutex_unlock(&priv->wx_mutex);
0350     return ret;
0351 }
0352 
0353 static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
0354                  union iwreq_data *wrqu, char *b)
0355 {
0356     int ret;
0357     struct r8192_priv *priv = ieee80211_priv(dev);
0358 
0359     if (!priv->up)
0360         return -ENETDOWN;
0361 
0362     mutex_lock(&priv->wx_mutex);
0363 
0364     ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
0365 
0366     mutex_unlock(&priv->wx_mutex);
0367 
0368     return ret;
0369 }
0370 
0371 static int r8192_wx_set_essid(struct net_device *dev,
0372                   struct iw_request_info *a,
0373                   union iwreq_data *wrqu, char *b)
0374 {
0375     struct r8192_priv *priv = ieee80211_priv(dev);
0376     int ret;
0377 
0378     mutex_lock(&priv->wx_mutex);
0379 
0380     ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
0381 
0382     mutex_unlock(&priv->wx_mutex);
0383 
0384     return ret;
0385 }
0386 
0387 static int r8192_wx_get_essid(struct net_device *dev,
0388                   struct iw_request_info *a,
0389                   union iwreq_data *wrqu, char *b)
0390 {
0391     int ret;
0392     struct r8192_priv *priv = ieee80211_priv(dev);
0393 
0394     mutex_lock(&priv->wx_mutex);
0395 
0396     ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
0397 
0398     mutex_unlock(&priv->wx_mutex);
0399 
0400     return ret;
0401 }
0402 
0403 static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
0404                  union iwreq_data *wrqu, char *b)
0405 {
0406     int ret;
0407     struct r8192_priv *priv = ieee80211_priv(dev);
0408 
0409     mutex_lock(&priv->wx_mutex);
0410 
0411     ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
0412 
0413     mutex_unlock(&priv->wx_mutex);
0414     return ret;
0415 }
0416 
0417 static int r8192_wx_get_name(struct net_device *dev,
0418                  struct iw_request_info *info,
0419                  union iwreq_data *wrqu, char *extra)
0420 {
0421     struct r8192_priv *priv = ieee80211_priv(dev);
0422 
0423     return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
0424 }
0425 
0426 static int r8192_wx_set_frag(struct net_device *dev,
0427                  struct iw_request_info *info,
0428                  union iwreq_data *wrqu, char *extra)
0429 {
0430     struct r8192_priv *priv = ieee80211_priv(dev);
0431 
0432     if (wrqu->frag.disabled) {
0433         priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
0434     } else {
0435         if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
0436             wrqu->frag.value > MAX_FRAG_THRESHOLD)
0437             return -EINVAL;
0438 
0439         priv->ieee80211->fts = wrqu->frag.value & ~0x1;
0440     }
0441 
0442     return 0;
0443 }
0444 
0445 static int r8192_wx_get_frag(struct net_device *dev,
0446                  struct iw_request_info *info,
0447                  union iwreq_data *wrqu, char *extra)
0448 {
0449     struct r8192_priv *priv = ieee80211_priv(dev);
0450 
0451     wrqu->frag.value = priv->ieee80211->fts;
0452     wrqu->frag.fixed = 0;   /* no auto select */
0453     wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
0454 
0455     return 0;
0456 }
0457 
0458 static int r8192_wx_set_wap(struct net_device *dev,
0459                 struct iw_request_info *info,
0460                 union iwreq_data *awrq,
0461                 char *extra)
0462 {
0463     int ret;
0464     struct r8192_priv *priv = ieee80211_priv(dev);
0465     /* struct sockaddr *temp = (struct sockaddr *)awrq; */
0466     mutex_lock(&priv->wx_mutex);
0467 
0468     ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
0469 
0470     mutex_unlock(&priv->wx_mutex);
0471 
0472     return ret;
0473 }
0474 
0475 static int r8192_wx_get_wap(struct net_device *dev,
0476                 struct iw_request_info *info,
0477                 union iwreq_data *wrqu, char *extra)
0478 {
0479     struct r8192_priv *priv = ieee80211_priv(dev);
0480 
0481     return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
0482 }
0483 
0484 static int r8192_wx_get_enc(struct net_device *dev,
0485                 struct iw_request_info *info,
0486                 union iwreq_data *wrqu, char *key)
0487 {
0488     struct r8192_priv *priv = ieee80211_priv(dev);
0489 
0490     return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
0491 }
0492 
0493 static int r8192_wx_set_enc(struct net_device *dev,
0494                 struct iw_request_info *info,
0495                 union iwreq_data *wrqu, char *key)
0496 {
0497     struct r8192_priv *priv = ieee80211_priv(dev);
0498     struct ieee80211_device *ieee = priv->ieee80211;
0499     int ret;
0500     u32 hwkey[4] = {0, 0, 0, 0};
0501     u8 mask = 0xff;
0502     u32 key_idx = 0;
0503     u8 zero_addr[4][6] = {  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
0504                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
0505                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
0506                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
0507     int i;
0508 
0509     if (!priv->up)
0510         return -ENETDOWN;
0511 
0512     mutex_lock(&priv->wx_mutex);
0513 
0514     RT_TRACE(COMP_SEC, "Setting SW wep key");
0515     ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
0516 
0517     mutex_unlock(&priv->wx_mutex);
0518 
0519     /* sometimes, the length is zero while we do not type key value */
0520     if (wrqu->encoding.length != 0) {
0521         for (i = 0; i < 4; i++) {
0522             hwkey[i] |=  key[4 * i + 0] & mask;
0523             if (i == 1 && (4 * i + 1) == wrqu->encoding.length)
0524                 mask = 0x00;
0525             if (i == 3 && (4 * i + 1) == wrqu->encoding.length)
0526                 mask = 0x00;
0527             hwkey[i] |= (key[4 * i + 1] & mask) << 8;
0528             hwkey[i] |= (key[4 * i + 2] & mask) << 16;
0529             hwkey[i] |= (key[4 * i + 3] & mask) << 24;
0530         }
0531 
0532         #define CONF_WEP40  0x4
0533         #define CONF_WEP104 0x14
0534 
0535         switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
0536         case 0:
0537             key_idx = ieee->tx_keyidx;
0538             break;
0539         case 1:
0540             key_idx = 0;
0541             break;
0542         case 2:
0543             key_idx = 1;
0544             break;
0545         case 3:
0546             key_idx = 2;
0547             break;
0548         case 4:
0549             key_idx = 3;
0550             break;
0551         default:
0552             break;
0553         }
0554 
0555         if (wrqu->encoding.length == 0x5) {
0556             ieee->pairwise_key_type = KEY_TYPE_WEP40;
0557             EnableHWSecurityConfig8192(dev);
0558 
0559             setKey(dev,
0560                    key_idx,                /* EntryNo */
0561                    key_idx,                /* KeyIndex */
0562                    KEY_TYPE_WEP40,         /* KeyType */
0563                    zero_addr[key_idx],
0564                    0,                      /* DefaultKey */
0565                    hwkey);                 /* KeyContent */
0566         } else if (wrqu->encoding.length == 0xd) {
0567             ieee->pairwise_key_type = KEY_TYPE_WEP104;
0568             EnableHWSecurityConfig8192(dev);
0569 
0570             setKey(dev,
0571                    key_idx,                /* EntryNo */
0572                    key_idx,                /* KeyIndex */
0573                    KEY_TYPE_WEP104,        /* KeyType */
0574                    zero_addr[key_idx],
0575                    0,                      /* DefaultKey */
0576                    hwkey);                 /* KeyContent */
0577         } else {
0578             netdev_warn(dev, "wrong type in WEP, not WEP40 and WEP104\n");
0579         }
0580     }
0581 
0582     return ret;
0583 }
0584 
0585 static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa,
0586                   union iwreq_data *wrqu, char *p)
0587 {
0588     struct r8192_priv *priv = ieee80211_priv(dev);
0589     int *parms = (int *)p;
0590     int mode = parms[0];
0591 
0592     priv->ieee80211->active_scan = mode;
0593 
0594     return 1;
0595 }
0596 
0597 static int r8192_wx_set_retry(struct net_device *dev,
0598                   struct iw_request_info *info,
0599                   union iwreq_data *wrqu, char *extra)
0600 {
0601     struct r8192_priv *priv = ieee80211_priv(dev);
0602     int err = 0;
0603 
0604     mutex_lock(&priv->wx_mutex);
0605 
0606     if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
0607         wrqu->retry.disabled){
0608         err = -EINVAL;
0609         goto exit;
0610     }
0611     if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
0612         err = -EINVAL;
0613         goto exit;
0614     }
0615 
0616     if (wrqu->retry.value > R8180_MAX_RETRY) {
0617         err = -EINVAL;
0618         goto exit;
0619     }
0620     if (wrqu->retry.flags & IW_RETRY_MAX) {
0621         priv->retry_rts = wrqu->retry.value;
0622         DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
0623 
0624     } else {
0625         priv->retry_data = wrqu->retry.value;
0626         DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
0627     }
0628 
0629     /* FIXME !
0630      * We might try to write directly the TX config register
0631      * or to restart just the (R)TX process.
0632      * I'm unsure if whole reset is really needed
0633      */
0634 
0635     rtl8192_commit(dev);
0636 exit:
0637     mutex_unlock(&priv->wx_mutex);
0638 
0639     return err;
0640 }
0641 
0642 static int r8192_wx_get_retry(struct net_device *dev,
0643                   struct iw_request_info *info,
0644                   union iwreq_data *wrqu, char *extra)
0645 {
0646     struct r8192_priv *priv = ieee80211_priv(dev);
0647 
0648     wrqu->retry.disabled = 0; /* can't be disabled */
0649 
0650     if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
0651         IW_RETRY_LIFETIME)
0652         return -EINVAL;
0653 
0654     if (wrqu->retry.flags & IW_RETRY_MAX) {
0655         wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
0656         wrqu->retry.value = priv->retry_rts;
0657     } else {
0658         wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
0659         wrqu->retry.value = priv->retry_data;
0660     }
0661 
0662     return 0;
0663 }
0664 
0665 static int r8192_wx_get_sens(struct net_device *dev,
0666                  struct iw_request_info *info,
0667                  union iwreq_data *wrqu, char *extra)
0668 {
0669     struct r8192_priv *priv = ieee80211_priv(dev);
0670 
0671     if (!priv->rf_set_sens)
0672         return -1; /* we have not this support for this radio */
0673     wrqu->sens.value = priv->sens;
0674     return 0;
0675 }
0676 
0677 static int r8192_wx_set_sens(struct net_device *dev,
0678                  struct iw_request_info *info,
0679                  union iwreq_data *wrqu, char *extra)
0680 {
0681     struct r8192_priv *priv = ieee80211_priv(dev);
0682     short err = 0;
0683 
0684     mutex_lock(&priv->wx_mutex);
0685     if (!priv->rf_set_sens) {
0686         err = -1; /* we have not this support for this radio */
0687         goto exit;
0688     }
0689     if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
0690         priv->sens = wrqu->sens.value;
0691     else
0692         err = -EINVAL;
0693 
0694 exit:
0695     mutex_unlock(&priv->wx_mutex);
0696 
0697     return err;
0698 }
0699 
0700 /* hw security need to reorganized. */
0701 static int r8192_wx_set_enc_ext(struct net_device *dev,
0702                 struct iw_request_info *info,
0703                 union iwreq_data *wrqu, char *extra)
0704 {
0705     int ret = 0;
0706     struct r8192_priv *priv = ieee80211_priv(dev);
0707     struct ieee80211_device *ieee = priv->ieee80211;
0708 
0709     mutex_lock(&priv->wx_mutex);
0710     ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
0711 
0712     {
0713         u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
0714         u8 zero[6] = {0};
0715         u32 key[4] = {0};
0716         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
0717         struct iw_point *encoding = &wrqu->encoding;
0718         u8 idx = 0, alg = 0, group = 0;
0719 
0720         if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
0721             /* none is not allowed to use hwsec WB 2008.07.01 */
0722             goto end_hw_sec;
0723 
0724         /* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */
0725         alg =  (ext->alg == IW_ENCODE_ALG_CCMP) ? KEY_TYPE_CCMP : ext->alg;
0726         idx = encoding->flags & IW_ENCODE_INDEX;
0727         if (idx)
0728             idx--;
0729         group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
0730 
0731         if ((!group) || (ieee->iw_mode == IW_MODE_ADHOC) || (alg ==  KEY_TYPE_WEP40)) {
0732             if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
0733                 alg = KEY_TYPE_WEP104;
0734             ieee->pairwise_key_type = alg;
0735             EnableHWSecurityConfig8192(dev);
0736         }
0737         memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */
0738 
0739         if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
0740             setKey(dev,
0741                    idx, /* EntryNao */
0742                    idx, /* KeyIndex */
0743                    alg, /* KeyType */
0744                    zero,    /* MacAddr */
0745                    0,   /* DefaultKey */
0746                    key);    /* KeyContent */
0747         } else if (group) {
0748             ieee->group_key_type = alg;
0749             setKey(dev,
0750                    idx, /* EntryNo */
0751                    idx, /* KeyIndex */
0752                    alg, /* KeyType */
0753                    broadcast_addr,  /* MacAddr */
0754                    0,       /* DefaultKey */
0755                    key);        /* KeyContent */
0756         } else {    /* pairwise key */
0757             setKey(dev,
0758                    4,   /* EntryNo */
0759                    idx, /* KeyIndex */
0760                    alg, /* KeyType */
0761                    (u8 *)ieee->ap_mac_addr,/* MacAddr */
0762                    0,           /* DefaultKey */
0763                    key);            /* KeyContent */
0764         }
0765     }
0766 
0767 end_hw_sec:
0768 
0769     mutex_unlock(&priv->wx_mutex);
0770     return ret;
0771 }
0772 
0773 static int r8192_wx_set_auth(struct net_device *dev,
0774                  struct iw_request_info *info,
0775                  union iwreq_data *data, char *extra)
0776 {
0777     int ret = 0;
0778     struct r8192_priv *priv = ieee80211_priv(dev);
0779 
0780     mutex_lock(&priv->wx_mutex);
0781     ret = ieee80211_wx_set_auth(priv->ieee80211, info, &data->param, extra);
0782     mutex_unlock(&priv->wx_mutex);
0783     return ret;
0784 }
0785 
0786 static int r8192_wx_set_mlme(struct net_device *dev,
0787                  struct iw_request_info *info,
0788                  union iwreq_data *wrqu, char *extra)
0789 {
0790     int ret = 0;
0791     struct r8192_priv *priv = ieee80211_priv(dev);
0792 
0793     mutex_lock(&priv->wx_mutex);
0794     ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
0795 
0796     mutex_unlock(&priv->wx_mutex);
0797     return ret;
0798 }
0799 
0800 static int r8192_wx_set_gen_ie(struct net_device *dev,
0801                    struct iw_request_info *info,
0802                    union iwreq_data *data, char *extra)
0803 {
0804     int ret = 0;
0805     struct r8192_priv *priv = ieee80211_priv(dev);
0806 
0807     mutex_lock(&priv->wx_mutex);
0808     ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
0809     mutex_unlock(&priv->wx_mutex);
0810     return ret;
0811 }
0812 
0813 static int dummy(struct net_device *dev, struct iw_request_info *a,
0814          union iwreq_data *wrqu, char *b)
0815 {
0816     return -1;
0817 }
0818 
0819 static iw_handler r8192_wx_handlers[] = {
0820     NULL,                     /* SIOCSIWCOMMIT */
0821     r8192_wx_get_name,    /* SIOCGIWNAME */
0822     dummy,                    /* SIOCSIWNWID */
0823     dummy,                    /* SIOCGIWNWID */
0824     r8192_wx_set_freq,        /* SIOCSIWFREQ */
0825     r8192_wx_get_freq,        /* SIOCGIWFREQ */
0826     r8192_wx_set_mode,        /* SIOCSIWMODE */
0827     r8192_wx_get_mode,        /* SIOCGIWMODE */
0828     r8192_wx_set_sens,        /* SIOCSIWSENS */
0829     r8192_wx_get_sens,        /* SIOCGIWSENS */
0830     NULL,                     /* SIOCSIWRANGE */
0831     rtl8180_wx_get_range,     /* SIOCGIWRANGE */
0832     NULL,                     /* SIOCSIWPRIV */
0833     NULL,                     /* SIOCGIWPRIV */
0834     NULL,                     /* SIOCSIWSTATS */
0835     NULL,                     /* SIOCGIWSTATS */
0836     dummy,                    /* SIOCSIWSPY */
0837     dummy,                    /* SIOCGIWSPY */
0838     NULL,                     /* SIOCGIWTHRSPY */
0839     NULL,                     /* SIOCWIWTHRSPY */
0840     r8192_wx_set_wap,     /* SIOCSIWAP */
0841     r8192_wx_get_wap,         /* SIOCGIWAP */
0842     r8192_wx_set_mlme,                     /* MLME-- */
0843     dummy,                     /* SIOCGIWAPLIST -- deprecated */
0844     r8192_wx_set_scan,        /* SIOCSIWSCAN */
0845     r8192_wx_get_scan,        /* SIOCGIWSCAN */
0846     r8192_wx_set_essid,       /* SIOCSIWESSID */
0847     r8192_wx_get_essid,       /* SIOCGIWESSID */
0848     dummy,                    /* SIOCSIWNICKN */
0849     dummy,                    /* SIOCGIWNICKN */
0850     NULL,                     /* -- hole -- */
0851     NULL,                     /* -- hole -- */
0852     r8192_wx_set_rate,        /* SIOCSIWRATE */
0853     r8192_wx_get_rate,        /* SIOCGIWRATE */
0854     r8192_wx_set_rts,                    /* SIOCSIWRTS */
0855     r8192_wx_get_rts,                    /* SIOCGIWRTS */
0856     r8192_wx_set_frag,        /* SIOCSIWFRAG */
0857     r8192_wx_get_frag,        /* SIOCGIWFRAG */
0858     dummy,                    /* SIOCSIWTXPOW */
0859     dummy,                    /* SIOCGIWTXPOW */
0860     r8192_wx_set_retry,       /* SIOCSIWRETRY */
0861     r8192_wx_get_retry,       /* SIOCGIWRETRY */
0862     r8192_wx_set_enc,         /* SIOCSIWENCODE */
0863     r8192_wx_get_enc,         /* SIOCGIWENCODE */
0864     r8192_wx_set_power,                    /* SIOCSIWPOWER */
0865     r8192_wx_get_power,                    /* SIOCGIWPOWER */
0866     NULL,           /*---hole---*/
0867     NULL,           /*---hole---*/
0868     r8192_wx_set_gen_ie, /* NULL, */        /* SIOCSIWGENIE */
0869     NULL,           /* SIOCSIWGENIE */
0870 
0871     r8192_wx_set_auth,/* NULL, */           /* SIOCSIWAUTH */
0872     NULL,/* r8192_wx_get_auth, */ /* NULL, */   /* SIOCSIWAUTH */
0873     r8192_wx_set_enc_ext,           /* SIOCSIWENCODEEXT */
0874     NULL,/* r8192_wx_get_enc_ext, *//* NULL, */         /* SIOCSIWENCODEEXT */
0875     NULL,           /* SIOCSIWPMKSA */
0876     NULL,            /*---hole---*/
0877 
0878 };
0879 
0880 static const struct iw_priv_args r8192_private_args[] = {
0881     {
0882         SIOCIWFIRSTPRIV + 0x0,
0883         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
0884     },
0885     {
0886         SIOCIWFIRSTPRIV + 0x1,
0887         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
0888 
0889     },
0890     {
0891         SIOCIWFIRSTPRIV + 0x2,
0892         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
0893     },
0894     {
0895         SIOCIWFIRSTPRIV + 0x3,
0896         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
0897     }
0898 };
0899 
0900 static iw_handler r8192_private_handler[] = {
0901     r8192_wx_set_crcmon,
0902     r8192_wx_set_scan_type,
0903     r8192_wx_set_rawtx,
0904     r8192_wx_force_reset,
0905 };
0906 
0907 struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
0908 {
0909     struct r8192_priv *priv = ieee80211_priv(dev);
0910     struct ieee80211_device *ieee = priv->ieee80211;
0911     struct iw_statistics *wstats = &priv->wstats;
0912     int tmp_level = 0;
0913     int tmp_qual = 0;
0914     int tmp_noise = 0;
0915 
0916     if (ieee->state < IEEE80211_LINKED) {
0917         wstats->qual.qual = 0;
0918         wstats->qual.level = 0;
0919         wstats->qual.noise = 0;
0920         wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
0921         return wstats;
0922     }
0923 
0924     tmp_level = (&ieee->current_network)->stats.rssi;
0925     tmp_qual = (&ieee->current_network)->stats.signal;
0926     tmp_noise = (&ieee->current_network)->stats.noise;
0927 
0928     wstats->qual.level = tmp_level;
0929     wstats->qual.qual = tmp_qual;
0930     wstats->qual.noise = tmp_noise;
0931     wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
0932     return wstats;
0933 }
0934 
0935 const struct iw_handler_def  r8192_wx_handlers_def = {
0936     .standard = r8192_wx_handlers,
0937     .num_standard = ARRAY_SIZE(r8192_wx_handlers),
0938     .private = r8192_private_handler,
0939     .num_private = ARRAY_SIZE(r8192_private_handler),
0940     .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
0941     .get_wireless_stats = r8192_get_wireless_stats,
0942     .private_args = (struct iw_priv_args *)r8192_private_args,
0943 };