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 thank 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        read_nic_byte(dev, addr, &data1);
 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 corresponding 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        /* Informative stuff (to choose between different interface) */
 359        __u32           throughput;     /* To give an idea... */
 360        /* In theory this value should be the maximum benchmarked
 361         * TCP/IP throughput, because with most of these devices the
 362         * bit rate is meaningless (overhead an co) to estimate how
 363         * fast the connection will go and pick the fastest one.
 364         * I suggest people to play with Netperf or any benchmark...
 365         */
 366
 367        /* NWID (or domain id) */
 368        __u32           min_nwid;       /* Minimal NWID we are able to set */
 369        __u32           max_nwid;       /* Maximal NWID we are able to set */
 370
 371        /* Old Frequency (backward compat - moved lower ) */
 372        __u16           old_num_channels;
 373        __u8            old_num_frequency;
 374
 375        /* Scan capabilities */
 376        __u8            scan_capa;
 377};
 378static int rtl8180_wx_get_range(struct net_device *dev,
 379                                struct iw_request_info *info,
 380                                union iwreq_data *wrqu, char *extra)
 381{
 382        struct iw_range *range = (struct iw_range *)extra;
 383        struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
 384        struct r8192_priv *priv = ieee80211_priv(dev);
 385        u16 val;
 386        int i;
 387
 388        wrqu->data.length = sizeof(*range);
 389        memset(range, 0, sizeof(*range));
 390
 391        /* Let's try to keep this struct in the same order as in
 392         * linux/include/wireless.h
 393         */
 394
 395        /* TODO: See what values we can set, and remove the ones we can't
 396         * set, or fill them with some default data.
 397         */
 398
 399        /* ~5 Mb/s real (802.11b) */
 400        range->throughput = 5 * 1000 * 1000;
 401
 402        // TODO: Not used in 802.11b?
 403//      range->min_nwid;        /* Minimal NWID we are able to set */
 404        // TODO: Not used in 802.11b?
 405//      range->max_nwid;        /* Maximal NWID we are able to set */
 406
 407        /* Old Frequency (backward compat - moved lower ) */
 408//      range->old_num_channels;
 409//      range->old_num_frequency;
 410//      range->old_freq[6]; /* Filler to keep "version" at the same offset */
 411        if(priv->rf_set_sens != NULL)
 412                range->sensitivity = priv->max_sens;    /* signal level threshold range */
 413
 414        range->max_qual.qual = 100;
 415        /* TODO: Find real max RSSI and stick here */
 416        range->max_qual.level = 0;
 417        range->max_qual.noise = -98;
 418        range->max_qual.updated = 7; /* Updated all three */
 419
 420        range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
 421        /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
 422        range->avg_qual.level = 20 + -98;
 423        range->avg_qual.noise = 0;
 424        range->avg_qual.updated = 7; /* Updated all three */
 425
 426        range->num_bitrates = RATE_COUNT;
 427
 428        for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
 429                range->bitrate[i] = rtl8180_rates[i];
 430        }
 431
 432        range->min_frag = MIN_FRAG_THRESHOLD;
 433        range->max_frag = MAX_FRAG_THRESHOLD;
 434
 435        range->min_pmp=0;
 436        range->max_pmp = 5000000;
 437        range->min_pmt = 0;
 438        range->max_pmt = 65535*1000;
 439        range->pmp_flags = IW_POWER_PERIOD;
 440        range->pmt_flags = IW_POWER_TIMEOUT;
 441        range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
 442
 443        range->we_version_compiled = WIRELESS_EXT;
 444        range->we_version_source = 16;
 445
 446//      range->retry_capa;      /* What retry options are supported */
 447//      range->retry_flags;     /* How to decode max/min retry limit */
 448//      range->r_time_flags;    /* How to decode max/min retry life */
 449//      range->min_retry;       /* Minimal number of retries */
 450//      range->max_retry;       /* Maximal number of retries */
 451//      range->min_r_time;      /* Minimal retry lifetime */
 452//      range->max_r_time;      /* Maximal retry lifetime */
 453
 454
 455        for (i = 0, val = 0; i < 14; i++) {
 456
 457                // Include only legal frequencies for some countries
 458                if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
 459                        range->freq[val].i = i + 1;
 460                        range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
 461                        range->freq[val].e = 1;
 462                        val++;
 463                } else {
 464                        // FIXME: do we need to set anything for channels
 465                        // we don't use ?
 466                }
 467
 468                if (val == IW_MAX_FREQUENCIES)
 469                break;
 470        }
 471        range->num_frequency = val;
 472        range->num_channels = val;
 473#if WIRELESS_EXT > 17
 474        range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
 475                          IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
 476#endif
 477        tmp->scan_capa = 0x01;
 478        return 0;
 479}
 480
 481
 482static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
 483                             union iwreq_data *wrqu, char *b)
 484{
 485        struct r8192_priv *priv = ieee80211_priv(dev);
 486        struct ieee80211_device *ieee = priv->ieee80211;
 487        int ret = 0;
 488
 489        if(!priv->up) return -ENETDOWN;
 490
 491        if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
 492                return -EAGAIN;
 493        if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
 494        {
 495                struct iw_scan_req *req = (struct iw_scan_req *)b;
 496                if (req->essid_len)
 497                {
 498                        //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
 499                        ieee->current_network.ssid_len = req->essid_len;
 500                        memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
 501                        //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
 502                }
 503        }
 504
 505        down(&priv->wx_sem);
 506        if(priv->ieee80211->state != IEEE80211_LINKED){
 507                priv->ieee80211->scanning = 0;
 508                ieee80211_softmac_scan_syncro(priv->ieee80211);
 509                ret = 0;
 510        }
 511        else
 512        ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
 513        up(&priv->wx_sem);
 514        return ret;
 515}
 516
 517
 518static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
 519                             union iwreq_data *wrqu, char *b)
 520{
 521
 522        int ret;
 523        struct r8192_priv *priv = ieee80211_priv(dev);
 524
 525        if(!priv->up) return -ENETDOWN;
 526
 527        down(&priv->wx_sem);
 528
 529        ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
 530
 531        up(&priv->wx_sem);
 532
 533        return ret;
 534}
 535
 536static int r8192_wx_set_essid(struct net_device *dev,
 537                              struct iw_request_info *a,
 538                              union iwreq_data *wrqu, char *b)
 539{
 540        struct r8192_priv *priv = ieee80211_priv(dev);
 541        int ret;
 542        down(&priv->wx_sem);
 543
 544        ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
 545
 546        up(&priv->wx_sem);
 547
 548        return ret;
 549}
 550
 551
 552
 553
 554static int r8192_wx_get_essid(struct net_device *dev,
 555                              struct iw_request_info *a,
 556                              union iwreq_data *wrqu, char *b)
 557{
 558        int ret;
 559        struct r8192_priv *priv = ieee80211_priv(dev);
 560
 561        down(&priv->wx_sem);
 562
 563        ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
 564
 565        up(&priv->wx_sem);
 566
 567        return ret;
 568}
 569
 570
 571static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
 572                             union iwreq_data *wrqu, char *b)
 573{
 574        int ret;
 575        struct r8192_priv *priv = ieee80211_priv(dev);
 576
 577        down(&priv->wx_sem);
 578
 579        ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
 580
 581        up(&priv->wx_sem);
 582        return ret;
 583}
 584
 585static int r8192_wx_get_name(struct net_device *dev,
 586                             struct iw_request_info *info,
 587                             union iwreq_data *wrqu, char *extra)
 588{
 589        struct r8192_priv *priv = ieee80211_priv(dev);
 590        return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
 591}
 592
 593
 594static int r8192_wx_set_frag(struct net_device *dev,
 595                             struct iw_request_info *info,
 596                             union iwreq_data *wrqu, char *extra)
 597{
 598        struct r8192_priv *priv = ieee80211_priv(dev);
 599
 600        if (wrqu->frag.disabled)
 601                priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
 602        else {
 603                if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
 604                    wrqu->frag.value > MAX_FRAG_THRESHOLD)
 605                        return -EINVAL;
 606
 607                priv->ieee80211->fts = wrqu->frag.value & ~0x1;
 608        }
 609
 610        return 0;
 611}
 612
 613
 614static int r8192_wx_get_frag(struct net_device *dev,
 615                             struct iw_request_info *info,
 616                             union iwreq_data *wrqu, char *extra)
 617{
 618        struct r8192_priv *priv = ieee80211_priv(dev);
 619
 620        wrqu->frag.value = priv->ieee80211->fts;
 621        wrqu->frag.fixed = 0;   /* no auto select */
 622        wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
 623
 624        return 0;
 625}
 626
 627
 628static int r8192_wx_set_wap(struct net_device *dev,
 629                         struct iw_request_info *info,
 630                         union iwreq_data *awrq,
 631                         char *extra)
 632{
 633
 634        int ret;
 635        struct r8192_priv *priv = ieee80211_priv(dev);
 636//        struct sockaddr *temp = (struct sockaddr *)awrq;
 637        down(&priv->wx_sem);
 638
 639        ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
 640
 641        up(&priv->wx_sem);
 642
 643        return ret;
 644
 645}
 646
 647
 648static int r8192_wx_get_wap(struct net_device *dev,
 649                            struct iw_request_info *info,
 650                            union iwreq_data *wrqu, char *extra)
 651{
 652        struct r8192_priv *priv = ieee80211_priv(dev);
 653
 654        return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
 655}
 656
 657
 658static int r8192_wx_get_enc(struct net_device *dev,
 659                            struct iw_request_info *info,
 660                            union iwreq_data *wrqu, char *key)
 661{
 662        struct r8192_priv *priv = ieee80211_priv(dev);
 663
 664        return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
 665}
 666
 667static int r8192_wx_set_enc(struct net_device *dev,
 668                            struct iw_request_info *info,
 669                            union iwreq_data *wrqu, char *key)
 670{
 671        struct r8192_priv *priv = ieee80211_priv(dev);
 672        struct ieee80211_device *ieee = priv->ieee80211;
 673        int ret;
 674
 675        //u32 TargetContent;
 676        u32 hwkey[4]={0,0,0,0};
 677        u8 mask=0xff;
 678        u32 key_idx=0;
 679        //u8 broadcast_addr[6] ={       0xff,0xff,0xff,0xff,0xff,0xff};
 680        u8 zero_addr[4][6] ={   {0x00,0x00,0x00,0x00,0x00,0x00},
 681                                {0x00,0x00,0x00,0x00,0x00,0x01},
 682                                {0x00,0x00,0x00,0x00,0x00,0x02},
 683                                {0x00,0x00,0x00,0x00,0x00,0x03} };
 684        int i;
 685
 686       if(!priv->up) return -ENETDOWN;
 687
 688        down(&priv->wx_sem);
 689
 690        RT_TRACE(COMP_SEC, "Setting SW wep key");
 691        ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
 692
 693        up(&priv->wx_sem);
 694
 695
 696
 697        //sometimes, the length is zero while we do not type key value
 698        if(wrqu->encoding.length!=0){
 699
 700                for(i=0 ; i<4 ; i++){
 701                        hwkey[i] |=  key[4*i+0]&mask;
 702                        if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
 703                        if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
 704                        hwkey[i] |= (key[4*i+1]&mask)<<8;
 705                        hwkey[i] |= (key[4*i+2]&mask)<<16;
 706                        hwkey[i] |= (key[4*i+3]&mask)<<24;
 707                }
 708
 709                #define CONF_WEP40  0x4
 710                #define CONF_WEP104 0x14
 711
 712                switch (wrqu->encoding.flags & IW_ENCODE_INDEX){
 713                case 0: key_idx = ieee->tx_keyidx; break;
 714                case 1: key_idx = 0; break;
 715                case 2: key_idx = 1; break;
 716                case 3: key_idx = 2; break;
 717                case 4: key_idx = 3; break;
 718                default: break;
 719                }
 720
 721                if(wrqu->encoding.length==0x5){
 722                                ieee->pairwise_key_type = KEY_TYPE_WEP40;
 723                        EnableHWSecurityConfig8192(dev);
 724
 725                        setKey( dev,
 726                                key_idx,                //EntryNo
 727                                key_idx,                //KeyIndex
 728                                KEY_TYPE_WEP40,         //KeyType
 729                                zero_addr[key_idx],
 730                                0,                      //DefaultKey
 731                                hwkey);                 //KeyContent
 732
 733                }
 734
 735                else if(wrqu->encoding.length==0xd){
 736                                ieee->pairwise_key_type = KEY_TYPE_WEP104;
 737                                EnableHWSecurityConfig8192(dev);
 738
 739                        setKey( dev,
 740                                key_idx,                //EntryNo
 741                                key_idx,                //KeyIndex
 742                                KEY_TYPE_WEP104,        //KeyType
 743                                zero_addr[key_idx],
 744                                0,                      //DefaultKey
 745                                hwkey);                 //KeyContent
 746
 747                }
 748                else printk("wrong type in WEP, not WEP40 and WEP104\n");
 749
 750        }
 751
 752        return ret;
 753}
 754
 755
 756static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
 757 iwreq_data *wrqu, char *p){
 758
 759        struct r8192_priv *priv = ieee80211_priv(dev);
 760        int *parms=(int *)p;
 761        int mode=parms[0];
 762
 763        priv->ieee80211->active_scan = mode;
 764
 765        return 1;
 766}
 767
 768
 769
 770static int r8192_wx_set_retry(struct net_device *dev,
 771                                struct iw_request_info *info,
 772                                union iwreq_data *wrqu, char *extra)
 773{
 774        struct r8192_priv *priv = ieee80211_priv(dev);
 775        int err = 0;
 776
 777        down(&priv->wx_sem);
 778
 779        if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
 780            wrqu->retry.disabled){
 781                err = -EINVAL;
 782                goto exit;
 783        }
 784        if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
 785                err = -EINVAL;
 786                goto exit;
 787        }
 788
 789        if(wrqu->retry.value > R8180_MAX_RETRY){
 790                err= -EINVAL;
 791                goto exit;
 792        }
 793        if (wrqu->retry.flags & IW_RETRY_MAX) {
 794                priv->retry_rts = wrqu->retry.value;
 795                DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
 796
 797        }else {
 798                priv->retry_data = wrqu->retry.value;
 799                DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
 800        }
 801
 802        /* FIXME !
 803         * We might try to write directly the TX config register
 804         * or to restart just the (R)TX process.
 805         * I'm unsure if whole reset is really needed
 806         */
 807
 808        rtl8192_commit(dev);
 809        /*
 810        if(priv->up){
 811                rtl8180_rtx_disable(dev);
 812                rtl8180_rx_enable(dev);
 813                rtl8180_tx_enable(dev);
 814
 815        }
 816        */
 817exit:
 818        up(&priv->wx_sem);
 819
 820        return err;
 821}
 822
 823static int r8192_wx_get_retry(struct net_device *dev,
 824                                struct iw_request_info *info,
 825                                union iwreq_data *wrqu, char *extra)
 826{
 827        struct r8192_priv *priv = ieee80211_priv(dev);
 828
 829
 830        wrqu->retry.disabled = 0; /* can't be disabled */
 831
 832        if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
 833            IW_RETRY_LIFETIME)
 834                return -EINVAL;
 835
 836        if (wrqu->retry.flags & IW_RETRY_MAX) {
 837                wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
 838                wrqu->retry.value = priv->retry_rts;
 839        } else {
 840                wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
 841                wrqu->retry.value = priv->retry_data;
 842        }
 843        //printk("returning %d",wrqu->retry.value);
 844
 845
 846        return 0;
 847}
 848
 849static int r8192_wx_get_sens(struct net_device *dev,
 850                                struct iw_request_info *info,
 851                                union iwreq_data *wrqu, char *extra)
 852{
 853        struct r8192_priv *priv = ieee80211_priv(dev);
 854        if(priv->rf_set_sens == NULL)
 855                return -1; /* we have not this support for this radio */
 856        wrqu->sens.value = priv->sens;
 857        return 0;
 858}
 859
 860
 861static int r8192_wx_set_sens(struct net_device *dev,
 862                                struct iw_request_info *info,
 863                                union iwreq_data *wrqu, char *extra)
 864{
 865
 866        struct r8192_priv *priv = ieee80211_priv(dev);
 867
 868        short err = 0;
 869        down(&priv->wx_sem);
 870        //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
 871        if(priv->rf_set_sens == NULL) {
 872                err= -1; /* we have not this support for this radio */
 873                goto exit;
 874        }
 875        if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
 876                priv->sens = wrqu->sens.value;
 877        else
 878                err= -EINVAL;
 879
 880exit:
 881        up(&priv->wx_sem);
 882
 883        return err;
 884}
 885
 886#if (WIRELESS_EXT >= 18)
 887//hw security need to reorganized.
 888static int r8192_wx_set_enc_ext(struct net_device *dev,
 889                                        struct iw_request_info *info,
 890                                        union iwreq_data *wrqu, char *extra)
 891{
 892        int ret=0;
 893        struct r8192_priv *priv = ieee80211_priv(dev);
 894        struct ieee80211_device *ieee = priv->ieee80211;
 895        //printk("===>%s()\n", __FUNCTION__);
 896
 897
 898        down(&priv->wx_sem);
 899        ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
 900
 901        {
 902                u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
 903                u8 zero[6] = {0};
 904                u32 key[4] = {0};
 905                struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 906                struct iw_point *encoding = &wrqu->encoding;
 907                u8 idx = 0, alg = 0, group = 0;
 908                if ((encoding->flags & IW_ENCODE_DISABLED) ||
 909                ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
 910                        goto end_hw_sec;
 911
 912                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;
 913                idx = encoding->flags & IW_ENCODE_INDEX;
 914                if (idx)
 915                        idx --;
 916                group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
 917
 918                if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40))
 919                {
 920                        if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
 921                                alg = KEY_TYPE_WEP104;
 922                        ieee->pairwise_key_type = alg;
 923                        EnableHWSecurityConfig8192(dev);
 924                }
 925                memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
 926
 927                if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
 928                {
 929
 930                        setKey( dev,
 931                                        idx,//EntryNo
 932                                        idx, //KeyIndex
 933                                        alg,  //KeyType
 934                                        zero, //MacAddr
 935                                        0,              //DefaultKey
 936                                        key);           //KeyContent
 937                }
 938                else if (group)
 939                {
 940                        ieee->group_key_type = alg;
 941                        setKey( dev,
 942                                        idx,//EntryNo
 943                                        idx, //KeyIndex
 944                                        alg,  //KeyType
 945                                        broadcast_addr, //MacAddr
 946                                        0,              //DefaultKey
 947                                        key);           //KeyContent
 948                }
 949                else //pairwise key
 950                {
 951                        setKey( dev,
 952                                        4,//EntryNo
 953                                        idx, //KeyIndex
 954                                        alg,  //KeyType
 955                                        (u8 *)ieee->ap_mac_addr, //MacAddr
 956                                        0,              //DefaultKey
 957                                        key);           //KeyContent
 958                }
 959
 960
 961        }
 962
 963end_hw_sec:
 964
 965        up(&priv->wx_sem);
 966        return ret;
 967
 968}
 969static int r8192_wx_set_auth(struct net_device *dev,
 970                                        struct iw_request_info *info,
 971                                        union iwreq_data *data, char *extra)
 972{
 973        int ret=0;
 974        //printk("====>%s()\n", __FUNCTION__);
 975        struct r8192_priv *priv = ieee80211_priv(dev);
 976        down(&priv->wx_sem);
 977        ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
 978        up(&priv->wx_sem);
 979        return ret;
 980}
 981
 982static int r8192_wx_set_mlme(struct net_device *dev,
 983                                        struct iw_request_info *info,
 984                                        union iwreq_data *wrqu, char *extra)
 985{
 986        //printk("====>%s()\n", __FUNCTION__);
 987
 988        int ret=0;
 989        struct r8192_priv *priv = ieee80211_priv(dev);
 990        down(&priv->wx_sem);
 991        ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
 992
 993        up(&priv->wx_sem);
 994        return ret;
 995}
 996#endif
 997static int r8192_wx_set_gen_ie(struct net_device *dev,
 998                                        struct iw_request_info *info,
 999                                        union iwreq_data *data, char *extra)
