linux/drivers/staging/rtl8192u/r8192U_wx.c
<<
>>
Prefs
   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};
 944