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