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