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