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