1000{
1001           //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
1002        int ret=0;
1003        struct r8192_priv *priv = ieee80211_priv(dev);
1004        down(&priv->wx_sem);
1005        ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
1006        up(&priv->wx_sem);
1007        //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
1008        return ret;
1009
1010
1011}
1012
1013static int dummy(struct net_device *dev, struct iw_request_info *a,
1014                 union iwreq_data *wrqu,char *b)
1015{
1016        return -1;
1017}
1018
1019
1020static iw_handler r8192_wx_handlers[] =
1021{
1022        NULL,                     /* SIOCSIWCOMMIT */
1023        r8192_wx_get_name,        /* SIOCGIWNAME */
1024        dummy,                    /* SIOCSIWNWID */
1025        dummy,                    /* SIOCGIWNWID */
1026        r8192_wx_set_freq,        /* SIOCSIWFREQ */
1027        r8192_wx_get_freq,        /* SIOCGIWFREQ */
1028        r8192_wx_set_mode,        /* SIOCSIWMODE */
1029        r8192_wx_get_mode,        /* SIOCGIWMODE */
1030        r8192_wx_set_sens,        /* SIOCSIWSENS */
1031        r8192_wx_get_sens,        /* SIOCGIWSENS */
1032        NULL,                     /* SIOCSIWRANGE */
1033        rtl8180_wx_get_range,     /* SIOCGIWRANGE */
1034        NULL,                     /* SIOCSIWPRIV */
1035        NULL,                     /* SIOCGIWPRIV */
1036        NULL,                     /* SIOCSIWSTATS */
1037        NULL,                     /* SIOCGIWSTATS */
1038        dummy,                    /* SIOCSIWSPY */
1039        dummy,                    /* SIOCGIWSPY */
1040        NULL,                     /* SIOCGIWTHRSPY */
1041        NULL,                     /* SIOCWIWTHRSPY */
1042        r8192_wx_set_wap,         /* SIOCSIWAP */
1043        r8192_wx_get_wap,         /* SIOCGIWAP */
1044#if (WIRELESS_EXT >= 18)
1045        r8192_wx_set_mlme,                     /* MLME-- */
1046#else
1047         NULL,
1048#endif
1049        dummy,                     /* SIOCGIWAPLIST -- deprecated */
1050        r8192_wx_set_scan,        /* SIOCSIWSCAN */
1051        r8192_wx_get_scan,        /* SIOCGIWSCAN */
1052        r8192_wx_set_essid,       /* SIOCSIWESSID */
1053        r8192_wx_get_essid,       /* SIOCGIWESSID */
1054        dummy,                    /* SIOCSIWNICKN */
1055        dummy,                    /* SIOCGIWNICKN */
1056        NULL,                     /* -- hole -- */
1057        NULL,                     /* -- hole -- */
1058        r8192_wx_set_rate,        /* SIOCSIWRATE */
1059        r8192_wx_get_rate,        /* SIOCGIWRATE */
1060        r8192_wx_set_rts,                    /* SIOCSIWRTS */
1061        r8192_wx_get_rts,                    /* SIOCGIWRTS */
1062        r8192_wx_set_frag,        /* SIOCSIWFRAG */
1063        r8192_wx_get_frag,        /* SIOCGIWFRAG */
1064        dummy,                    /* SIOCSIWTXPOW */
1065        dummy,                    /* SIOCGIWTXPOW */
1066        r8192_wx_set_retry,       /* SIOCSIWRETRY */
1067        r8192_wx_get_retry,       /* SIOCGIWRETRY */
1068        r8192_wx_set_enc,         /* SIOCSIWENCODE */
1069        r8192_wx_get_enc,         /* SIOCGIWENCODE */
1070        r8192_wx_set_power,                    /* SIOCSIWPOWER */
1071        r8192_wx_get_power,                    /* SIOCGIWPOWER */
1072        NULL,                   /*---hole---*/
1073        NULL,                   /*---hole---*/
1074        r8192_wx_set_gen_ie,//NULL,                     /* SIOCSIWGENIE */
1075        NULL,                   /* SIOCSIWGENIE */
1076
1077#if (WIRELESS_EXT >= 18)
1078        r8192_wx_set_auth,//NULL,                       /* SIOCSIWAUTH */
1079        NULL,//r8192_wx_get_auth,//NULL,                        /* SIOCSIWAUTH */
1080        r8192_wx_set_enc_ext,                   /* SIOCSIWENCODEEXT */
1081        NULL,//r8192_wx_get_enc_ext,//NULL,                     /* SIOCSIWENCODEEXT */
1082#else
1083        NULL,
1084        NULL,
1085        NULL,
1086        NULL,
1087#endif
1088        NULL,                   /* SIOCSIWPMKSA */
1089        NULL,                    /*---hole---*/
1090
1091};
1092
1093
1094static const struct iw_priv_args r8192_private_args[] = {
1095
1096        {
1097                SIOCIWFIRSTPRIV + 0x0,
1098                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1099        },
1100
1101        {
1102                SIOCIWFIRSTPRIV + 0x1,
1103                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1104
1105        },
1106        {
1107                SIOCIWFIRSTPRIV + 0x2,
1108                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1109        }
1110#ifdef JOHN_IOCTL
1111        ,
1112        {
1113                SIOCIWFIRSTPRIV + 0x3,
1114                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF"
1115        }
1116        ,
1117        {
1118                SIOCIWFIRSTPRIV + 0x4,
1119                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF"
1120        }
1121        ,
1122        {
1123                SIOCIWFIRSTPRIV + 0x5,
1124                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB"
1125        }
1126        ,
1127        {
1128                SIOCIWFIRSTPRIV + 0x6,
1129                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB"
1130        }
1131        ,
1132        {
1133                SIOCIWFIRSTPRIV + 0x7,
1134                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb"
1135        }
1136        ,
1137        {
1138                SIOCIWFIRSTPRIV + 0x8,
1139                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb"
1140        }
1141        ,
1142        {
1143                SIOCIWFIRSTPRIV + 0x9,
1144                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
1145        }
1146
1147#endif
1148        ,
1149        {
1150                SIOCIWFIRSTPRIV + 0x3,
1151                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1152
1153        }
1154
1155};
1156
1157
1158static iw_handler r8192_private_handler[] = {
1159//      r8192_wx_set_monitor,  /* SIOCIWFIRSTPRIV */
1160        r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
1161//      r8192_wx_set_forceassociate,
1162//      r8192_wx_set_beaconinterval,
1163//      r8192_wx_set_monitor_type,
1164        r8192_wx_set_scan_type,
1165        r8192_wx_set_rawtx,
1166#ifdef JOHN_IOCTL
1167        r8192_wx_read_regs,
1168        r8192_wx_write_regs,
1169        r8192_wx_read_bb,
1170        r8192_wx_write_bb,
1171        r8192_wx_read_nicb,
1172        r8192_wx_write_nicb,
1173        r8192_wx_get_ap_status,
1174#endif
1175        //r8192_wx_null,
1176        r8192_wx_force_reset,
1177};
1178
1179//#if WIRELESS_EXT >= 17
1180struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1181{
1182       struct r8192_priv *priv = ieee80211_priv(dev);
1183        struct ieee80211_device *ieee = priv->ieee80211;
1184        struct iw_statistics *wstats = &priv->wstats;
1185        int tmp_level = 0;
1186        int tmp_qual = 0;
1187        int tmp_noise = 0;
1188        if(ieee->state < IEEE80211_LINKED)
1189        {
1190                wstats->qual.qual = 0;
1191                wstats->qual.level = 0;
1192                wstats->qual.noise = 0;
1193                wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1194                return wstats;
1195        }
1196
1197       tmp_level = (&ieee->current_network)->stats.rssi;
1198        tmp_qual = (&ieee->current_network)->stats.signal;
1199        tmp_noise = (&ieee->current_network)->stats.noise;
1200        //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1201
1202        wstats->qual.level = tmp_level;
1203        wstats->qual.qual = tmp_qual;
1204        wstats->qual.noise = tmp_noise;
1205        wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM;
1206        return wstats;
1207}
1208//#endif
1209
1210
1211struct iw_handler_def  r8192_wx_handlers_def={
1212        .standard = r8192_wx_handlers,
1213        .num_standard = ARRAY_SIZE(r8192_wx_handlers),
1214        .private = r8192_private_handler,
1215        .num_private = ARRAY_SIZE(r8192_private_handler),
1216        .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1217#if WIRELESS_EXT >= 17
1218        .get_wireless_stats = r8192_get_wireless_stats,
1219#endif
1220        .private_args = (struct iw_priv_args *)r8192_private_args,
1221};
1222