linux/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7#define _IOCTL_LINUX_C_
   8
   9#include <linux/etherdevice.h>
  10#include <drv_types.h>
  11#include <rtw_debug.h>
  12#include <rtw_mp.h>
  13#include <linux/jiffies.h>
  14#include <linux/kernel.h>
  15
  16#define RTL_IOCTL_WPA_SUPPLICANT        (SIOCIWFIRSTPRIV+30)
  17
  18#define SCAN_ITEM_SIZE 768
  19#define MAX_CUSTOM_LEN 64
  20#define RATE_COUNT 4
  21
  22/*  combo scan */
  23#define WEXT_CSCAN_AMOUNT 9
  24#define WEXT_CSCAN_BUF_LEN              360
  25#define WEXT_CSCAN_HEADER               "CSCAN S\x01\x00\x00S\x00"
  26#define WEXT_CSCAN_HEADER_SIZE          12
  27#define WEXT_CSCAN_SSID_SECTION         'S'
  28#define WEXT_CSCAN_CHANNEL_SECTION      'C'
  29#define WEXT_CSCAN_NPROBE_SECTION       'N'
  30#define WEXT_CSCAN_ACTV_DWELL_SECTION   'A'
  31#define WEXT_CSCAN_PASV_DWELL_SECTION   'P'
  32#define WEXT_CSCAN_HOME_DWELL_SECTION   'H'
  33#define WEXT_CSCAN_TYPE_SECTION         'T'
  34
  35
  36extern u8 key_2char2num(u8 hch, u8 lch);
  37
  38static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
  39        6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
  40
  41static const char * const iw_operation_mode[] = {
  42        "Auto", "Ad-Hoc", "Managed",  "Master", "Repeater", "Secondary", "Monitor"
  43};
  44
  45static int hex2num_i(char c)
  46{
  47        if (c >= '0' && c <= '9')
  48                return c - '0';
  49        if (c >= 'a' && c <= 'f')
  50                return c - 'a' + 10;
  51        if (c >= 'A' && c <= 'F')
  52                return c - 'A' + 10;
  53        return -1;
  54}
  55
  56/**
  57 * hwaddr_aton - Convert ASCII string to MAC address
  58 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
  59 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
  60 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
  61 */
  62static int hwaddr_aton_i(const char *txt, u8 *addr)
  63{
  64        int i;
  65
  66        for (i = 0; i < 6; i++) {
  67                int a, b;
  68
  69                a = hex2num_i(*txt++);
  70                if (a < 0)
  71                        return -1;
  72                b = hex2num_i(*txt++);
  73                if (b < 0)
  74                        return -1;
  75                *addr++ = (a << 4) | b;
  76                if (i < 5 && *txt++ != ':')
  77                        return -1;
  78        }
  79
  80        return 0;
  81}
  82
  83void indicate_wx_scan_complete_event(struct adapter *padapter)
  84{
  85        union iwreq_data wrqu;
  86
  87        memset(&wrqu, 0, sizeof(union iwreq_data));
  88
  89        /* DBG_871X("+rtw_indicate_wx_scan_complete_event\n"); */
  90}
  91
  92
  93void rtw_indicate_wx_assoc_event(struct adapter *padapter)
  94{
  95        union iwreq_data wrqu;
  96        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
  97        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  98        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  99        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex*)(&(pmlmeinfo->network));
 100
 101        memset(&wrqu, 0, sizeof(union iwreq_data));
 102
 103        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 104
 105        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ==true)
 106                memcpy(wrqu.ap_addr.sa_data, pnetwork->MacAddress, ETH_ALEN);
 107        else
 108                memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
 109
 110        DBG_871X_LEVEL(_drv_always_, "assoc success\n");
 111}
 112
 113void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
 114{
 115        union iwreq_data wrqu;
 116
 117        memset(&wrqu, 0, sizeof(union iwreq_data));
 118
 119        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 120        eth_zero_addr(wrqu.ap_addr.sa_data);
 121}
 122
 123/*
 124uint    rtw_is_cckrates_included(u8 *rate)
 125{
 126                u32 i = 0;
 127
 128                while (rate[i]!= 0)
 129                {
 130                        if  ((((rate[i]) & 0x7f) == 2)  || (((rate[i]) & 0x7f) == 4) ||
 131                        (((rate[i]) & 0x7f) == 11)  || (((rate[i]) & 0x7f) == 22))
 132                        return true;
 133                        i++;
 134                }
 135
 136                return false;
 137}
 138
 139uint    rtw_is_cckratesonly_included(u8 *rate)
 140{
 141        u32 i = 0;
 142
 143        while (rate[i]!= 0)
 144        {
 145                        if  ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
 146                                (((rate[i]) & 0x7f) != 11)  && (((rate[i]) & 0x7f) != 22))
 147                        return false;
 148                        i++;
 149        }
 150
 151        return true;
 152}
 153*/
 154
 155static char *translate_scan(struct adapter *padapter,
 156                                struct iw_request_info* info, struct wlan_network *pnetwork,
 157                                char *start, char *stop)
 158{
 159        struct iw_event iwe;
 160        u16 cap;
 161        u32 ht_ielen = 0;
 162        char *custom = NULL;
 163        char *p;
 164        u16 max_rate = 0, rate, ht_cap =false, vht_cap = false;
 165        u32 i = 0;
 166        u8 bw_40MHz = 0, short_GI = 0;
 167        u16 mcs_rate = 0, vht_data_rate = 0;
 168        u8 ie_offset = (pnetwork->network.Reserved[0] == 2? 0:12);
 169        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 170        u8 ss, sq;
 171
 172        /*  AP MAC address  */
 173        iwe.cmd = SIOCGIWAP;
 174        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 175
 176        memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
 177        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
 178
 179        /* Add the ESSID */
 180        iwe.cmd = SIOCGIWESSID;
 181        iwe.u.data.flags = 1;
 182        iwe.u.data.length = min((u16)pnetwork->network.Ssid.SsidLength, (u16)32);
 183        start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
 184
 185        /* parsing HT_CAP_IE */
 186        if (pnetwork->network.Reserved[0] == 2) { /*  Probe Request */
 187                p = rtw_get_ie(&pnetwork->network.IEs[0], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength);
 188        } else {
 189                p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12);
 190        }
 191        if (p && ht_ielen>0) {
 192                struct rtw_ieee80211_ht_cap *pht_capie;
 193                ht_cap = true;
 194                pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
 195                memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2);
 196                bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0;
 197                short_GI = (le16_to_cpu(pht_capie->cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
 198        }
 199
 200        /* Add the protocol name */
 201        iwe.cmd = SIOCGIWNAME;
 202        if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates)) == true) {
 203                if (ht_cap == true)
 204                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
 205                else
 206                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
 207        } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates)) == true) {
 208                if (ht_cap == true)
 209                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
 210                else
 211                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
 212        } else {
 213                if (pnetwork->network.Configuration.DSConfig > 14) {
 214                        if (vht_cap == true)
 215                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11AC");
 216                        else if (ht_cap == true)
 217                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
 218                        else
 219                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
 220                } else {
 221                        if (ht_cap == true)
 222                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
 223                        else
 224                                snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
 225                }
 226        }
 227
 228        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
 229
 230          /* Add mode */
 231        if (pnetwork->network.Reserved[0] == 2) { /*  Probe Request */
 232                cap = 0;
 233        } else {
 234                __le16 le_tmp;
 235
 236                iwe.cmd = SIOCGIWMODE;
 237                memcpy((u8 *)&le_tmp, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
 238                cap = le16_to_cpu(le_tmp);
 239        }
 240
 241        if (cap & (WLAN_CAPABILITY_IBSS |WLAN_CAPABILITY_BSS)) {
 242                if (cap & WLAN_CAPABILITY_BSS)
 243                        iwe.u.mode = IW_MODE_MASTER;
 244                else
 245                        iwe.u.mode = IW_MODE_ADHOC;
 246
 247                start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
 248        }
 249
 250        if (pnetwork->network.Configuration.DSConfig<1 /*|| pnetwork->network.Configuration.DSConfig>14*/)
 251                pnetwork->network.Configuration.DSConfig = 1;
 252
 253         /* Add frequency/channel */
 254        iwe.cmd = SIOCGIWFREQ;
 255        iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
 256        iwe.u.freq.e = 1;
 257        iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
 258        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
 259
 260        /* Add encryption capability */
 261        iwe.cmd = SIOCGIWENCODE;
 262        if (cap & WLAN_CAPABILITY_PRIVACY)
 263                iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 264        else
 265                iwe.u.data.flags = IW_ENCODE_DISABLED;
 266        iwe.u.data.length = 0;
 267        start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
 268
 269        /*Add basic and extended rates */
 270        max_rate = 0;
 271        custom = kzalloc(MAX_CUSTOM_LEN, GFP_ATOMIC);
 272        if (!custom)
 273                return start;
 274        p = custom;
 275        p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
 276        while (pnetwork->network.SupportedRates[i]!= 0) {
 277                rate = pnetwork->network.SupportedRates[i]&0x7F;
 278                if (rate > max_rate)
 279                        max_rate = rate;
 280                p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
 281                              "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
 282                i++;
 283        }
 284
 285        if (vht_cap == true) {
 286                max_rate = vht_data_rate;
 287        } else if (ht_cap == true) {
 288                if (mcs_rate&0x8000) { /* MCS15 */
 289                        max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
 290                } else if (mcs_rate&0x0080) { /* MCS7 */
 291                        max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
 292                } else { /* default MCS7 */
 293                        /* DBG_871X("wx_get_scan, mcs_rate_bitmap = 0x%x\n", mcs_rate); */
 294                        max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
 295                }
 296
 297                max_rate = max_rate*2;/* Mbps/2; */
 298        }
 299
 300        iwe.cmd = SIOCGIWRATE;
 301        iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
 302        iwe.u.bitrate.value = max_rate * 500000;
 303        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
 304
 305        /* parsing WPA/WPA2 IE */
 306        if (pnetwork->network.Reserved[0] != 2) { /*  Probe Request */
 307                u8 *buf;
 308                u8 wpa_ie[255], rsn_ie[255];
 309                u16 wpa_len = 0, rsn_len = 0;
 310                u8 *p;
 311                sint out_len = 0;
 312                out_len =rtw_get_sec_ie(pnetwork->network.IEs , pnetwork->network.IELength, rsn_ie,&rsn_len, wpa_ie,&wpa_len);
 313                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid));
 314                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
 315
 316                buf = kzalloc(MAX_WPA_IE_LEN*2, GFP_KERNEL);
 317                if (!buf)
 318                        return start;
 319                if (wpa_len > 0) {
 320                        p =buf;
 321                        p += sprintf(p, "wpa_ie =");
 322                        for (i = 0; i < wpa_len; i++)
 323                                p += sprintf(p, "%02x", wpa_ie[i]);
 324
 325                        if (wpa_len > 100) {
 326                                printk("-----------------Len %d----------------\n", wpa_len);
 327                                for (i = 0; i < wpa_len; i++)
 328                                        printk("%02x ", wpa_ie[i]);
 329                                printk("\n");
 330                                printk("-----------------Len %d----------------\n", wpa_len);
 331                        }
 332
 333                        memset(&iwe, 0, sizeof(iwe));
 334                        iwe.cmd = IWEVCUSTOM;
 335                        iwe.u.data.length = strlen(buf);
 336                        start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 337
 338                        memset(&iwe, 0, sizeof(iwe));
 339                        iwe.cmd =IWEVGENIE;
 340                        iwe.u.data.length = wpa_len;
 341                        start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
 342                }
 343                if (rsn_len > 0) {
 344                        p = buf;
 345                        memset(buf, 0, MAX_WPA_IE_LEN*2);
 346                        p += sprintf(p, "rsn_ie =");
 347                        for (i = 0; i < rsn_len; i++)
 348                                p += sprintf(p, "%02x", rsn_ie[i]);
 349                        memset(&iwe, 0, sizeof(iwe));
 350                        iwe.cmd = IWEVCUSTOM;
 351                        iwe.u.data.length = strlen(buf);
 352                        start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 353
 354                        memset(&iwe, 0, sizeof(iwe));
 355                        iwe.cmd =IWEVGENIE;
 356                        iwe.u.data.length = rsn_len;
 357                        start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
 358                }
 359                kfree(buf);
 360        }
 361
 362        { /* parsing WPS IE */
 363                uint cnt = 0, total_ielen;
 364                u8 *wpsie_ptr = NULL;
 365                uint wps_ielen = 0;
 366
 367                u8 *ie_ptr;
 368                total_ielen = pnetwork->network.IELength - ie_offset;
 369
 370                if (pnetwork->network.Reserved[0] == 2) { /*  Probe Request */
 371                        ie_ptr = pnetwork->network.IEs;
 372                        total_ielen = pnetwork->network.IELength;
 373                } else {    /*  Beacon or Probe Respones */
 374                        ie_ptr = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
 375                        total_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
 376                }
 377
 378                while (cnt < total_ielen) {
 379                        if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen>2)) {
 380                                wpsie_ptr = &ie_ptr[cnt];
 381                                iwe.cmd =IWEVGENIE;
 382                                iwe.u.data.length = (u16)wps_ielen;
 383                                start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
 384                        }
 385                        cnt+=ie_ptr[cnt+1]+2; /* goto next */
 386                }
 387        }
 388
 389        /* Add quality statistics */
 390        iwe.cmd = IWEVQUAL;
 391        iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
 392        #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
 393                | IW_QUAL_NOISE_UPDATED
 394        #else
 395                | IW_QUAL_NOISE_INVALID
 396        #endif
 397        #ifdef CONFIG_SIGNAL_DISPLAY_DBM
 398                | IW_QUAL_DBM
 399        #endif
 400        ;
 401
 402        if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
 403                is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
 404                ss = padapter->recvpriv.signal_strength;
 405                sq = padapter->recvpriv.signal_qual;
 406        } else {
 407                ss = pnetwork->network.PhyInfo.SignalStrength;
 408                sq = pnetwork->network.PhyInfo.SignalQuality;
 409        }
 410
 411
 412        #ifdef CONFIG_SIGNAL_DISPLAY_DBM
 413        iwe.u.qual.level = (u8) translate_percentage_to_dbm(ss);/* dbm */
 414        #else
 415        #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING
 416        {
 417                /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
 418
 419                struct hal_com_data *pHal = GET_HAL_DATA(padapter);
 420
 421                iwe.u.qual.level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, ss);
 422        }
 423        #else
 424        iwe.u.qual.level = (u8)ss;/*  */
 425        #endif
 426        #endif
 427
 428        iwe.u.qual.qual = (u8)sq;   /*  signal quality */
 429
 430        #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
 431        {
 432                s16 tmp_noise = 0;
 433                rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&(pnetwork->network.Configuration.DSConfig), &(tmp_noise));
 434                iwe.u.qual.noise = tmp_noise ;
 435        }
 436        #else
 437        iwe.u.qual.noise = 0; /*  noise level */
 438        #endif
 439
 440        /* DBG_871X("iqual =%d, ilevel =%d, inoise =%d, iupdated =%d\n", iwe.u.qual.qual, iwe.u.qual.level , iwe.u.qual.noise, iwe.u.qual.updated); */
 441
 442        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
 443
 444        {
 445                u8 *buf;
 446                u8 *p, *pos;
 447
 448                buf = kzalloc(MAX_WPA_IE_LEN, GFP_KERNEL);
 449                if (!buf)
 450                        goto exit;
 451                p = buf;
 452                pos = pnetwork->network.Reserved;
 453                p += sprintf(p, "fm =%02X%02X", pos[1], pos[0]);
 454                memset(&iwe, 0, sizeof(iwe));
 455                iwe.cmd = IWEVCUSTOM;
 456                iwe.u.data.length = strlen(buf);
 457                start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 458                kfree(buf);
 459        }
 460exit:
 461        kfree(custom);
 462
 463        return start;
 464}
 465
 466static int wpa_set_auth_algs(struct net_device *dev, u32 value)
 467{
 468        struct adapter *padapter = (struct adapter *) rtw_netdev_priv(dev);
 469        int ret = 0;
 470
 471        if ((value & WLAN_AUTH_SHARED_KEY) && (value & WLAN_AUTH_OPEN)) {
 472                DBG_871X("wpa_set_auth_algs, WLAN_AUTH_SHARED_KEY and WLAN_AUTH_OPEN [value:0x%x]\n", value);
 473                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 474                padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
 475                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
 476        } else if (value & WLAN_AUTH_SHARED_KEY)        {
 477                DBG_871X("wpa_set_auth_algs, WLAN_AUTH_SHARED_KEY  [value:0x%x]\n", value);
 478                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 479
 480                padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
 481                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
 482        } else if (value & WLAN_AUTH_OPEN) {
 483                DBG_871X("wpa_set_auth_algs, WLAN_AUTH_OPEN\n");
 484                /* padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; */
 485                if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
 486                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
 487                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
 488                }
 489        } else if (value & WLAN_AUTH_LEAP) {
 490                DBG_871X("wpa_set_auth_algs, WLAN_AUTH_LEAP\n");
 491        } else {
 492                DBG_871X("wpa_set_auth_algs, error!\n");
 493                ret = -EINVAL;
 494        }
 495
 496        return ret;
 497
 498}
 499
 500static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
 501{
 502        int ret = 0;
 503        u32 wep_key_idx, wep_key_len, wep_total_len;
 504        struct ndis_802_11_wep   *pwep = NULL;
 505        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 506        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 507        struct security_priv *psecuritypriv = &padapter->securitypriv;
 508
 509        param->u.crypt.err = 0;
 510        param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
 511
 512        if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) {
 513                ret =  -EINVAL;
 514                goto exit;
 515        }
 516
 517        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
 518            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
 519            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
 520                if (param->u.crypt.idx >= WEP_KEYS ||
 521                    param->u.crypt.idx >= BIP_MAX_KEYID) {
 522                        ret = -EINVAL;
 523                        goto exit;
 524                }
 525        } else {
 526                {
 527                        ret = -EINVAL;
 528                        goto exit;
 529                }
 530        }
 531
 532        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
 533                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n"));
 534                DBG_871X("wpa_set_encryption, crypt.alg = WEP\n");
 535
 536                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 537                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
 538                padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
 539
 540                wep_key_idx = param->u.crypt.idx;
 541                wep_key_len = param->u.crypt.key_len;
 542
 543                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx));
 544                DBG_871X("(1)wep_key_idx =%d\n", wep_key_idx);
 545
 546                if (wep_key_idx > WEP_KEYS)
 547                        return -EINVAL;
 548
 549                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx));
 550
 551                if (wep_key_len > 0) {
 552                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
 553                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
 554                        pwep = rtw_malloc(wep_total_len);
 555                        if (pwep == NULL) {
 556                                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n"));
 557                                goto exit;
 558                        }
 559
 560                        memset(pwep, 0, wep_total_len);
 561
 562                        pwep->KeyLength = wep_key_len;
 563                        pwep->Length = wep_total_len;
 564
 565                        if (wep_key_len == 13) {
 566                                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
 567                                padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
 568                        }
 569                } else {
 570                        ret = -EINVAL;
 571                        goto exit;
 572                }
 573
 574                pwep->KeyIndex = wep_key_idx;
 575                pwep->KeyIndex |= 0x80000000;
 576
 577                memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
 578
 579                if (param->u.crypt.set_tx) {
 580                        DBG_871X("wep, set_tx = 1\n");
 581
 582                        if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
 583                                ret = -EOPNOTSUPP ;
 584                } else {
 585                        DBG_871X("wep, set_tx = 0\n");
 586
 587                        /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
 588                        /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to fw/cam */
 589
 590                        if (wep_key_idx >= WEP_KEYS) {
 591                                ret = -EOPNOTSUPP ;
 592                                goto exit;
 593                        }
 594
 595                        memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
 596                        psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength;
 597                        rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, true);
 598                }
 599
 600                goto exit;
 601        }
 602
 603        if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /*  802_1x */
 604                struct sta_info * psta,*pbcmc_sta;
 605                struct sta_priv * pstapriv = &padapter->stapriv;
 606
 607                if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
 608                        psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
 609                        if (psta == NULL) {
 610                                /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
 611                        } else {
 612                                /* Jeff: don't disable ieee8021x_blocked while clearing key */
 613                                if (strcmp(param->u.crypt.alg, "none") != 0)
 614                                        psta->ieee8021x_blocked = false;
 615
 616                                if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||
 617                                                (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
 618                                        psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
 619                                }
 620
 621                                if (param->u.crypt.set_tx == 1) { /* pairwise key */
 622                                        memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
 623
 624                                        if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
 625                                                /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
 626                                                memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
 627                                                memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
 628
 629                                                padapter->securitypriv.busetkipkey =false;
 630                                                /* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
 631                                        }
 632
 633                                        /* DEBUG_ERR((" param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
 634                                        DBG_871X(" ~~~~set sta key:unicastkey\n");
 635
 636                                        rtw_setstakey_cmd(padapter, psta, true, true);
 637                                } else { /* group key */
 638                                        if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
 639                                                memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
 640                                                /* only TKIP group key need to install this */
 641                                                if (param->u.crypt.key_len > 16) {
 642                                                        memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[16]), 8);
 643                                                        memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey,&(param->u.crypt.key[24]), 8);
 644                                                }
 645                                                padapter->securitypriv.binstallGrpkey = true;
 646                                                /* DEBUG_ERR((" param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
 647                                                DBG_871X(" ~~~~set sta key:groupkey\n");
 648
 649                                                padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
 650
 651                                                rtw_set_key(padapter,&padapter->securitypriv, param->u.crypt.idx, 1, true);
 652                                        } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
 653                                                /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
 654                                                /* save the IGTK key, length 16 bytes */
 655                                                memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
 656                                                /*printk("IGTK key below:\n");
 657                                                for (no = 0;no<16;no++)
 658                                                        printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
 659                                                printk("\n");*/
 660                                                padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
 661                                                padapter->securitypriv.binstallBIPkey = true;
 662                                                DBG_871X(" ~~~~set sta key:IGKT\n");
 663                                        }
 664                                }
 665                        }
 666
 667                        pbcmc_sta =rtw_get_bcmc_stainfo(padapter);
 668                        if (pbcmc_sta == NULL) {
 669                                /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
 670                        } else {
 671                                /* Jeff: don't disable ieee8021x_blocked while clearing key */
 672                                if (strcmp(param->u.crypt.alg, "none") != 0)
 673                                        pbcmc_sta->ieee8021x_blocked = false;
 674
 675                                if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled)||
 676                                                (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled)) {
 677                                        pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
 678                                }
 679                        }
 680                } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 681                        /* adhoc mode */
 682                }
 683        }
 684
 685exit:
 686
 687        kfree(pwep);
 688        return ret;
 689}
 690
 691static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
 692{
 693        u8 *buf = NULL, *pos = NULL;
 694        int group_cipher = 0, pairwise_cipher = 0;
 695        int ret = 0;
 696        u8 null_addr[]= {0, 0, 0, 0, 0, 0};
 697
 698        if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
 699                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
 700                if (pie == NULL)
 701                        return ret;
 702                else
 703                        return -EINVAL;
 704        }
 705
 706        if (ielen) {
 707                buf = rtw_zmalloc(ielen);
 708                if (buf == NULL) {
 709                        ret =  -ENOMEM;
 710                        goto exit;
 711                }
 712
 713                memcpy(buf, pie , ielen);
 714
 715                /* dump */
 716                {
 717                        int i;
 718                        DBG_871X("\n wpa_ie(length:%d):\n", ielen);
 719                        for (i = 0;i<ielen;i =i+8)
 720                                DBG_871X("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
 721                }
 722
 723                pos = buf;
 724                if (ielen < RSN_HEADER_LEN) {
 725                        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
 726                        ret  = -1;
 727                        goto exit;
 728                }
 729
 730                if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
 731                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 732                        padapter->securitypriv.ndisauthtype =Ndis802_11AuthModeWPAPSK;
 733                        memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
 734                }
 735
 736                if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
 737                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 738                        padapter->securitypriv.ndisauthtype =Ndis802_11AuthModeWPA2PSK;
 739                        memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
 740                }
 741
 742                if (group_cipher == 0)
 743                        group_cipher = WPA_CIPHER_NONE;
 744                if (pairwise_cipher == 0)
 745                        pairwise_cipher = WPA_CIPHER_NONE;
 746
 747                switch (group_cipher) {
 748                        case WPA_CIPHER_NONE:
 749                                padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
 750                                padapter->securitypriv.ndisencryptstatus =Ndis802_11EncryptionDisabled;
 751                                break;
 752                        case WPA_CIPHER_WEP40:
 753                                padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
 754                                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 755                                break;
 756                        case WPA_CIPHER_TKIP:
 757                                padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
 758                                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
 759                                break;
 760                        case WPA_CIPHER_CCMP:
 761                                padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
 762                                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
 763                                break;
 764                        case WPA_CIPHER_WEP104:
 765                                padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
 766                                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 767                                break;
 768                }
 769
 770                switch (pairwise_cipher) {
 771                        case WPA_CIPHER_NONE:
 772                                padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
 773                                padapter->securitypriv.ndisencryptstatus =Ndis802_11EncryptionDisabled;
 774                                break;
 775                        case WPA_CIPHER_WEP40:
 776                                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
 777                                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 778                                break;
 779                        case WPA_CIPHER_TKIP:
 780                                padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
 781                                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
 782                                break;
 783                        case WPA_CIPHER_CCMP:
 784                                padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
 785                                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
 786                                break;
 787                        case WPA_CIPHER_WEP104:
 788                                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
 789                                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
 790                                break;
 791                }
 792
 793                _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
 794                {/* set wps_ie */
 795                        u16 cnt = 0;
 796                        u8 eid, wps_oui[4]={0x0, 0x50, 0xf2, 0x04};
 797
 798                        while (cnt < ielen) {
 799                                eid = buf[cnt];
 800
 801                                if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
 802                                        DBG_871X("SET WPS_IE\n");
 803
 804                                        padapter->securitypriv.wps_ie_len = ((buf[cnt+1]+2) < MAX_WPS_IE_LEN) ? (buf[cnt+1]+2):MAX_WPS_IE_LEN;
 805
 806                                        memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
 807
 808                                        set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
 809
 810                                        cnt += buf[cnt+1]+2;
 811
 812                                        break;
 813                                } else {
 814                                        cnt += buf[cnt+1]+2; /* goto next */
 815                                }
 816                        }
 817                }
 818        }
 819
 820        /* TKIP and AES disallow multicast packets until installing group key */
 821        if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
 822                || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
 823                || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
 824                /* WPS open need to enable multicast */
 825                /*  check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true) */
 826                rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
 827
 828        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
 829                 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
 830                  pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
 831
 832exit:
 833
 834        kfree(buf);
 835
 836        return ret;
 837}
 838
 839static int rtw_wx_get_name(struct net_device *dev,
 840                             struct iw_request_info *info,
 841                             union iwreq_data *wrqu, char *extra)
 842{
 843        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 844        u32 ht_ielen = 0;
 845        char *p;
 846        u8 ht_cap =false, vht_cap =false;
 847        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 848        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
 849        NDIS_802_11_RATES_EX* prates = NULL;
 850
 851        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
 852
 853        if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
 854                /* parsing HT_CAP_IE */
 855                p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
 856                if (p && ht_ielen>0)
 857                        ht_cap = true;
 858
 859                prates = &pcur_bss->SupportedRates;
 860
 861                if (rtw_is_cckratesonly_included((u8 *)prates) == true) {
 862                        if (ht_cap == true)
 863                                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
 864                        else
 865                                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
 866                } else if ((rtw_is_cckrates_included((u8 *)prates)) == true) {
 867                        if (ht_cap == true)
 868                                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
 869                        else
 870                                snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
 871                } else {
 872                        if (pcur_bss->Configuration.DSConfig > 14) {
 873                                if (vht_cap == true)
 874                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11AC");
 875                                else if (ht_cap == true)
 876                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
 877                                else
 878                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
 879                        } else {
 880                                if (ht_cap == true)
 881                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
 882                                else
 883                                        snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
 884                        }
 885                }
 886        } else {
 887                /* prates = &padapter->registrypriv.dev_network.SupportedRates; */
 888                /* snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); */
 889                snprintf(wrqu->name, IFNAMSIZ, "unassociated");
 890        }
 891        return 0;
 892}
 893
 894static int rtw_wx_set_freq(struct net_device *dev,
 895                             struct iw_request_info *info,
 896                             union iwreq_data *wrqu, char *extra)
 897{
 898        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
 899
 900        return 0;
 901}
 902
 903static int rtw_wx_get_freq(struct net_device *dev,
 904                             struct iw_request_info *info,
 905                             union iwreq_data *wrqu, char *extra)
 906{
 907        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 908        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 909        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
 910
 911        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
 912                /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
 913                wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
 914                wrqu->freq.e = 1;
 915                wrqu->freq.i = pcur_bss->Configuration.DSConfig;
 916
 917        } else {
 918                wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
 919                wrqu->freq.e = 1;
 920                wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
 921        }
 922
 923        return 0;
 924}
 925
 926static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
 927                             union iwreq_data *wrqu, char *b)
 928{
 929        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 930        enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType ;
 931        int ret = 0;
 932
 933        if (_FAIL == rtw_pwr_wakeup(padapter)) {
 934                ret = -EPERM;
 935                goto exit;
 936        }
 937
 938        if (padapter->hw_init_completed ==false) {
 939                ret = -EPERM;
 940                goto exit;
 941        }
 942
 943        switch (wrqu->mode) {
 944                case IW_MODE_AUTO:
 945                        networkType = Ndis802_11AutoUnknown;
 946                        DBG_871X("set_mode = IW_MODE_AUTO\n");
 947                        break;
 948                case IW_MODE_ADHOC:
 949                        networkType = Ndis802_11IBSS;
 950                        DBG_871X("set_mode = IW_MODE_ADHOC\n");
 951                        break;
 952                case IW_MODE_MASTER:
 953                        networkType = Ndis802_11APMode;
 954                        DBG_871X("set_mode = IW_MODE_MASTER\n");
 955                        /* rtw_setopmode_cmd(padapter, networkType, true); */
 956                        break;
 957                case IW_MODE_INFRA:
 958                        networkType = Ndis802_11Infrastructure;
 959                        DBG_871X("set_mode = IW_MODE_INFRA\n");
 960                        break;
 961
 962                default :
 963                        ret = -EINVAL;
 964                        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported \n", iw_operation_mode[wrqu->mode]));
 965                        goto exit;
 966        }
 967
 968/*
 969        if (Ndis802_11APMode == networkType)
 970        {
 971                rtw_setopmode_cmd(padapter, networkType, true);
 972        }
 973        else
 974        {
 975                rtw_setopmode_cmd(padapter, Ndis802_11AutoUnknown, true);
 976        }
 977*/
 978
 979        if (rtw_set_802_11_infrastructure_mode(padapter, networkType) ==false) {
 980
 981                ret = -EPERM;
 982                goto exit;
 983
 984        }
 985
 986        rtw_setopmode_cmd(padapter, networkType, true);
 987
 988exit:
 989        return ret;
 990}
 991
 992static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
 993                             union iwreq_data *wrqu, char *b)
 994{
 995        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 996        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 997
 998        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
 999
1000        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1001                wrqu->mode = IW_MODE_INFRA;
1002        } else if  ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
1003                       (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
1004                wrqu->mode = IW_MODE_ADHOC;
1005        } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1006                wrqu->mode = IW_MODE_MASTER;
1007        } else {
1008                wrqu->mode = IW_MODE_AUTO;
1009        }
1010        return 0;
1011}
1012
1013
1014static int rtw_wx_set_pmkid(struct net_device *dev,
1015                             struct iw_request_info *a,
1016                             union iwreq_data *wrqu, char *extra)
1017{
1018        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1019        u8          j, blInserted = false;
1020        int         intReturn = false;
1021        struct security_priv *psecuritypriv = &padapter->securitypriv;
1022        struct iw_pmksa*  pPMK = (struct iw_pmksa*) extra;
1023        u8     strZeroMacAddress[ ETH_ALEN ] = { 0x00 };
1024        u8     strIssueBssid[ ETH_ALEN ] = { 0x00 };
1025
1026        /*
1027        There are the BSSID information in the bssid.sa_data array.
1028        If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information.
1029        If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver.
1030        If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver.
1031        */
1032
1033        memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
1034        if (pPMK->cmd == IW_PMKSA_ADD) {
1035                DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
1036                if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
1037                    return(intReturn);
1038                else
1039                    intReturn = true;
1040
1041                blInserted = false;
1042
1043                /* overwrite PMKID */
1044                for (j = 0 ; j<NUM_PMKID_CACHE; j++) {
1045                        if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
1046                                /*  BSSID is matched, the same AP => rewrite with new PMKID. */
1047                                DBG_871X("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
1048
1049                                memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
1050                                psecuritypriv->PMKIDList[ j ].bUsed = true;
1051                                psecuritypriv->PMKIDIndex = j+1;
1052                                blInserted = true;
1053                                break;
1054                        }
1055                }
1056
1057                if (!blInserted) {
1058                    /*  Find a new entry */
1059                    DBG_871X("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
1060                            psecuritypriv->PMKIDIndex);
1061
1062                    memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
1063                    memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
1064
1065                    psecuritypriv->PMKIDList[ psecuritypriv->PMKIDIndex ].bUsed = true;
1066                    psecuritypriv->PMKIDIndex++ ;
1067                    if (psecuritypriv->PMKIDIndex == 16)
1068                        psecuritypriv->PMKIDIndex = 0;
1069                }
1070        } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
1071                DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
1072                intReturn = true;
1073                for (j = 0 ; j<NUM_PMKID_CACHE; j++) {
1074                        if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
1075                                /*  BSSID is matched, the same AP => Remove this PMKID information and reset it. */
1076                                eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
1077                                psecuritypriv->PMKIDList[ j ].bUsed = false;
1078                                break;
1079                        }
1080                }
1081        } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
1082            DBG_871X("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
1083            memset(&psecuritypriv->PMKIDList[ 0 ], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
1084            psecuritypriv->PMKIDIndex = 0;
1085            intReturn = true;
1086        }
1087        return intReturn;
1088}
1089
1090static int rtw_wx_get_sens(struct net_device *dev,
1091                             struct iw_request_info *info,
1092                             union iwreq_data *wrqu, char *extra)
1093{
1094        {
1095                wrqu->sens.value = 0;
1096                wrqu->sens.fixed = 0;   /* no auto select */
1097                wrqu->sens.disabled = 1;
1098        }
1099        return 0;
1100}
1101
1102static int rtw_wx_get_range(struct net_device *dev,
1103                                struct iw_request_info *info,
1104                                union iwreq_data *wrqu, char *extra)
1105{
1106        struct iw_range *range = (struct iw_range *)extra;
1107        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1108        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1109
1110        u16 val;
1111        int i;
1112
1113        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
1114
1115        wrqu->data.length = sizeof(*range);
1116        memset(range, 0, sizeof(*range));
1117
1118        /* Let's try to keep this struct in the same order as in
1119         * linux/include/wireless.h
1120         */
1121
1122        /* TODO: See what values we can set, and remove the ones we can't
1123         * set, or fill them with some default data.
1124         */
1125
1126        /* ~5 Mb/s real (802.11b) */
1127        range->throughput = 5 * 1000 * 1000;
1128
1129        /* signal level threshold range */
1130
1131        /* percent values between 0 and 100. */
1132        range->max_qual.qual = 100;
1133        range->max_qual.level = 100;
1134        range->max_qual.noise = 100;
1135        range->max_qual.updated = 7; /* Updated all three */
1136
1137
1138        range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
1139        /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
1140        range->avg_qual.level = 256 - 78;
1141        range->avg_qual.noise = 0;
1142        range->avg_qual.updated = 7; /* Updated all three */
1143
1144        range->num_bitrates = RATE_COUNT;
1145
1146        for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
1147                range->bitrate[i] = rtw_rates[i];
1148
1149        range->min_frag = MIN_FRAG_THRESHOLD;
1150        range->max_frag = MAX_FRAG_THRESHOLD;
1151
1152        range->pm_capa = 0;
1153
1154        range->we_version_compiled = WIRELESS_EXT;
1155        range->we_version_source = 16;
1156
1157        for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
1158
1159                /*  Include only legal frequencies for some countries */
1160                if (pmlmeext->channel_set[i].ChannelNum != 0) {
1161                        range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
1162                        range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
1163                        range->freq[val].e = 1;
1164                        val++;
1165                }
1166
1167                if (val == IW_MAX_FREQUENCIES)
1168                        break;
1169        }
1170
1171        range->num_channels = val;
1172        range->num_frequency = val;
1173
1174/*  Commented by Albert 2009/10/13 */
1175/*  The following code will proivde the security capability to network manager. */
1176/*  If the driver doesn't provide this capability to network manager, */
1177/*  the WPA/WPA2 routers can't be choosen in the network manager. */
1178
1179/*
1180#define IW_SCAN_CAPA_NONE               0x00
1181#define IW_SCAN_CAPA_ESSID              0x01
1182#define IW_SCAN_CAPA_BSSID              0x02
1183#define IW_SCAN_CAPA_CHANNEL    0x04
1184#define IW_SCAN_CAPA_MODE               0x08
1185#define IW_SCAN_CAPA_RATE               0x10
1186#define IW_SCAN_CAPA_TYPE               0x20
1187#define IW_SCAN_CAPA_TIME               0x40
1188*/
1189
1190        range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
1191                          IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
1192
1193        range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |IW_SCAN_CAPA_BSSID|
1194                                        IW_SCAN_CAPA_CHANNEL|IW_SCAN_CAPA_MODE|IW_SCAN_CAPA_RATE;
1195
1196        return 0;
1197}
1198
1199/* set bssid flow */
1200/* s1. rtw_set_802_11_infrastructure_mode() */
1201/* s2. rtw_set_802_11_authentication_mode() */
1202/* s3. set_802_11_encryption_mode() */
1203/* s4. rtw_set_802_11_bssid() */
1204static int rtw_wx_set_wap(struct net_device *dev,
1205                         struct iw_request_info *info,
1206                         union iwreq_data *awrq,
1207                         char *extra)
1208{
1209        uint ret = 0;
1210        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1211        struct sockaddr *temp = (struct sockaddr *)awrq;
1212        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1213        struct list_head        *phead;
1214        u8 *dst_bssid, *src_bssid;
1215        struct __queue  *queue  = &(pmlmepriv->scanned_queue);
1216        struct  wlan_network    *pnetwork = NULL;
1217        enum NDIS_802_11_AUTHENTICATION_MODE    authmode;
1218
1219        rtw_ps_deny(padapter, PS_DENY_JOIN);
1220        if (_FAIL == rtw_pwr_wakeup(padapter)) {
1221                ret = -1;
1222                goto exit;
1223        }
1224
1225        if (!padapter->bup) {
1226                ret = -1;
1227                goto exit;
1228        }
1229
1230
1231        if (temp->sa_family != ARPHRD_ETHER) {
1232                ret = -EINVAL;
1233                goto exit;
1234        }
1235
1236        authmode = padapter->securitypriv.ndisauthtype;
1237        spin_lock_bh(&queue->lock);
1238        phead = get_list_head(queue);
1239        pmlmepriv->pscanned = get_next(phead);
1240
1241        while (1) {
1242                if (phead == pmlmepriv->pscanned)
1243                        break;
1244
1245                pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
1246
1247                pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1248
1249                dst_bssid = pnetwork->network.MacAddress;
1250
1251                src_bssid = temp->sa_data;
1252
1253                if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
1254                        if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
1255                                ret = -1;
1256                                spin_unlock_bh(&queue->lock);
1257                                goto exit;
1258                        }
1259                                break;
1260                }
1261
1262        }
1263        spin_unlock_bh(&queue->lock);
1264
1265        rtw_set_802_11_authentication_mode(padapter, authmode);
1266        /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1267        if (rtw_set_802_11_bssid(padapter, temp->sa_data) == false) {
1268                ret = -1;
1269                goto exit;
1270        }
1271
1272exit:
1273
1274        rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
1275
1276        return ret;
1277}
1278
1279static int rtw_wx_get_wap(struct net_device *dev,
1280                            struct iw_request_info *info,
1281                            union iwreq_data *wrqu, char *extra)
1282{
1283
1284        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1285        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1286        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1287
1288        wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1289
1290        eth_zero_addr(wrqu->ap_addr.sa_data);
1291
1292        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
1293
1294        if  (((check_fwstate(pmlmepriv, _FW_LINKED)) == true) ||
1295                        ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) ||
1296                        ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true)) {
1297                memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
1298        } else {
1299                eth_zero_addr(wrqu->ap_addr.sa_data);
1300        }
1301
1302        return 0;
1303}
1304
1305static int rtw_wx_set_mlme(struct net_device *dev,
1306                             struct iw_request_info *info,
1307                             union iwreq_data *wrqu, char *extra)
1308{
1309        int ret = 0;
1310        u16 reason;
1311        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1312        struct iw_mlme *mlme = (struct iw_mlme *) extra;
1313
1314
1315        if (mlme == NULL)
1316                return -1;
1317
1318        DBG_871X("%s\n", __func__);
1319
1320        reason = mlme->reason_code;
1321
1322        DBG_871X("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
1323
1324        switch (mlme->cmd) {
1325        case IW_MLME_DEAUTH:
1326                if (!rtw_set_802_11_disassociate(padapter))
1327                        ret = -1;
1328                break;
1329        case IW_MLME_DISASSOC:
1330                if (!rtw_set_802_11_disassociate(padapter))
1331                        ret = -1;
1332                break;
1333        default:
1334                return -EOPNOTSUPP;
1335        }
1336
1337        return ret;
1338}
1339
1340static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
1341                             union iwreq_data *wrqu, char *extra)
1342{
1343        u8 _status = false;
1344        int ret = 0;
1345        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1346        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1347        struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1348        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
1349
1350        #ifdef DBG_IOCTL
1351        DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__);
1352        #endif
1353
1354        rtw_ps_deny(padapter, PS_DENY_SCAN);
1355        if (_FAIL == rtw_pwr_wakeup(padapter)) {
1356                ret = -1;
1357                goto exit;
1358        }
1359
1360        if (padapter->bDriverStopped) {
1361                DBG_871X("bDriverStopped =%d\n", padapter->bDriverStopped);
1362                ret = -1;
1363                goto exit;
1364        }
1365
1366        if (!padapter->bup) {
1367                ret = -1;
1368                goto exit;
1369        }
1370
1371        if (padapter->hw_init_completed ==false) {
1372                ret = -1;
1373                goto exit;
1374        }
1375
1376        /*  When Busy Traffic, driver do not site survey. So driver return success. */
1377        /*  wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
1378        /*  modify by thomas 2011-02-22. */
1379        if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1380                indicate_wx_scan_complete_event(padapter);
1381                goto exit;
1382        }
1383
1384        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) {
1385                indicate_wx_scan_complete_event(padapter);
1386                goto exit;
1387        }
1388
1389        memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
1390
1391        if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1392                struct iw_scan_req *req = (struct iw_scan_req *)extra;
1393
1394                if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1395                        int len = min((int)req->essid_len, IW_ESSID_MAX_SIZE);
1396
1397                        memcpy(ssid[0].Ssid, req->essid, len);
1398                        ssid[0].SsidLength = len;
1399
1400                        DBG_871X("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
1401
1402                        spin_lock_bh(&pmlmepriv->lock);
1403
1404                        _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
1405
1406                        spin_unlock_bh(&pmlmepriv->lock);
1407
1408                } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
1409                        DBG_871X("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
1410                }
1411
1412        } else if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE
1413                && !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
1414                int len = wrqu->data.length -WEXT_CSCAN_HEADER_SIZE;
1415                char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
1416                char section;
1417                char sec_len;
1418                int ssid_index = 0;
1419
1420                /* DBG_871X("%s COMBO_SCAN header is recognized\n", __func__); */
1421
1422                while (len >= 1) {
1423                        section = *(pos++); len-= 1;
1424
1425                        switch (section) {
1426                                case WEXT_CSCAN_SSID_SECTION:
1427                                        /* DBG_871X("WEXT_CSCAN_SSID_SECTION\n"); */
1428                                        if (len < 1) {
1429                                                len = 0;
1430                                                break;
1431                                        }
1432
1433                                        sec_len = *(pos++); len-= 1;
1434
1435                                        if (sec_len>0 && sec_len<=len) {
1436                                                ssid[ssid_index].SsidLength = sec_len;
1437                                                memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength);
1438                                                /* DBG_871X("%s COMBO_SCAN with specific ssid:%s, %d\n", __func__ */
1439                                                /*      , ssid[ssid_index].Ssid, ssid[ssid_index].SsidLength); */
1440                                                ssid_index++;
1441                                        }
1442
1443                                        pos+=sec_len; len-=sec_len;
1444                                        break;
1445
1446
1447                                case WEXT_CSCAN_CHANNEL_SECTION:
1448                                        /* DBG_871X("WEXT_CSCAN_CHANNEL_SECTION\n"); */
1449                                        pos+= 1; len-= 1;
1450                                        break;
1451                                case WEXT_CSCAN_ACTV_DWELL_SECTION:
1452                                        /* DBG_871X("WEXT_CSCAN_ACTV_DWELL_SECTION\n"); */
1453                                        pos+=2; len-=2;
1454                                        break;
1455                                case WEXT_CSCAN_PASV_DWELL_SECTION:
1456                                        /* DBG_871X("WEXT_CSCAN_PASV_DWELL_SECTION\n"); */
1457                                        pos+=2; len-=2;
1458                                        break;
1459                                case WEXT_CSCAN_HOME_DWELL_SECTION:
1460                                        /* DBG_871X("WEXT_CSCAN_HOME_DWELL_SECTION\n"); */
1461                                        pos+=2; len-=2;
1462                                        break;
1463                                case WEXT_CSCAN_TYPE_SECTION:
1464                                        /* DBG_871X("WEXT_CSCAN_TYPE_SECTION\n"); */
1465                                        pos+= 1; len-= 1;
1466                                        break;
1467                                default:
1468                                        /* DBG_871X("Unknown CSCAN section %c\n", section); */
1469                                        len = 0; /*  stop parsing */
1470                        }
1471                        /* DBG_871X("len:%d\n", len); */
1472
1473                }
1474
1475                /* jeff: it has still some scan paramater to parse, we only do this now... */
1476                _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
1477
1478        } else {
1479                _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1480        }
1481
1482        if (_status == false)
1483                ret = -1;
1484
1485exit:
1486
1487        rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
1488
1489        #ifdef DBG_IOCTL
1490        DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
1491        #endif
1492
1493        return ret;
1494}
1495
1496static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
1497                             union iwreq_data *wrqu, char *extra)
1498{
1499        struct list_head                                        *plist, *phead;
1500        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1501        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1502        struct __queue                          *queue  = &(pmlmepriv->scanned_queue);
1503        struct  wlan_network    *pnetwork = NULL;
1504        char *ev = extra;
1505        char *stop = ev + wrqu->data.length;
1506        u32 ret = 0;
1507        sint wait_status;
1508
1509        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
1510        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
1511
1512        #ifdef DBG_IOCTL
1513        DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__);
1514        #endif
1515
1516        if (adapter_to_pwrctl(padapter)->brfoffbyhw && padapter->bDriverStopped) {
1517                ret = -EINVAL;
1518                goto exit;
1519        }
1520
1521        wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
1522
1523        if (check_fwstate(pmlmepriv, wait_status))
1524                return -EAGAIN;
1525
1526        spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1527
1528        phead = get_list_head(queue);
1529        plist = get_next(phead);
1530
1531        while (1) {
1532                if (phead == plist)
1533                        break;
1534
1535                if ((stop - ev) < SCAN_ITEM_SIZE) {
1536                        ret = -E2BIG;
1537                        break;
1538                }
1539
1540                pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1541
1542                /* report network only if the current channel set contains the channel to which this network belongs */
1543                if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
1544                        && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == true
1545                        && true == rtw_validate_ssid(&(pnetwork->network.Ssid))) {
1546
1547                        ev =translate_scan(padapter, a, pnetwork, ev, stop);
1548                }
1549
1550                plist = get_next(plist);
1551
1552        }
1553
1554        spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1555
1556        wrqu->data.length = ev-extra;
1557        wrqu->data.flags = 0;
1558
1559exit:
1560
1561        #ifdef DBG_IOCTL
1562        DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
1563        #endif
1564
1565        return ret ;
1566
1567}
1568
1569/* set ssid flow */
1570/* s1. rtw_set_802_11_infrastructure_mode() */
1571/* s2. set_802_11_authenticaion_mode() */
1572/* s3. set_802_11_encryption_mode() */
1573/* s4. rtw_set_802_11_ssid() */
1574static int rtw_wx_set_essid(struct net_device *dev,
1575                              struct iw_request_info *a,
1576                              union iwreq_data *wrqu, char *extra)
1577{
1578        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1579        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1580        struct __queue *queue = &pmlmepriv->scanned_queue;
1581        struct list_head *phead;
1582        struct wlan_network *pnetwork = NULL;
1583        enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1584        struct ndis_802_11_ssid ndis_ssid;
1585        u8 *dst_ssid, *src_ssid;
1586
1587        uint ret = 0, len;
1588
1589        #ifdef DBG_IOCTL
1590        DBG_871X("DBG_IOCTL %s:%d\n", __func__, __LINE__);
1591        #endif
1592
1593        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1594                 ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
1595
1596        rtw_ps_deny(padapter, PS_DENY_JOIN);
1597        if (_FAIL == rtw_pwr_wakeup(padapter)) {
1598                ret = -1;
1599                goto exit;
1600        }
1601
1602        if (!padapter->bup) {
1603                ret = -1;
1604                goto exit;
1605        }
1606
1607        if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
1608                ret = -E2BIG;
1609                goto exit;
1610        }
1611
1612        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1613                ret = -1;
1614                goto exit;
1615        }
1616
1617        authmode = padapter->securitypriv.ndisauthtype;
1618        DBG_871X("=>%s\n", __func__);
1619        if (wrqu->essid.flags && wrqu->essid.length) {
1620                len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
1621
1622                if (wrqu->essid.length != 33)
1623                        DBG_871X("ssid =%s, len =%d\n", extra, wrqu->essid.length);
1624
1625                memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
1626                ndis_ssid.SsidLength = len;
1627                memcpy(ndis_ssid.Ssid, extra, len);
1628                src_ssid = ndis_ssid.Ssid;
1629
1630                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
1631                spin_lock_bh(&queue->lock);
1632                phead = get_list_head(queue);
1633                pmlmepriv->pscanned = get_next(phead);
1634
1635                while (1) {
1636                        if (phead == pmlmepriv->pscanned) {
1637                                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_warning_,
1638                                         ("rtw_wx_set_essid: scan_q is empty, set ssid to check if scanning again!\n"));
1639
1640                                break;
1641                        }
1642
1643                        pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
1644
1645                        pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1646
1647                        dst_ssid = pnetwork->network.Ssid.Ssid;
1648
1649                        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1650                                 ("rtw_wx_set_essid: dst_ssid =%s\n",
1651                                  pnetwork->network.Ssid.Ssid));
1652
1653                        if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) &&
1654                                (pnetwork->network.Ssid.SsidLength ==ndis_ssid.SsidLength)) {
1655                                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1656                                         ("rtw_wx_set_essid: find match, set infra mode\n"));
1657
1658                                if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
1659                                        if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
1660                                                continue;
1661                                }
1662
1663                                if (rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode) == false) {
1664                                        ret = -1;
1665                                        spin_unlock_bh(&queue->lock);
1666                                        goto exit;
1667                                }
1668
1669                                break;
1670                        }
1671                }
1672                spin_unlock_bh(&queue->lock);
1673                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
1674                         ("set ssid: set_802_11_auth. mode =%d\n", authmode));
1675                rtw_set_802_11_authentication_mode(padapter, authmode);
1676                /* set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
1677                if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == false) {
1678                        ret = -1;
1679                        goto exit;
1680                }
1681        }
1682
1683exit:
1684
1685        rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
1686
1687        DBG_871X("<=%s, ret %d\n", __func__, ret);
1688
1689        #ifdef DBG_IOCTL
1690        DBG_871X("DBG_IOCTL %s:%d return %d\n", __func__, __LINE__, ret);
1691        #endif
1692
1693        return ret;
1694}
1695
1696static int rtw_wx_get_essid(struct net_device *dev,
1697                              struct iw_request_info *a,
1698                              union iwreq_data *wrqu, char *extra)
1699{
1700        u32 len, ret = 0;
1701        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1702        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1703        struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1704
1705        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
1706
1707        if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
1708              (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
1709                len = pcur_bss->Ssid.SsidLength;
1710
1711                wrqu->essid.length = len;
1712
1713                memcpy(extra, pcur_bss->Ssid.Ssid, len);
1714
1715                wrqu->essid.flags = 1;
1716        } else {
1717                ret = -1;
1718                goto exit;
1719        }
1720
1721exit:
1722        return ret;
1723}
1724
1725static int rtw_wx_set_rate(struct net_device *dev,
1726                              struct iw_request_info *a,
1727                              union iwreq_data *wrqu, char *extra)
1728{
1729        int     i, ret = 0;
1730        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1731        u8 datarates[NumRates];
1732        u32 target_rate = wrqu->bitrate.value;
1733        u32 fixed = wrqu->bitrate.fixed;
1734        u32 ratevalue = 0;
1735        u8 mpdatarate[NumRates]={11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
1736
1737        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
1738        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
1739
1740        if (target_rate == -1) {
1741                ratevalue = 11;
1742                goto set_rate;
1743        }
1744        target_rate = target_rate/100000;
1745
1746        switch (target_rate) {
1747                case 10:
1748                        ratevalue = 0;
1749                        break;
1750                case 20:
1751                        ratevalue = 1;
1752                        break;
1753                case 55:
1754                        ratevalue = 2;
1755                        break;
1756                case 60:
1757                        ratevalue = 3;
1758                        break;
1759                case 90:
1760                        ratevalue = 4;
1761                        break;
1762                case 110:
1763                        ratevalue = 5;
1764                        break;
1765                case 120:
1766                        ratevalue = 6;
1767                        break;
1768                case 180:
1769                        ratevalue = 7;
1770                        break;
1771                case 240:
1772                        ratevalue = 8;
1773                        break;
1774                case 360:
1775                        ratevalue = 9;
1776                        break;
1777                case 480:
1778                        ratevalue = 10;
1779                        break;
1780                case 540:
1781                        ratevalue = 11;
1782                        break;
1783                default:
1784                        ratevalue = 11;
1785                        break;
1786        }
1787
1788set_rate:
1789
1790        for (i = 0; i<NumRates; i++) {
1791                if (ratevalue ==mpdatarate[i]) {
1792                        datarates[i] = mpdatarate[i];
1793                        if (fixed == 0)
1794                                break;
1795                } else {
1796                        datarates[i] = 0xff;
1797                }
1798
1799                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
1800        }
1801
1802        if (rtw_setdatarate_cmd(padapter, datarates) != _SUCCESS) {
1803                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("rtw_wx_set_rate Fail!!!\n"));
1804                ret = -1;
1805        }
1806        return ret;
1807}
1808
1809static int rtw_wx_get_rate(struct net_device *dev,
1810                             struct iw_request_info *info,
1811                             union iwreq_data *wrqu, char *extra)
1812{
1813        u16 max_rate = 0;
1814
1815        max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
1816
1817        if (max_rate == 0)
1818                return -EPERM;
1819
1820        wrqu->bitrate.fixed = 0;        /* no auto select */
1821        wrqu->bitrate.value = max_rate * 100000;
1822
1823        return 0;
1824}
1825
1826static int rtw_wx_set_rts(struct net_device *dev,
1827                             struct iw_request_info *info,
1828                             union iwreq_data *wrqu, char *extra)
1829{
1830        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1831
1832        if (wrqu->rts.disabled)
1833                padapter->registrypriv.rts_thresh = 2347;
1834        else {
1835                if (wrqu->rts.value < 0 ||
1836                    wrqu->rts.value > 2347)
1837                        return -EINVAL;
1838
1839                padapter->registrypriv.rts_thresh = wrqu->rts.value;
1840        }
1841
1842        DBG_871X("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1843
1844        return 0;
1845}
1846
1847static int rtw_wx_get_rts(struct net_device *dev,
1848                             struct iw_request_info *info,
1849                             union iwreq_data *wrqu, char *extra)
1850{
1851        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1852
1853        DBG_871X("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
1854
1855        wrqu->rts.value = padapter->registrypriv.rts_thresh;
1856        wrqu->rts.fixed = 0;    /* no auto select */
1857        /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
1858
1859        return 0;
1860}
1861
1862static int rtw_wx_set_frag(struct net_device *dev,
1863                             struct iw_request_info *info,
1864                             union iwreq_data *wrqu, char *extra)
1865{
1866        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1867
1868        if (wrqu->frag.disabled)
1869                padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
1870        else {
1871                if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
1872                    wrqu->frag.value > MAX_FRAG_THRESHOLD)
1873                        return -EINVAL;
1874
1875                padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
1876        }
1877
1878        DBG_871X("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1879
1880        return 0;
1881
1882}
1883
1884static int rtw_wx_get_frag(struct net_device *dev,
1885                             struct iw_request_info *info,
1886                             union iwreq_data *wrqu, char *extra)
1887{
1888        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1889
1890        DBG_871X("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
1891
1892        wrqu->frag.value = padapter->xmitpriv.frag_len;
1893        wrqu->frag.fixed = 0;   /* no auto select */
1894        /* wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); */
1895
1896        return 0;
1897}
1898
1899static int rtw_wx_get_retry(struct net_device *dev,
1900                             struct iw_request_info *info,
1901                             union iwreq_data *wrqu, char *extra)
1902{
1903        /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */
1904
1905
1906        wrqu->retry.value = 7;
1907        wrqu->retry.fixed = 0;  /* no auto select */
1908        wrqu->retry.disabled = 1;
1909
1910        return 0;
1911
1912}
1913
1914static int rtw_wx_set_enc(struct net_device *dev,
1915                            struct iw_request_info *info,
1916                            union iwreq_data *wrqu, char *keybuf)
1917{
1918        u32 key, ret = 0;
1919        u32 keyindex_provided;
1920        struct ndis_802_11_wep   wep;
1921        enum NDIS_802_11_AUTHENTICATION_MODE authmode;
1922
1923        struct iw_point *erq = &(wrqu->encoding);
1924        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
1925        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1926        DBG_871X("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
1927
1928        memset(&wep, 0, sizeof(struct ndis_802_11_wep));
1929
1930        key = erq->flags & IW_ENCODE_INDEX;
1931
1932        if (erq->flags & IW_ENCODE_DISABLED) {
1933                DBG_871X("EncryptionDisabled\n");
1934                padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
1935                padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1936                padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1937                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1938                authmode = Ndis802_11AuthModeOpen;
1939                padapter->securitypriv.ndisauthtype =authmode;
1940
1941                goto exit;
1942        }
1943
1944        if (key) {
1945                if (key > WEP_KEYS)
1946                        return -EINVAL;
1947                key--;
1948                keyindex_provided = 1;
1949        } else {
1950                keyindex_provided = 0;
1951                key = padapter->securitypriv.dot11PrivacyKeyIndex;
1952                DBG_871X("rtw_wx_set_enc, key =%d\n", key);
1953        }
1954
1955        /* set authentication mode */
1956        if (erq->flags & IW_ENCODE_OPEN) {
1957                DBG_871X("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
1958                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1959
1960                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1961
1962                padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1963                padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1964                authmode = Ndis802_11AuthModeOpen;
1965                padapter->securitypriv.ndisauthtype =authmode;
1966        } else if (erq->flags & IW_ENCODE_RESTRICTED) {
1967                DBG_871X("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
1968                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
1969
1970                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1971
1972                padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1973                padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1974                authmode = Ndis802_11AuthModeShared;
1975                padapter->securitypriv.ndisauthtype =authmode;
1976        } else {
1977                DBG_871X("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
1978
1979                padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
1980                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
1981                padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1982                padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1983                authmode = Ndis802_11AuthModeOpen;
1984                padapter->securitypriv.ndisauthtype =authmode;
1985        }
1986
1987        wep.KeyIndex = key;
1988        if (erq->length > 0) {
1989                wep.KeyLength = erq->length <= 5 ? 5 : 13;
1990
1991                wep.Length = wep.KeyLength + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
1992        } else {
1993                wep.KeyLength = 0 ;
1994
1995                if (keyindex_provided == 1) { /*  set key_id only, no given KeyMaterial(erq->length == 0). */
1996                        padapter->securitypriv.dot11PrivacyKeyIndex = key;
1997
1998                        DBG_871X("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
1999
2000                        switch (padapter->securitypriv.dot11DefKeylen[key]) {
2001                                case 5:
2002                                        padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
2003                                        break;
2004                                case 13:
2005                                        padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
2006                                        break;
2007                                default:
2008                                        padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2009                                        break;
2010                        }
2011
2012                        goto exit;
2013
2014                }
2015
2016        }
2017
2018        wep.KeyIndex |= 0x80000000;
2019
2020        memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
2021
2022        if (rtw_set_802_11_add_wep(padapter, &wep) == false) {
2023                if (rf_on == pwrpriv->rf_pwrstate)
2024                        ret = -EOPNOTSUPP;
2025                goto exit;
2026        }
2027
2028exit:
2029        return ret;
2030}
2031
2032static int rtw_wx_get_enc(struct net_device *dev,
2033                            struct iw_request_info *info,
2034                            union iwreq_data *wrqu, char *keybuf)
2035{
2036        uint key, ret = 0;
2037        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2038        struct iw_point *erq = &(wrqu->encoding);
2039        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2040
2041        if (check_fwstate(pmlmepriv, _FW_LINKED) != true) {
2042                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true) {
2043                         erq->length = 0;
2044                         erq->flags |= IW_ENCODE_DISABLED;
2045                         return 0;
2046                 }
2047        }
2048
2049
2050        key = erq->flags & IW_ENCODE_INDEX;
2051
2052        if (key) {
2053                if (key > WEP_KEYS)
2054                        return -EINVAL;
2055                key--;
2056        } else {
2057                key = padapter->securitypriv.dot11PrivacyKeyIndex;
2058        }
2059
2060        erq->flags = key + 1;
2061
2062        /* if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen) */
2063        /*  */
2064        /*       erq->flags |= IW_ENCODE_OPEN; */
2065        /*  */
2066
2067        switch (padapter->securitypriv.ndisencryptstatus) {
2068        case Ndis802_11EncryptionNotSupported:
2069        case Ndis802_11EncryptionDisabled:
2070                erq->length = 0;
2071                erq->flags |= IW_ENCODE_DISABLED;
2072                break;
2073        case Ndis802_11Encryption1Enabled:
2074                erq->length = padapter->securitypriv.dot11DefKeylen[key];
2075
2076                if (erq->length) {
2077                        memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
2078
2079                        erq->flags |= IW_ENCODE_ENABLED;
2080
2081                        if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
2082                                erq->flags |= IW_ENCODE_OPEN;
2083                        else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
2084                                erq->flags |= IW_ENCODE_RESTRICTED;
2085                } else {
2086                        erq->length = 0;
2087                        erq->flags |= IW_ENCODE_DISABLED;
2088                }
2089                break;
2090        case Ndis802_11Encryption2Enabled:
2091        case Ndis802_11Encryption3Enabled:
2092                erq->length = 16;
2093                erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
2094                break;
2095        default:
2096                erq->length = 0;
2097                erq->flags |= IW_ENCODE_DISABLED;
2098                break;
2099        }
2100        return ret;
2101}
2102
2103static int rtw_wx_get_power(struct net_device *dev,
2104                             struct iw_request_info *info,
2105                             union iwreq_data *wrqu, char *extra)
2106{
2107        /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */
2108
2109        wrqu->power.value = 0;
2110        wrqu->power.fixed = 0;  /* no auto select */
2111        wrqu->power.disabled = 1;
2112
2113        return 0;
2114}
2115
2116static int rtw_wx_set_gen_ie(struct net_device *dev,
2117                             struct iw_request_info *info,
2118                             union iwreq_data *wrqu, char *extra)
2119{
2120        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2121
2122        return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
2123}
2124
2125static int rtw_wx_set_auth(struct net_device *dev,
2126                           struct iw_request_info *info,
2127                           union iwreq_data *wrqu, char *extra)
2128{
2129        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2130        struct iw_param *param = (struct iw_param*)&(wrqu->param);
2131        int ret = 0;
2132
2133        switch (param->flags & IW_AUTH_INDEX) {
2134        case IW_AUTH_WPA_VERSION:
2135                break;
2136        case IW_AUTH_CIPHER_PAIRWISE:
2137                break;
2138        case IW_AUTH_CIPHER_GROUP:
2139                break;
2140        case IW_AUTH_KEY_MGMT:
2141                /*
2142                 *  ??? does not use these parameters
2143                 */
2144                break;
2145        case IW_AUTH_TKIP_COUNTERMEASURES:
2146                /* wpa_supplicant is setting the tkip countermeasure. */
2147                if (param->value) /* enabling */
2148                        padapter->securitypriv.btkip_countermeasure = true;
2149                else /* disabling */
2150                        padapter->securitypriv.btkip_countermeasure = false;
2151                break;
2152        case IW_AUTH_DROP_UNENCRYPTED:
2153                /* HACK:
2154                 *
2155                 * wpa_supplicant calls set_wpa_enabled when the driver
2156                 * is loaded and unloaded, regardless of if WPA is being
2157                 * used.  No other calls are made which can be used to
2158                 * determine if encryption will be used or not prior to
2159                 * association being expected.  If encryption is not being
2160                 * used, drop_unencrypted is set to false, else true -- we
2161                 * can use this to determine if the CAP_PRIVACY_ON bit should
2162                 * be set.
2163                 */
2164
2165                /*
2166                 * This means init value, or using wep, ndisencryptstatus =
2167                 * Ndis802_11Encryption1Enabled, then it needn't reset it;
2168                 */
2169                if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
2170                        break;
2171
2172                if (param->value) {
2173                        padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
2174                        padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
2175                        padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
2176                        padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
2177                        padapter->securitypriv.ndisauthtype =Ndis802_11AuthModeOpen;
2178                }
2179
2180                break;
2181        case IW_AUTH_80211_AUTH_ALG:
2182                /*
2183                 *  It's the starting point of a link layer connection using wpa_supplicant
2184                 */
2185                if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2186                        LeaveAllPowerSaveMode(padapter);
2187                        rtw_disassoc_cmd(padapter, 500, false);
2188                        DBG_871X("%s...call rtw_indicate_disconnect\n ", __func__);
2189                        rtw_indicate_disconnect(padapter);
2190                        rtw_free_assoc_resources(padapter, 1);
2191                }
2192
2193                ret = wpa_set_auth_algs(dev, (u32)param->value);
2194                break;
2195        case IW_AUTH_WPA_ENABLED:
2196                break;
2197        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
2198                break;
2199        case IW_AUTH_PRIVACY_INVOKED:
2200                break;
2201        default:
2202                return -EOPNOTSUPP;
2203        }
2204
2205        return ret;
2206}
2207
2208static int rtw_wx_set_enc_ext(struct net_device *dev,
2209                             struct iw_request_info *info,
2210                             union iwreq_data *wrqu, char *extra)
2211{
2212        char *alg_name;
2213        u32 param_len;
2214        struct ieee_param *param = NULL;
2215        struct iw_point *pencoding = &wrqu->encoding;
2216        struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
2217        int ret = 0;
2218
2219        param_len = sizeof(struct ieee_param) + pext->key_len;
2220        param = rtw_malloc(param_len);
2221        if (param == NULL)
2222                return -1;
2223
2224        memset(param, 0, param_len);
2225
2226        param->cmd = IEEE_CMD_SET_ENCRYPTION;
2227        memset(param->sta_addr, 0xff, ETH_ALEN);
2228
2229
2230        switch (pext->alg) {
2231        case IW_ENCODE_ALG_NONE:
2232                /* todo: remove key */
2233                /* remove = 1; */
2234                alg_name = "none";
2235                break;
2236        case IW_ENCODE_ALG_WEP:
2237                alg_name = "WEP";
2238                break;
2239        case IW_ENCODE_ALG_TKIP:
2240                alg_name = "TKIP";
2241                break;
2242        case IW_ENCODE_ALG_CCMP:
2243                alg_name = "CCMP";
2244                break;
2245        case IW_ENCODE_ALG_AES_CMAC:
2246                alg_name = "BIP";
2247                break;
2248        default:
2249                ret = -1;
2250                goto exit;
2251        }
2252
2253        strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
2254
2255        if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
2256                param->u.crypt.set_tx = 1;
2257
2258        /* cliW: WEP does not have group key
2259         * just not checking GROUP key setting
2260         */
2261        if ((pext->alg != IW_ENCODE_ALG_WEP) &&
2262                ((pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
2263                || (pext->ext_flags & IW_ENCODE_ALG_AES_CMAC))) {
2264                param->u.crypt.set_tx = 0;
2265        }
2266
2267        param->u.crypt.idx = (pencoding->flags&0x00FF) -1 ;
2268
2269        if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
2270                memcpy(param->u.crypt.seq, pext->rx_seq, 8);
2271
2272        if (pext->key_len) {
2273                param->u.crypt.key_len = pext->key_len;
2274                /* memcpy(param + 1, pext + 1, pext->key_len); */
2275                memcpy(param->u.crypt.key, pext + 1, pext->key_len);
2276        }
2277
2278        if (pencoding->flags & IW_ENCODE_DISABLED) {
2279                /* todo: remove key */
2280                /* remove = 1; */
2281        }
2282
2283        ret =  wpa_set_encryption(dev, param, param_len);
2284
2285exit:
2286        kfree(param);
2287
2288        return ret;
2289}
2290
2291
2292static int rtw_wx_get_nick(struct net_device *dev,
2293                             struct iw_request_info *info,
2294                             union iwreq_data *wrqu, char *extra)
2295{
2296        /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */
2297         /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
2298         /* struct security_priv *psecuritypriv = &padapter->securitypriv; */
2299
2300        if (extra) {
2301                wrqu->data.length = 14;
2302                wrqu->data.flags = 1;
2303                memcpy(extra, "<WIFI@REALTEK>", 14);
2304        }
2305        return 0;
2306}
2307
2308static int rtw_wx_read32(struct net_device *dev,
2309                            struct iw_request_info *info,
2310                            union iwreq_data *wrqu, char *extra)
2311{
2312        struct adapter *padapter;
2313        struct iw_point *p;
2314        u16 len;
2315        u32 addr;
2316        u32 data32;
2317        u32 bytes;
2318        u8 *ptmp;
2319        int ret;
2320
2321
2322        ret = 0;
2323        padapter = (struct adapter *)rtw_netdev_priv(dev);
2324        p = &wrqu->data;
2325        len = p->length;
2326        if (0 == len)
2327                return -EINVAL;
2328
2329        ptmp = rtw_malloc(len);
2330        if (NULL == ptmp)
2331                return -ENOMEM;
2332
2333        if (copy_from_user(ptmp, p->pointer, len)) {
2334                ret = -EFAULT;
2335                goto exit;
2336        }
2337
2338        bytes = 0;
2339        addr = 0;
2340        sscanf(ptmp, "%d,%x", &bytes, &addr);
2341
2342        switch (bytes) {
2343                case 1:
2344                        data32 = rtw_read8(padapter, addr);
2345                        sprintf(extra, "0x%02X", data32);
2346                        break;
2347                case 2:
2348                        data32 = rtw_read16(padapter, addr);
2349                        sprintf(extra, "0x%04X", data32);
2350                        break;
2351                case 4:
2352                        data32 = rtw_read32(padapter, addr);
2353                        sprintf(extra, "0x%08X", data32);
2354                        break;
2355                default:
2356                        DBG_871X(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
2357                        ret = -EINVAL;
2358                        goto exit;
2359        }
2360        DBG_871X(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra);
2361
2362exit:
2363        kfree(ptmp);
2364
2365        return 0;
2366}
2367
2368static int rtw_wx_write32(struct net_device *dev,
2369                            struct iw_request_info *info,
2370                            union iwreq_data *wrqu, char *extra)
2371{
2372        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2373
2374        u32 addr;
2375        u32 data32;
2376        u32 bytes;
2377
2378
2379        bytes = 0;
2380        addr = 0;
2381        data32 = 0;
2382        sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
2383
2384        switch (bytes) {
2385                case 1:
2386                        rtw_write8(padapter, addr, (u8)data32);
2387                        DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
2388                        break;
2389                case 2:
2390                        rtw_write16(padapter, addr, (u16)data32);
2391                        DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
2392                        break;
2393                case 4:
2394                        rtw_write32(padapter, addr, data32);
2395                        DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
2396                        break;
2397                default:
2398                        DBG_871X(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
2399                        return -EINVAL;
2400        }
2401
2402        return 0;
2403}
2404
2405static int rtw_wx_read_rf(struct net_device *dev,
2406                            struct iw_request_info *info,
2407                            union iwreq_data *wrqu, char *extra)
2408{
2409        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2410        u32 path, addr, data32;
2411
2412
2413        path = *(u32*)extra;
2414        addr = *((u32*)extra + 1);
2415        data32 = rtw_hal_read_rfreg(padapter, path, addr, 0xFFFFF);
2416        /*
2417         * IMPORTANT!!
2418         * Only when wireless private ioctl is at odd order,
2419         * "extra" would be copied to user space.
2420         */
2421        sprintf(extra, "0x%05x", data32);
2422
2423        return 0;
2424}
2425
2426static int rtw_wx_write_rf(struct net_device *dev,
2427                            struct iw_request_info *info,
2428                            union iwreq_data *wrqu, char *extra)
2429{
2430        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2431        u32 path, addr, data32;
2432
2433
2434        path = *(u32*)extra;
2435        addr = *((u32*)extra + 1);
2436        data32 = *((u32*)extra + 2);
2437/*      DBG_871X("%s: path =%d addr = 0x%02x data = 0x%05x\n", __func__, path, addr, data32); */
2438        rtw_hal_write_rfreg(padapter, path, addr, 0xFFFFF, data32);
2439
2440        return 0;
2441}
2442
2443static int rtw_wx_priv_null(struct net_device *dev, struct iw_request_info *a,
2444                 union iwreq_data *wrqu, char *b)
2445{
2446        return -1;
2447}
2448
2449static int dummy(struct net_device *dev, struct iw_request_info *a,
2450                 union iwreq_data *wrqu, char *b)
2451{
2452        /* struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); */
2453        /* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); */
2454
2455        /* DBG_871X("cmd_code =%x, fwstate = 0x%x\n", a->cmd, get_fwstate(pmlmepriv)); */
2456
2457        return -1;
2458
2459}
2460
2461static int rtw_wx_set_channel_plan(struct net_device *dev,
2462                               struct iw_request_info *info,
2463                               union iwreq_data *wrqu, char *extra)
2464{
2465        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2466        u8 channel_plan_req = (u8) (*((int *)wrqu));
2467
2468        if (_SUCCESS == rtw_set_chplan_cmd(padapter, channel_plan_req, 1, 1))
2469                DBG_871X("%s set channel_plan = 0x%02X\n", __func__, channel_plan_req);
2470         else
2471                return -EPERM;
2472
2473        return 0;
2474}
2475
2476static int rtw_wx_set_mtk_wps_probe_ie(struct net_device *dev,
2477                struct iw_request_info *a,
2478                union iwreq_data *wrqu, char *b)
2479{
2480        return 0;
2481}
2482
2483static int rtw_wx_get_sensitivity(struct net_device *dev,
2484                                struct iw_request_info *info,
2485                                union iwreq_data *wrqu, char *buf)
2486{
2487        return 0;
2488}
2489
2490static int rtw_wx_set_mtk_wps_ie(struct net_device *dev,
2491                                struct iw_request_info *info,
2492                                union iwreq_data *wrqu, char *extra)
2493{
2494        return 0;
2495}
2496
2497/*
2498typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
2499                          union iwreq_data *wrqu, char *extra);
2500*/
2501/*
2502 *For all data larger than 16 octets, we need to use a
2503 *pointer to memory allocated in user space.
2504 */
2505static  int rtw_drvext_hdl(struct net_device *dev, struct iw_request_info *info,
2506                                                union iwreq_data *wrqu, char *extra)
2507{
2508        return 0;
2509}
2510
2511static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info,
2512                                                union iwreq_data *wrqu, char *extra)
2513{
2514        int ret = 0;
2515        return ret;
2516}
2517
2518static int rtw_get_ap_info(struct net_device *dev,
2519                               struct iw_request_info *info,
2520                               union iwreq_data *wrqu, char *extra)
2521{
2522        int ret = 0;
2523        u32 cnt = 0, wpa_ielen;
2524        struct list_head        *plist, *phead;
2525        unsigned char *pbuf;
2526        u8 bssid[ETH_ALEN];
2527        char data[32];
2528        struct wlan_network *pnetwork = NULL;
2529        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2530        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2531        struct __queue *queue = &(pmlmepriv->scanned_queue);
2532        struct iw_point *pdata = &wrqu->data;
2533
2534        DBG_871X("+rtw_get_aplist_info\n");
2535
2536        if ((padapter->bDriverStopped) || (pdata == NULL)) {
2537                ret = -EINVAL;
2538                goto exit;
2539        }
2540
2541        while ((check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) == true) {
2542                msleep(30);
2543                cnt++;
2544                if (cnt > 100)
2545                        break;
2546        }
2547
2548
2549        /* pdata->length = 0;? */
2550        pdata->flags = 0;
2551        if (pdata->length>=32) {
2552                if (copy_from_user(data, pdata->pointer, 32)) {
2553                        ret = -EINVAL;
2554                        goto exit;
2555                }
2556        } else {
2557                ret = -EINVAL;
2558                goto exit;
2559        }
2560
2561        spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2562
2563        phead = get_list_head(queue);
2564        plist = get_next(phead);
2565
2566        while (1) {
2567                if (phead == plist)
2568                        break;
2569
2570
2571                pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
2572
2573                /* if (hwaddr_aton_i(pdata->pointer, bssid)) */
2574                if (hwaddr_aton_i(data, bssid)) {
2575                        DBG_871X("Invalid BSSID '%s'.\n", (u8 *)data);
2576                        spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2577                        return -EINVAL;
2578                }
2579
2580
2581                if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) { /* BSSID match, then check if supporting wpa/wpa2 */
2582                        DBG_871X("BSSID:" MAC_FMT "\n", MAC_ARG(bssid));
2583
2584                        pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2585                        if (pbuf && (wpa_ielen>0)) {
2586                                pdata->flags = 1;
2587                                break;
2588                        }
2589
2590                        pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
2591                        if (pbuf && (wpa_ielen>0)) {
2592                                pdata->flags = 2;
2593                                break;
2594                        }
2595                }
2596
2597                plist = get_next(plist);
2598
2599        }
2600
2601        spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2602
2603        if (pdata->length>=34) {
2604                if (copy_to_user((u8 __force __user *)pdata->pointer+32, (u8 *)&pdata->flags, 1)) {
2605                        ret = -EINVAL;
2606                        goto exit;
2607                }
2608        }
2609
2610exit:
2611
2612        return ret;
2613
2614}
2615
2616static int rtw_set_pid(struct net_device *dev,
2617                               struct iw_request_info *info,
2618                               union iwreq_data *wrqu, char *extra)
2619{
2620
2621        int ret = 0;
2622        struct adapter *padapter = rtw_netdev_priv(dev);
2623        int *pdata = (int *)wrqu;
2624        int selector;
2625
2626        if ((padapter->bDriverStopped) || (pdata == NULL)) {
2627                ret = -EINVAL;
2628                goto exit;
2629        }
2630
2631        selector = *pdata;
2632        if (selector < 3 && selector >= 0) {
2633                padapter->pid[selector] = *(pdata+1);
2634                DBG_871X("%s set pid[%d]=%d\n", __func__, selector , padapter->pid[selector]);
2635        }
2636        else
2637                DBG_871X("%s selector %d error\n", __func__, selector);
2638
2639exit:
2640
2641        return ret;
2642
2643}
2644
2645static int rtw_wps_start(struct net_device *dev,
2646                               struct iw_request_info *info,
2647                               union iwreq_data *wrqu, char *extra)
2648{
2649
2650        int ret = 0;
2651        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2652        struct iw_point *pdata = &wrqu->data;
2653        u32   u32wps_start = 0;
2654        unsigned int uintRet = 0;
2655
2656        if ((true == padapter->bDriverStopped) ||(true ==padapter->bSurpriseRemoved) || (NULL == pdata)) {
2657                ret = -EINVAL;
2658                goto exit;
2659        }
2660
2661        uintRet = copy_from_user((void*) &u32wps_start, pdata->pointer, 4);
2662        if (u32wps_start == 0)
2663                u32wps_start = *extra;
2664
2665        DBG_871X("[%s] wps_start = %d\n", __func__, u32wps_start);
2666
2667#ifdef CONFIG_INTEL_WIDI
2668        process_intel_widi_wps_status(padapter, u32wps_start);
2669#endif /* CONFIG_INTEL_WIDI */
2670
2671exit:
2672
2673        return ret;
2674
2675}
2676
2677static int rtw_p2p_set(struct net_device *dev,
2678                               struct iw_request_info *info,
2679                               union iwreq_data *wrqu, char *extra)
2680{
2681
2682        int ret = 0;
2683
2684        return ret;
2685
2686}
2687
2688static int rtw_p2p_get(struct net_device *dev,
2689                               struct iw_request_info *info,
2690                               union iwreq_data *wrqu, char *extra)
2691{
2692
2693        int ret = 0;
2694
2695        return ret;
2696
2697}
2698
2699static int rtw_p2p_get2(struct net_device *dev,
2700                                                struct iw_request_info *info,
2701                                                union iwreq_data *wrqu, char *extra)
2702{
2703
2704        int ret = 0;
2705
2706        return ret;
2707
2708}
2709
2710static int rtw_rereg_nd_name(struct net_device *dev,
2711                               struct iw_request_info *info,
2712                               union iwreq_data *wrqu, char *extra)
2713{
2714        int ret = 0;
2715        struct adapter *padapter = rtw_netdev_priv(dev);
2716        struct rereg_nd_name_data *rereg_priv = &padapter->rereg_nd_name_priv;
2717        char new_ifname[IFNAMSIZ];
2718
2719        if (rereg_priv->old_ifname[0] == 0) {
2720                char *reg_ifname;
2721                reg_ifname = padapter->registrypriv.ifname;
2722
2723                strncpy(rereg_priv->old_ifname, reg_ifname, IFNAMSIZ);
2724                rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
2725        }
2726
2727        /* DBG_871X("%s wrqu->data.length:%d\n", __func__, wrqu->data.length); */
2728        if (wrqu->data.length > IFNAMSIZ)
2729                return -EFAULT;
2730
2731        if (copy_from_user(new_ifname, wrqu->data.pointer, IFNAMSIZ))
2732                return -EFAULT;
2733
2734        if (0 == strcmp(rereg_priv->old_ifname, new_ifname))
2735                return ret;
2736
2737        DBG_871X("%s new_ifname:%s\n", __func__, new_ifname);
2738        if (0 != (ret = rtw_change_ifname(padapter, new_ifname)))
2739                goto exit;
2740
2741        strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
2742        rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
2743
2744        if (!memcmp(new_ifname, "disable%d", 9)) {
2745
2746                DBG_871X("%s disable\n", __func__);
2747                /*  free network queue for Android's timming issue */
2748                rtw_free_network_queue(padapter, true);
2749
2750                /*  the interface is being "disabled", we can do deeper IPS */
2751                /* rereg_priv->old_ips_mode = rtw_get_ips_mode_req(&padapter->pwrctrlpriv); */
2752                /* rtw_ips_mode_req(&padapter->pwrctrlpriv, IPS_NORMAL); */
2753        }
2754exit:
2755        return ret;
2756
2757}
2758
2759static int rtw_dbg_port(struct net_device *dev,
2760                               struct iw_request_info *info,
2761                               union iwreq_data *wrqu, char *extra)
2762{
2763        int ret = 0;
2764        u8 major_cmd, minor_cmd;
2765        u16 arg;
2766        u32 extra_arg, *pdata, val32;
2767        struct sta_info *psta;
2768        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
2769        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2770        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2771        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2772        struct wlan_network *cur_network = &(pmlmepriv->cur_network);
2773        struct sta_priv *pstapriv = &padapter->stapriv;
2774
2775
2776        pdata = (u32*)&wrqu->data;
2777
2778        val32 = *pdata;
2779        arg = (u16)(val32&0x0000ffff);
2780        major_cmd = (u8)(val32>>24);
2781        minor_cmd = (u8)((val32>>16)&0x00ff);
2782
2783        extra_arg = *(pdata+1);
2784
2785        switch (major_cmd) {
2786                case 0x70:/* read_reg */
2787                        switch (minor_cmd) {
2788                                case 1:
2789                                        DBG_871X("rtw_read8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
2790                                        break;
2791                                case 2:
2792                                        DBG_871X("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
2793                                        break;
2794                                case 4:
2795                                        DBG_871X("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
2796                                        break;
2797                        }
2798                        break;
2799                case 0x71:/* write_reg */
2800                        switch (minor_cmd) {
2801                                case 1:
2802                                        rtw_write8(padapter, arg, extra_arg);
2803                                        DBG_871X("rtw_write8(0x%x) = 0x%02x\n", arg, rtw_read8(padapter, arg));
2804                                        break;
2805                                case 2:
2806                                        rtw_write16(padapter, arg, extra_arg);
2807                                        DBG_871X("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
2808                                        break;
2809                                case 4:
2810                                        rtw_write32(padapter, arg, extra_arg);
2811                                        DBG_871X("rtw_write32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
2812                                        break;
2813                        }
2814                        break;
2815                case 0x72:/* read_bb */
2816                        DBG_871X("read_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
2817                        break;
2818                case 0x73:/* write_bb */
2819                        rtw_hal_write_bbreg(padapter, arg, 0xffffffff, extra_arg);
2820                        DBG_871X("write_bbreg(0x%x) = 0x%x\n", arg, rtw_hal_read_bbreg(padapter, arg, 0xffffffff));
2821                        break;
2822                case 0x74:/* read_rf */
2823                        DBG_871X("read RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
2824                        break;
2825                case 0x75:/* write_rf */
2826                        rtw_hal_write_rfreg(padapter, minor_cmd, arg, 0xffffffff, extra_arg);
2827                        DBG_871X("write RF_reg path(0x%02x), offset(0x%x), value(0x%08x)\n", minor_cmd, arg, rtw_hal_read_rfreg(padapter, minor_cmd, arg, 0xffffffff));
2828                        break;
2829
2830                case 0x76:
2831                        switch (minor_cmd) {
2832                                case 0x00: /* normal mode, */
2833                                        padapter->recvpriv.is_signal_dbg = 0;
2834                                        break;
2835                                case 0x01: /* dbg mode */
2836                                        padapter->recvpriv.is_signal_dbg = 1;
2837                                        extra_arg = extra_arg>100?100:extra_arg;
2838                                        padapter->recvpriv.signal_strength_dbg =extra_arg;
2839                                        break;
2840                        }
2841                        break;
2842                case 0x78: /* IOL test */
2843                        break;
2844                case 0x79:
2845                        {
2846                                /*
2847                                * dbg 0x79000000 [value], set RESP_TXAGC to + value, value:0~15
2848                                * dbg 0x79010000 [value], set RESP_TXAGC to - value, value:0~15
2849                                */
2850                                u8 value =  extra_arg & 0x0f;
2851                                u8 sign = minor_cmd;
2852                                u16 write_value = 0;
2853
2854                                DBG_871X("%s set RESP_TXAGC to %s %u\n", __func__, sign?"minus":"plus", value);
2855
2856                                if (sign)
2857                                        value = value | 0x10;
2858
2859                                write_value = value | (value << 5);
2860                                rtw_write16(padapter, 0x6d9, write_value);
2861                        }
2862                        break;
2863                case 0x7a:
2864                        receive_disconnect(padapter, pmlmeinfo->network.MacAddress
2865                                , WLAN_REASON_EXPIRATION_CHK);
2866                        break;
2867                case 0x7F:
2868                        switch (minor_cmd) {
2869                                case 0x0:
2870                                        DBG_871X("fwstate = 0x%x\n", get_fwstate(pmlmepriv));
2871                                        break;
2872                                case 0x01:
2873                                        DBG_871X("minor_cmd 0x%x\n", minor_cmd);
2874                                        break;
2875                                case 0x02:
2876                                        DBG_871X("pmlmeinfo->state = 0x%x\n", pmlmeinfo->state);
2877                                        DBG_871X("DrvBcnEarly =%d\n", pmlmeext->DrvBcnEarly);
2878                                        DBG_871X("DrvBcnTimeOut =%d\n", pmlmeext->DrvBcnTimeOut);
2879                                        break;
2880                                case 0x03:
2881                                        DBG_871X("qos_option =%d\n", pmlmepriv->qospriv.qos_option);
2882                                        DBG_871X("ht_option =%d\n", pmlmepriv->htpriv.ht_option);
2883                                        break;
2884                                case 0x04:
2885                                        DBG_871X("cur_ch =%d\n", pmlmeext->cur_channel);
2886                                        DBG_871X("cur_bw =%d\n", pmlmeext->cur_bwmode);
2887                                        DBG_871X("cur_ch_off =%d\n", pmlmeext->cur_ch_offset);
2888
2889                                        DBG_871X("oper_ch =%d\n", rtw_get_oper_ch(padapter));
2890                                        DBG_871X("oper_bw =%d\n", rtw_get_oper_bw(padapter));
2891                                        DBG_871X("oper_ch_offet =%d\n", rtw_get_oper_choffset(padapter));
2892
2893                                        break;
2894                                case 0x05:
2895                                        psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
2896                                        if (psta) {
2897                                                int i;
2898                                                struct recv_reorder_ctrl *preorder_ctrl;
2899
2900                                                DBG_871X("SSID =%s\n", cur_network->network.Ssid.Ssid);
2901                                                DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
2902                                                DBG_871X("cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
2903                                                DBG_871X("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
2904                                                DBG_871X("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
2905                                                DBG_871X("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
2906                                                DBG_871X("bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
2907                                                DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
2908                                                DBG_871X("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
2909
2910                                                for (i = 0;i<16;i++) {
2911                                                        preorder_ctrl = &psta->recvreorder_ctrl[i];
2912                                                        if (preorder_ctrl->enable)
2913                                                                DBG_871X("tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq);
2914                                                }
2915
2916                                        } else {
2917                                                DBG_871X("can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
2918                                        }
2919                                        break;
2920                                case 0x06:
2921                                        {
2922                                                u32 ODMFlag;
2923                                                rtw_hal_get_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
2924                                                DBG_871X("(B)DMFlag = 0x%x, arg = 0x%x\n", ODMFlag, arg);
2925                                                ODMFlag = (u32)(0x0f&arg);
2926                                                DBG_871X("(A)DMFlag = 0x%x\n", ODMFlag);
2927                                                rtw_hal_set_hwreg(padapter, HW_VAR_DM_FLAG, (u8 *)(&ODMFlag));
2928                                        }
2929                                        break;
2930                                case 0x07:
2931                                        DBG_871X("bSurpriseRemoved =%d, bDriverStopped =%d\n",
2932                                                padapter->bSurpriseRemoved, padapter->bDriverStopped);
2933                                        break;
2934                                case 0x08:
2935                                        {
2936                                                DBG_871X("minor_cmd 0x%x\n", minor_cmd);
2937                                        }
2938                                        break;
2939                                case 0x09:
2940                                        {
2941                                                int i, j;
2942                                                struct list_head        *plist, *phead;
2943                                                struct recv_reorder_ctrl *preorder_ctrl;
2944
2945                                                DBG_871X("sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
2946
2947                                                spin_lock_bh(&pstapriv->sta_hash_lock);
2948
2949                                                for (i = 0; i< NUM_STA; i++) {
2950                                                        phead = &(pstapriv->sta_hash[i]);
2951                                                        plist = get_next(phead);
2952
2953                                                        while (phead != plist) {
2954                                                                psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
2955
2956                                                                plist = get_next(plist);
2957
2958                                                                if (extra_arg == psta->aid) {
2959                                                                        DBG_871X("sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
2960                                                                        DBG_871X("rtsen =%d, cts2slef =%d\n", psta->rtsen, psta->cts2self);
2961                                                                        DBG_871X("state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
2962                                                                        DBG_871X("qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
2963                                                                        DBG_871X("bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
2964                                                                        DBG_871X("ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
2965                                                                        DBG_871X("agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
2966                                                                        DBG_871X("capability = 0x%x\n", psta->capability);
2967                                                                        DBG_871X("flags = 0x%x\n", psta->flags);
2968                                                                        DBG_871X("wpa_psk = 0x%x\n", psta->wpa_psk);
2969                                                                        DBG_871X("wpa2_group_cipher = 0x%x\n", psta->wpa2_group_cipher);
2970                                                                        DBG_871X("wpa2_pairwise_cipher = 0x%x\n", psta->wpa2_pairwise_cipher);
2971                                                                        DBG_871X("qos_info = 0x%x\n", psta->qos_info);
2972                                                                        DBG_871X("dot118021XPrivacy = 0x%x\n", psta->dot118021XPrivacy);
2973
2974
2975
2976                                                                        for (j = 0;j<16;j++) {
2977                                                                                preorder_ctrl = &psta->recvreorder_ctrl[j];
2978                                                                                if (preorder_ctrl->enable)
2979                                                                                        DBG_871X("tid =%d, indicate_seq =%d\n", j, preorder_ctrl->indicate_seq);
2980                                                                        }
2981                                                                }
2982                                                        }
2983                                                }
2984
2985                                                spin_unlock_bh(&pstapriv->sta_hash_lock);
2986
2987                                        }
2988                                        break;
2989                                case 0x0a:
2990                                        {
2991                                                int max_mac_id = 0;
2992                                                max_mac_id = rtw_search_max_mac_id(padapter);
2993                                                printk("%s ==> max_mac_id = %d\n", __func__, max_mac_id);
2994                                        }
2995                                        break;
2996                                case 0x0b: /* Enable = 1, Disable = 0 driver control vrtl_carrier_sense. */
2997                                        if (arg == 0) {
2998                                                DBG_871X("disable driver ctrl vcs\n");
2999                                                padapter->driver_vcs_en = 0;
3000                                        } else if (arg == 1) {
3001                                                DBG_871X("enable driver ctrl vcs = %d\n", extra_arg);
3002                                                padapter->driver_vcs_en = 1;
3003
3004                                                if (extra_arg>2)
3005                                                        padapter->driver_vcs_type = 1;
3006                                                else
3007                                                        padapter->driver_vcs_type = extra_arg;
3008                                        }
3009                                        break;
3010                                case 0x0c:/* dump rx/tx packet */
3011                                        {
3012                                                if (arg == 0) {
3013                                                        DBG_871X("dump rx packet (%d)\n", extra_arg);
3014                                                        /* pHalData->bDumpRxPkt =extra_arg; */
3015                                                        rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_RXPKT, &(extra_arg));
3016                                                } else if (arg == 1) {
3017                                                        DBG_871X("dump tx packet (%d)\n", extra_arg);
3018                                                        rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(extra_arg));
3019                                                }
3020                                        }
3021                                        break;
3022                                case 0x0e:
3023                                        {
3024                                                if (arg == 0) {
3025                                                        DBG_871X("disable driver ctrl rx_ampdu_factor\n");
3026                                                        padapter->driver_rx_ampdu_factor = 0xFF;
3027                                                } else if (arg == 1) {
3028
3029                                                        DBG_871X("enable driver ctrl rx_ampdu_factor = %d\n", extra_arg);
3030
3031                                                        if ((extra_arg & 0x03) > 0x03)
3032                                                                padapter->driver_rx_ampdu_factor = 0xFF;
3033                                                        else
3034                                                                padapter->driver_rx_ampdu_factor = extra_arg;
3035                                                }
3036                                        }
3037                                        break;
3038
3039                                case 0x10:/*  driver version display */
3040                                        dump_drv_version(RTW_DBGDUMP);
3041                                        break;
3042                                case 0x11:/* dump linked status */
3043                                        {
3044                                                 linked_info_dump(padapter, extra_arg);
3045                                        }
3046                                        break;
3047                                case 0x12: /* set rx_stbc */
3048                                {
3049                                        struct registry_priv *pregpriv = &padapter->registrypriv;
3050                                        /*  0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */
3051                                        /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
3052                                        if (pregpriv && (extra_arg == 0 || extra_arg == 1|| extra_arg == 2 || extra_arg == 3)) {
3053                                                pregpriv->rx_stbc = extra_arg;
3054                                                DBG_871X("set rx_stbc =%d\n", pregpriv->rx_stbc);
3055                                        } else
3056                                                DBG_871X("get rx_stbc =%d\n", pregpriv->rx_stbc);
3057
3058                                }
3059                                break;
3060                                case 0x13: /* set ampdu_enable */
3061                                {
3062                                        struct registry_priv *pregpriv = &padapter->registrypriv;
3063                                        /*  0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */
3064                                        if (pregpriv && extra_arg < 3) {
3065                                                pregpriv->ampdu_enable = extra_arg;
3066                                                DBG_871X("set ampdu_enable =%d\n", pregpriv->ampdu_enable);
3067                                        } else
3068                                                DBG_871X("get ampdu_enable =%d\n", pregpriv->ampdu_enable);
3069
3070                                }
3071                                break;
3072                                case 0x14:
3073                                {
3074                                        DBG_871X("minor_cmd 0x%x\n", minor_cmd);
3075                                }
3076                                break;
3077                                case 0x16:
3078                                {
3079                                        if (arg == 0xff) {
3080                                                rtw_odm_dbg_comp_msg(RTW_DBGDUMP, padapter);
3081                                        } else {
3082                                                u64 dbg_comp = (u64)extra_arg;
3083                                                rtw_odm_dbg_comp_set(padapter, dbg_comp);
3084                                        }
3085                                }
3086                                        break;
3087#ifdef DBG_FIXED_CHAN
3088                                case 0x17:
3089                                        {
3090                                                struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3091                                                printk("===>  Fixed channel to %d\n", extra_arg);
3092                                                pmlmeext->fixed_chan = extra_arg;
3093
3094                                        }
3095                                        break;
3096#endif
3097                                case 0x18:
3098                                        {
3099                                                printk("===>  Switch USB Mode %d\n", extra_arg);
3100                                                rtw_hal_set_hwreg(padapter, HW_VAR_USB_MODE, (u8 *)&extra_arg);
3101                                        }
3102                                        break;
3103                                case 0x19:
3104                                        {
3105                                                struct registry_priv *pregistrypriv = &padapter->registrypriv;
3106                                                /*  extra_arg : */
3107                                                /*  BIT0: Enable VHT LDPC Rx, BIT1: Enable VHT LDPC Tx, */
3108                                                /*  BIT4: Enable HT LDPC Rx, BIT5: Enable HT LDPC Tx */
3109                                                if (arg == 0) {
3110                                                        DBG_871X("driver disable LDPC\n");
3111                                                        pregistrypriv->ldpc_cap = 0x00;
3112                                                } else if (arg == 1) {
3113                                                        DBG_871X("driver set LDPC cap = 0x%x\n", extra_arg);
3114                                                        pregistrypriv->ldpc_cap = (u8)(extra_arg&0x33);
3115                                                }
3116                                        }
3117                                        break;
3118                                case 0x1a:
3119                                        {
3120                                                struct registry_priv *pregistrypriv = &padapter->registrypriv;
3121                                                /*  extra_arg : */
3122                                                /*  BIT0: Enable VHT STBC Rx, BIT1: Enable VHT STBC Tx, */
3123                                                /*  BIT4: Enable HT STBC Rx, BIT5: Enable HT STBC Tx */
3124                                                if (arg == 0) {
3125                                                        DBG_871X("driver disable STBC\n");
3126                                                        pregistrypriv->stbc_cap = 0x00;
3127                                                } else if (arg == 1) {
3128                                                        DBG_871X("driver set STBC cap = 0x%x\n", extra_arg);
3129                                                        pregistrypriv->stbc_cap = (u8)(extra_arg&0x33);
3130                                                }
3131                                        }
3132                                        break;
3133                                case 0x1b:
3134                                        {
3135                                                struct registry_priv *pregistrypriv = &padapter->registrypriv;
3136
3137                                                if (arg == 0) {
3138                                                        DBG_871X("disable driver ctrl max_rx_rate, reset to default_rate_set\n");
3139                                                        init_mlme_default_rate_set(padapter);
3140                                                        pregistrypriv->ht_enable = (u8)rtw_ht_enable;
3141                                                } else if (arg == 1) {
3142
3143                                                        int i;
3144                                                        u8 max_rx_rate;
3145
3146                                                        DBG_871X("enable driver ctrl max_rx_rate = 0x%x\n", extra_arg);
3147
3148                                                        max_rx_rate = (u8)extra_arg;
3149
3150                                                        if (max_rx_rate < 0xc) { /*  max_rx_rate < MSC0 -> B or G -> disable HT */
3151                                                                pregistrypriv->ht_enable = 0;
3152                                                                for (i = 0; i<NumRates; i++) {
3153                                                                        if (pmlmeext->datarate[i] > max_rx_rate)
3154                                                                                pmlmeext->datarate[i] = 0xff;
3155                                                                }
3156
3157                                                        }
3158                                                        else if (max_rx_rate < 0x1c) { /*  mcs0~mcs15 */
3159                                                                u32 mcs_bitmap = 0x0;
3160
3161                                                                for (i = 0; i<((max_rx_rate+1)-0xc); i++)
3162                                                                        mcs_bitmap |= BIT(i);
3163
3164                                                                set_mcs_rate_by_mask(pmlmeext->default_supported_mcs_set, mcs_bitmap);
3165                                                        }
3166                                                }
3167                                        }
3168                                        break;
3169                                case 0x1c: /* enable/disable driver control AMPDU Density for peer sta's rx */
3170                                        {
3171                                                if (arg == 0) {
3172                                                        DBG_871X("disable driver ctrl ampdu density\n");
3173                                                        padapter->driver_ampdu_spacing = 0xFF;
3174                                                } else if (arg == 1) {
3175
3176                                                        DBG_871X("enable driver ctrl ampdu density = %d\n", extra_arg);
3177
3178                                                        if ((extra_arg & 0x07) > 0x07)
3179                                                                padapter->driver_ampdu_spacing = 0xFF;
3180                                                        else
3181                                                                padapter->driver_ampdu_spacing = extra_arg;
3182                                                }
3183                                        }
3184                                        break;
3185#ifdef CONFIG_BACKGROUND_NOISE_MONITOR
3186                                case 0x1e:
3187                                        {
3188                                                struct hal_com_data     *pHalData = GET_HAL_DATA(padapter);
3189                                                PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
3190                                                u8 chan = rtw_get_oper_ch(padapter);
3191                                                DBG_871X("===========================================\n");
3192                                                ODM_InbandNoise_Monitor(pDM_Odm, true, 0x1e, 100);
3193                                                DBG_871X("channel(%d), noise_a = %d, noise_b = %d , noise_all:%d\n",
3194                                                        chan, pDM_Odm->noise_level.noise[ODM_RF_PATH_A],
3195                                                        pDM_Odm->noise_level.noise[ODM_RF_PATH_B],
3196                                                        pDM_Odm->noise_level.noise_all);
3197                                                DBG_871X("===========================================\n");
3198
3199                                        }
3200                                        break;
3201#endif
3202                                case 0x23:
3203                                        {
3204                                                DBG_871X("turn %s the bNotifyChannelChange Variable\n", (extra_arg == 1)?"on":"off");
3205                                                padapter->bNotifyChannelChange = extra_arg;
3206                                                break;
3207                                        }
3208                                case 0x24:
3209                                        {
3210                                                break;
3211                                        }
3212#ifdef CONFIG_GPIO_API
3213                            case 0x25: /* Get GPIO register */
3214                                    {
3215                                            /*
3216                                            * dbg 0x7f250000 [gpio_num], Get gpio value, gpio_num:0~7
3217                                            */
3218
3219                                            int value;
3220                                            DBG_871X("Read GPIO Value  extra_arg = %d\n", extra_arg);
3221                                            value = rtw_get_gpio(dev, extra_arg);
3222                                            DBG_871X("Read GPIO Value = %d\n", value);
3223                                            break;
3224                                    }
3225                            case 0x26: /* Set GPIO direction */
3226                                    {
3227
3228                                            /* dbg 0x7f26000x [y], Set gpio direction,
3229                                            * x: gpio_num, 4~7  y: indicate direction, 0~1
3230                                            */
3231
3232                                            int value;
3233                                            DBG_871X("Set GPIO Direction! arg = %d , extra_arg =%d\n", arg , extra_arg);
3234                                            value = rtw_config_gpio(dev, arg, extra_arg);
3235                                            DBG_871X("Set GPIO Direction %s\n", (value ==-1)?"Fail!!!":"Success");
3236                                            break;
3237                                        }
3238                                case 0x27: /* Set GPIO output direction value */
3239                                        {
3240                                                /*
3241                                                * dbg 0x7f27000x [y], Set gpio output direction value,
3242                                                * x: gpio_num, 4~7  y: indicate direction, 0~1
3243                                                */
3244
3245                                                int value;
3246                                                DBG_871X("Set GPIO Value! arg = %d , extra_arg =%d\n", arg , extra_arg);
3247                                                value = rtw_set_gpio_output_value(dev, arg, extra_arg);
3248                                                DBG_871X("Set GPIO Value %s\n", (value ==-1)?"Fail!!!":"Success");
3249                                                break;
3250                                        }
3251#endif
3252                                case 0xaa:
3253                                        {
3254                                                if ((extra_arg & 0x7F)> 0x3F) extra_arg = 0xFF;
3255                                                DBG_871X("chang data rate to :0x%02x\n", extra_arg);
3256                                                padapter->fix_rate = extra_arg;
3257                                        }
3258                                        break;
3259                                case 0xdd:/* registers dump , 0 for mac reg, 1 for bb reg, 2 for rf reg */
3260                                        {
3261                                                if (extra_arg == 0)
3262                                                        mac_reg_dump(RTW_DBGDUMP, padapter);
3263                                                else if (extra_arg == 1)
3264                                                        bb_reg_dump(RTW_DBGDUMP, padapter);
3265                                                else if (extra_arg ==2)
3266                                                        rf_reg_dump(RTW_DBGDUMP, padapter);
3267                                        }
3268                                        break;
3269
3270                                case 0xee:/* turn on/off dynamic funcs */
3271                                        {
3272                                                u32 odm_flag;
3273
3274                                                if (0xf ==extra_arg) {
3275                                                        rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC,&odm_flag);
3276                                                        DBG_871X(" === DMFlag(0x%08x) ===\n", odm_flag);
3277                                                        DBG_871X("extra_arg = 0  - disable all dynamic func\n");
3278                                                        DBG_871X("extra_arg = 1  - disable DIG- BIT(0)\n");
3279                                                        DBG_871X("extra_arg = 2  - disable High power - BIT(1)\n");
3280                                                        DBG_871X("extra_arg = 3  - disable tx power tracking - BIT(2)\n");
3281                                                        DBG_871X("extra_arg = 4  - disable BT coexistence - BIT(3)\n");
3282                                                        DBG_871X("extra_arg = 5  - disable antenna diversity - BIT(4)\n");
3283                                                        DBG_871X("extra_arg = 6  - enable all dynamic func\n");
3284                                                } else {
3285                                                        /*extra_arg = 0  - disable all dynamic func
3286                                                                extra_arg = 1  - disable DIG
3287                                                                extra_arg = 2  - disable tx power tracking
3288                                                                extra_arg = 3  - turn on all dynamic func
3289                                                        */
3290                                                        rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DM_FUNC, &(extra_arg));
3291                                                        rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DM_FUNC,&odm_flag);
3292                                                        DBG_871X(" === DMFlag(0x%08x) ===\n", odm_flag);
3293                                                }
3294                                        }
3295                                        break;
3296
3297                                case 0xfd:
3298                                        rtw_write8(padapter, 0xc50, arg);
3299                                        DBG_871X("wr(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
3300                                        rtw_write8(padapter, 0xc58, arg);
3301                                        DBG_871X("wr(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
3302                                        break;
3303                                case 0xfe:
3304                                        DBG_871X("rd(0xc50) = 0x%x\n", rtw_read8(padapter, 0xc50));
3305                                        DBG_871X("rd(0xc58) = 0x%x\n", rtw_read8(padapter, 0xc58));
3306                                        break;
3307                                case 0xff:
3308                                        {
3309                                                DBG_871X("dbg(0x210) = 0x%x\n", rtw_read32(padapter, 0x210));
3310                                                DBG_871X("dbg(0x608) = 0x%x\n", rtw_read32(padapter, 0x608));
3311                                                DBG_871X("dbg(0x280) = 0x%x\n", rtw_read32(padapter, 0x280));
3312                                                DBG_871X("dbg(0x284) = 0x%x\n", rtw_read32(padapter, 0x284));
3313                                                DBG_871X("dbg(0x288) = 0x%x\n", rtw_read32(padapter, 0x288));
3314
3315                                                DBG_871X("dbg(0x664) = 0x%x\n", rtw_read32(padapter, 0x664));
3316
3317
3318                                                DBG_871X("\n");
3319
3320                                                DBG_871X("dbg(0x430) = 0x%x\n", rtw_read32(padapter, 0x430));
3321                                                DBG_871X("dbg(0x438) = 0x%x\n", rtw_read32(padapter, 0x438));
3322
3323                                                DBG_871X("dbg(0x440) = 0x%x\n", rtw_read32(padapter, 0x440));
3324
3325                                                DBG_871X("dbg(0x458) = 0x%x\n", rtw_read32(padapter, 0x458));
3326
3327                                                DBG_871X("dbg(0x484) = 0x%x\n", rtw_read32(padapter, 0x484));
3328                                                DBG_871X("dbg(0x488) = 0x%x\n", rtw_read32(padapter, 0x488));
3329
3330                                                DBG_871X("dbg(0x444) = 0x%x\n", rtw_read32(padapter, 0x444));
3331                                                DBG_871X("dbg(0x448) = 0x%x\n", rtw_read32(padapter, 0x448));
3332                                                DBG_871X("dbg(0x44c) = 0x%x\n", rtw_read32(padapter, 0x44c));
3333                                                DBG_871X("dbg(0x450) = 0x%x\n", rtw_read32(padapter, 0x450));
3334                                        }
3335                                        break;
3336                        }
3337                        break;
3338                default:
3339                        DBG_871X("error dbg cmd!\n");
3340                        break;
3341        }
3342
3343
3344        return ret;
3345
3346}
3347
3348static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
3349{
3350        uint ret = 0;
3351        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3352
3353        switch (name) {
3354        case IEEE_PARAM_WPA_ENABLED:
3355
3356                padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
3357
3358                /* ret = ieee80211_wpa_enable(ieee, value); */
3359
3360                switch ((value)&0xff) {
3361                case 1 : /* WPA */
3362                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
3363                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
3364                        break;
3365                case 2: /* WPA2 */
3366                        padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
3367                        padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
3368                        break;
3369                }
3370
3371                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
3372
3373                break;
3374
3375        case IEEE_PARAM_TKIP_COUNTERMEASURES:
3376                /* ieee->tkip_countermeasures =value; */
3377                break;
3378
3379        case IEEE_PARAM_DROP_UNENCRYPTED:
3380        {
3381                /* HACK:
3382                 *
3383                 * wpa_supplicant calls set_wpa_enabled when the driver
3384                 * is loaded and unloaded, regardless of if WPA is being
3385                 * used.  No other calls are made which can be used to
3386                 * determine if encryption will be used or not prior to
3387                 * association being expected.  If encryption is not being
3388                 * used, drop_unencrypted is set to false, else true -- we
3389                 * can use this to determine if the CAP_PRIVACY_ON bit should
3390                 * be set.
3391                 */
3392                break;
3393
3394        }
3395        case IEEE_PARAM_PRIVACY_INVOKED:
3396
3397                /* ieee->privacy_invoked =value; */
3398
3399                break;
3400
3401        case IEEE_PARAM_AUTH_ALGS:
3402
3403                ret = wpa_set_auth_algs(dev, value);
3404
3405                break;
3406
3407        case IEEE_PARAM_IEEE_802_1X:
3408
3409                /* ieee->ieee802_1x =value; */
3410
3411                break;
3412
3413        case IEEE_PARAM_WPAX_SELECT:
3414
3415                /*  added for WPA2 mixed mode */
3416                /* DBG_871X(KERN_WARNING "------------------------>wpax value = %x\n", value); */
3417                /*
3418                spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
3419                ieee->wpax_type_set = 1;
3420                ieee->wpax_type_notify = value;
3421                spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
3422                */
3423
3424                break;
3425
3426        default:
3427
3428
3429
3430                ret = -EOPNOTSUPP;
3431
3432
3433                break;
3434
3435        }
3436
3437        return ret;
3438
3439}
3440
3441static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
3442{
3443        int ret = 0;
3444        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3445
3446        switch (command) {
3447                case IEEE_MLME_STA_DEAUTH:
3448
3449                        if (!rtw_set_802_11_disassociate(padapter))
3450                                ret = -1;
3451
3452                        break;
3453
3454                case IEEE_MLME_STA_DISASSOC:
3455
3456                        if (!rtw_set_802_11_disassociate(padapter))
3457                                ret = -1;
3458
3459                        break;
3460
3461                default:
3462                        ret = -EOPNOTSUPP;
3463                        break;
3464        }
3465
3466        return ret;
3467
3468}
3469
3470static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
3471{
3472        struct ieee_param *param;
3473        uint ret = 0;
3474
3475        /* down(&ieee->wx_sem); */
3476
3477        if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3478                ret = -EINVAL;
3479                goto out;
3480        }
3481
3482        param = rtw_malloc(p->length);
3483        if (param == NULL) {
3484                ret = -ENOMEM;
3485                goto out;
3486        }
3487
3488        if (copy_from_user(param, p->pointer, p->length)) {
3489                kfree(param);
3490                ret = -EFAULT;
3491                goto out;
3492        }
3493
3494        switch (param->cmd) {
3495
3496        case IEEE_CMD_SET_WPA_PARAM:
3497                ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
3498                break;
3499
3500        case IEEE_CMD_SET_WPA_IE:
3501                /* ret = wpa_set_wpa_ie(dev, param, p->length); */
3502                ret =  rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev), (char*)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
3503                break;
3504
3505        case IEEE_CMD_SET_ENCRYPTION:
3506                ret = wpa_set_encryption(dev, param, p->length);
3507                break;
3508
3509        case IEEE_CMD_MLME:
3510                ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
3511                break;
3512
3513        default:
3514                DBG_871X("Unknown WPA supplicant request: %d\n", param->cmd);
3515                ret = -EOPNOTSUPP;
3516                break;
3517
3518        }
3519
3520        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3521                ret = -EFAULT;
3522
3523        kfree(param);
3524
3525out:
3526
3527        /* up(&ieee->wx_sem); */
3528
3529        return ret;
3530
3531}
3532
3533static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
3534{
3535        int ret = 0;
3536        u32 wep_key_idx, wep_key_len, wep_total_len;
3537        struct ndis_802_11_wep   *pwep = NULL;
3538        struct sta_info *psta = NULL, *pbcmc_sta = NULL;
3539        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3540        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3541        struct security_priv* psecuritypriv =&(padapter->securitypriv);
3542        struct sta_priv *pstapriv = &padapter->stapriv;
3543
3544        DBG_871X("%s\n", __func__);
3545
3546        param->u.crypt.err = 0;
3547        param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3548
3549        /* sizeof(struct ieee_param) = 64 bytes; */
3550        /* if (param_len !=  (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) */
3551        if (param_len !=  sizeof(struct ieee_param) + param->u.crypt.key_len) {
3552                ret =  -EINVAL;
3553                goto exit;
3554        }
3555
3556        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3557            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3558            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3559                if (param->u.crypt.idx >= WEP_KEYS) {
3560                        ret = -EINVAL;
3561                        goto exit;
3562                }
3563        } else {
3564                psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3565                if (!psta) {
3566                        /* ret = -EINVAL; */
3567                        DBG_871X("rtw_set_encryption(), sta has already been removed or never been added\n");
3568                        goto exit;
3569                }
3570        }
3571
3572        if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
3573                /* todo:clear default encryption keys */
3574
3575                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
3576                psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
3577                psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
3578                psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
3579
3580                DBG_871X("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
3581
3582                goto exit;
3583        }
3584
3585
3586        if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
3587                DBG_871X("r871x_set_encryption, crypt.alg = WEP\n");
3588
3589                wep_key_idx = param->u.crypt.idx;
3590                wep_key_len = param->u.crypt.key_len;
3591
3592                DBG_871X("r871x_set_encryption, wep_key_idx =%d, len =%d\n", wep_key_idx, wep_key_len);
3593
3594                if ((wep_key_idx >= WEP_KEYS) || (wep_key_len<= 0)) {
3595                        ret = -EINVAL;
3596                        goto exit;
3597                }
3598
3599
3600                if (wep_key_len > 0) {
3601                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
3602                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
3603                        pwep = rtw_malloc(wep_total_len);
3604                        if (pwep == NULL) {
3605                                DBG_871X(" r871x_set_encryption: pwep allocate fail !!!\n");
3606                                goto exit;
3607                        }
3608
3609                        memset(pwep, 0, wep_total_len);
3610
3611                        pwep->KeyLength = wep_key_len;
3612                        pwep->Length = wep_total_len;
3613
3614                }
3615
3616                pwep->KeyIndex = wep_key_idx;
3617
3618                memcpy(pwep->KeyMaterial,  param->u.crypt.key, pwep->KeyLength);
3619
3620                if (param->u.crypt.set_tx) {
3621                        DBG_871X("wep, set_tx = 1\n");
3622
3623                        psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
3624                        psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
3625                        psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
3626                        psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
3627
3628                        if (pwep->KeyLength == 13) {
3629                                psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
3630                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
3631                        }
3632
3633
3634                        psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
3635
3636                        memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
3637
3638                        psecuritypriv->dot11DefKeylen[wep_key_idx]=pwep->KeyLength;
3639
3640                        rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 1);
3641                } else {
3642                        DBG_871X("wep, set_tx = 0\n");
3643
3644                        /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
3645                        /* psecuritypriv->dot11PrivacyKeyIndex =keyid", but can rtw_set_key to cam */
3646
3647                        memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
3648
3649                        psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
3650
3651                        rtw_ap_set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx, 0);
3652                }
3653
3654                goto exit;
3655
3656        }
3657
3658
3659        if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /*  group key */
3660                if (param->u.crypt.set_tx == 1) {
3661                        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3662                                DBG_871X("%s, set group_key, WEP\n", __func__);
3663
3664                                memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
3665
3666                                psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
3667                                if (param->u.crypt.key_len == 13)
3668                                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
3669
3670                        } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3671                                DBG_871X("%s, set group_key, TKIP\n", __func__);
3672
3673                                psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
3674
3675                                memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
3676
3677                                /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3678                                /* set mic key */
3679                                memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
3680                                memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
3681
3682                                psecuritypriv->busetkipkey = true;
3683
3684                        }
3685                        else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3686                                DBG_871X("%s, set group_key, CCMP\n", __func__);
3687
3688                                psecuritypriv->dot118021XGrpPrivacy = _AES_;
3689
3690                                memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
3691                        } else {
3692                                DBG_871X("%s, set group_key, none\n", __func__);
3693
3694                                psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
3695                        }
3696
3697                        psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
3698
3699                        psecuritypriv->binstallGrpkey = true;
3700
3701                        psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
3702
3703                        rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
3704
3705                        pbcmc_sta =rtw_get_bcmc_stainfo(padapter);
3706                        if (pbcmc_sta) {
3707                                pbcmc_sta->ieee8021x_blocked = false;
3708                                pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
3709                        }
3710                }
3711
3712                goto exit;
3713
3714        }
3715
3716        if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /*  psk/802_1x */
3717                if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
3718                        if (param->u.crypt.set_tx == 1) {
3719                                memcpy(psta->dot118021x_UncstKey.skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
3720
3721                                if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3722                                        DBG_871X("%s, set pairwise key, WEP\n", __func__);
3723
3724                                        psta->dot118021XPrivacy = _WEP40_;
3725                                        if (param->u.crypt.key_len == 13)
3726                                                psta->dot118021XPrivacy = _WEP104_;
3727                                } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3728                                        DBG_871X("%s, set pairwise key, TKIP\n", __func__);
3729
3730                                        psta->dot118021XPrivacy = _TKIP_;
3731
3732                                        /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3733                                        /* set mic key */
3734                                        memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
3735                                        memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
3736
3737                                        psecuritypriv->busetkipkey = true;
3738
3739                                } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3740
3741                                        DBG_871X("%s, set pairwise key, CCMP\n", __func__);
3742
3743                                        psta->dot118021XPrivacy = _AES_;
3744                                } else {
3745                                        DBG_871X("%s, set pairwise key, none\n", __func__);
3746
3747                                        psta->dot118021XPrivacy = _NO_PRIVACY_;
3748                                }
3749
3750                                rtw_ap_set_pairwise_key(padapter, psta);
3751
3752                                psta->ieee8021x_blocked = false;
3753
3754                        } else { /* group key??? */
3755                                if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3756                                        memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
3757
3758                                        psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
3759                                        if (param->u.crypt.key_len == 13)
3760                                                psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
3761                                } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3762                                        psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
3763
3764                                        memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
3765
3766                                        /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
3767                                        /* set mic key */
3768                                        memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
3769                                        memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
3770
3771                                        psecuritypriv->busetkipkey = true;
3772
3773                                } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3774                                        psecuritypriv->dot118021XGrpPrivacy = _AES_;
3775
3776                                        memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len>16 ?16:param->u.crypt.key_len));
3777                                } else {
3778                                        psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
3779                                }
3780
3781                                psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
3782
3783                                psecuritypriv->binstallGrpkey = true;
3784
3785                                psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/*  */
3786
3787                                rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
3788
3789                                pbcmc_sta =rtw_get_bcmc_stainfo(padapter);
3790                                if (pbcmc_sta) {
3791                                        pbcmc_sta->ieee8021x_blocked = false;
3792                                        pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
3793                                }
3794                        }
3795                }
3796        }
3797
3798exit:
3799        kfree(pwep);
3800
3801        return ret;
3802
3803}
3804
3805static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
3806{
3807        int ret = 0;
3808        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3809        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3810        struct sta_priv *pstapriv = &padapter->stapriv;
3811        unsigned char *pbuf = param->u.bcn_ie.buf;
3812
3813
3814        DBG_871X("%s, len =%d\n", __func__, len);
3815
3816        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
3817                return -EINVAL;
3818
3819        memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
3820
3821        if ((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<= 0))
3822                pstapriv->max_num_sta = NUM_STA;
3823
3824
3825        if (rtw_check_beacon_data(padapter, pbuf,  (len-12-2)) == _SUCCESS)/*  12 = param header, 2:no packed */
3826                ret = 0;
3827        else
3828                ret = -EINVAL;
3829
3830
3831        return ret;
3832
3833}
3834
3835static int rtw_hostapd_sta_flush(struct net_device *dev)
3836{
3837        /* _irqL irqL; */
3838        /* struct list_head     *phead, *plist; */
3839        /* struct sta_info *psta = NULL; */
3840        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3841        /* struct sta_priv *pstapriv = &padapter->stapriv; */
3842
3843        DBG_871X("%s\n", __func__);
3844
3845        flush_all_cam_entry(padapter);  /* clear CAM */
3846
3847        return rtw_sta_flush(padapter);
3848
3849}
3850
3851static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
3852{
3853        int ret = 0;
3854        struct sta_info *psta = NULL;
3855        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3856        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3857        struct sta_priv *pstapriv = &padapter->stapriv;
3858
3859        DBG_871X("rtw_add_sta(aid =%d) =" MAC_FMT "\n", param->u.add_sta.aid, MAC_ARG(param->sta_addr));
3860
3861        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
3862                return -EINVAL;
3863
3864        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3865            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3866            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3867                return -EINVAL;
3868        }
3869
3870/*
3871        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3872        if (psta)
3873        {
3874                DBG_871X("rtw_add_sta(), free has been added psta =%p\n", psta);
3875                spin_lock_bh(&(pstapriv->sta_hash_lock));
3876                rtw_free_stainfo(padapter,  psta);
3877                spin_unlock_bh(&(pstapriv->sta_hash_lock));
3878
3879                psta = NULL;
3880        }
3881*/
3882        /* psta = rtw_alloc_stainfo(pstapriv, param->sta_addr); */
3883        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3884        if (psta) {
3885                int flags = param->u.add_sta.flags;
3886
3887                /* DBG_871X("rtw_add_sta(), init sta's variables, psta =%p\n", psta); */
3888
3889                psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
3890
3891                memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
3892
3893
3894                /* check wmm cap. */
3895                if (WLAN_STA_WME&flags)
3896                        psta->qos_option = 1;
3897                else
3898                        psta->qos_option = 0;
3899
3900                if (pmlmepriv->qospriv.qos_option == 0)
3901                        psta->qos_option = 0;
3902
3903                /* chec 802.11n ht cap. */
3904                if (WLAN_STA_HT&flags) {
3905                        psta->htpriv.ht_option = true;
3906                        psta->qos_option = 1;
3907                        memcpy((void*)&psta->htpriv.ht_cap, (void*)&param->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
3908                } else {
3909                        psta->htpriv.ht_option = false;
3910                }
3911
3912                if (pmlmepriv->htpriv.ht_option == false)
3913                        psta->htpriv.ht_option = false;
3914
3915                update_sta_info_apmode(padapter, psta);
3916
3917
3918        } else {
3919                ret = -ENOMEM;
3920        }
3921
3922        return ret;
3923
3924}
3925
3926static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
3927{
3928        int ret = 0;
3929        struct sta_info *psta = NULL;
3930        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3931        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3932        struct sta_priv *pstapriv = &padapter->stapriv;
3933
3934        DBG_871X("rtw_del_sta =" MAC_FMT "\n", MAC_ARG(param->sta_addr));
3935
3936        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
3937                return -EINVAL;
3938
3939        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3940            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3941            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3942                return -EINVAL;
3943        }
3944
3945        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
3946        if (psta) {
3947                u8 updated =false;
3948
3949                /* DBG_871X("free psta =%p, aid =%d\n", psta, psta->aid); */
3950
3951                spin_lock_bh(&pstapriv->asoc_list_lock);
3952                if (list_empty(&psta->asoc_list) ==false) {
3953                        list_del_init(&psta->asoc_list);
3954                        pstapriv->asoc_list_cnt--;
3955                        updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
3956
3957                }
3958                spin_unlock_bh(&pstapriv->asoc_list_lock);
3959
3960                associated_clients_update(padapter, updated);
3961
3962                psta = NULL;
3963
3964        } else {
3965                DBG_871X("rtw_del_sta(), sta has already been removed or never been added\n");
3966
3967                /* ret = -1; */
3968        }
3969
3970
3971        return ret;
3972
3973}
3974
3975static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
3976{
3977        int ret = 0;
3978        struct sta_info *psta = NULL;
3979        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
3980        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3981        struct sta_priv *pstapriv = &padapter->stapriv;
3982        struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
3983        struct sta_data *psta_data = (struct sta_data *)param_ex->data;
3984
3985        DBG_871X("rtw_ioctl_get_sta_info, sta_addr: " MAC_FMT "\n", MAC_ARG(param_ex->sta_addr));
3986
3987        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
3988                return -EINVAL;
3989
3990        if (param_ex->sta_addr[0] == 0xff && param_ex->sta_addr[1] == 0xff &&
3991            param_ex->sta_addr[2] == 0xff && param_ex->sta_addr[3] == 0xff &&
3992            param_ex->sta_addr[4] == 0xff && param_ex->sta_addr[5] == 0xff) {
3993                return -EINVAL;
3994        }
3995
3996        psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
3997        if (psta) {
3998                psta_data->aid = (u16)psta->aid;
3999                psta_data->capability = psta->capability;
4000                psta_data->flags = psta->flags;
4001
4002/*
4003                nonerp_set : BIT(0)
4004                no_short_slot_time_set : BIT(1)
4005                no_short_preamble_set : BIT(2)
4006                no_ht_gf_set : BIT(3)
4007                no_ht_set : BIT(4)
4008                ht_20mhz_set : BIT(5)
4009*/
4010
4011                psta_data->sta_set =((psta->nonerp_set) |
4012                                                        (psta->no_short_slot_time_set <<1) |
4013                                                        (psta->no_short_preamble_set <<2) |
4014                                                        (psta->no_ht_gf_set <<3) |
4015                                                        (psta->no_ht_set <<4) |
4016                                                        (psta->ht_20mhz_set <<5));
4017
4018                psta_data->tx_supp_rates_len =  psta->bssratelen;
4019                memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
4020                memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap));
4021                psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
4022                psta_data->rx_bytes = psta->sta_stats.rx_bytes;
4023                psta_data->rx_drops = psta->sta_stats.rx_drops;
4024
4025                psta_data->tx_pkts = psta->sta_stats.tx_pkts;
4026                psta_data->tx_bytes = psta->sta_stats.tx_bytes;
4027                psta_data->tx_drops = psta->sta_stats.tx_drops;
4028
4029
4030        } else {
4031                ret = -1;
4032        }
4033
4034        return ret;
4035
4036}
4037
4038static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
4039{
4040        int ret = 0;
4041        struct sta_info *psta = NULL;
4042        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4043        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4044        struct sta_priv *pstapriv = &padapter->stapriv;
4045
4046        DBG_871X("rtw_get_sta_wpaie, sta_addr: " MAC_FMT "\n", MAC_ARG(param->sta_addr));
4047
4048        if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)) != true)
4049                return -EINVAL;
4050
4051        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
4052            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
4053            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
4054                return -EINVAL;
4055        }
4056
4057        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
4058        if (psta) {
4059                if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
4060                        int wpa_ie_len;
4061                        int copy_len;
4062
4063                        wpa_ie_len = psta->wpa_ie[1];
4064
4065                        copy_len = ((wpa_ie_len+2) > sizeof(psta->wpa_ie)) ? (sizeof(psta->wpa_ie)):(wpa_ie_len+2);
4066
4067                        param->u.wpa_ie.len = copy_len;
4068
4069                        memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
4070                } else {
4071                        /* ret = -1; */
4072                        DBG_871X("sta's wpa_ie is NONE\n");
4073                }
4074        } else {
4075                ret = -1;
4076        }
4077
4078        return ret;
4079
4080}
4081
4082static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
4083{
4084        int ret = 0;
4085        unsigned char wps_oui[4]={0x0, 0x50, 0xf2, 0x04};
4086        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4087        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4088        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
4089        int ie_len;
4090
4091        DBG_871X("%s, len =%d\n", __func__, len);
4092
4093        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4094                return -EINVAL;
4095
4096        ie_len = len-12-2;/*  12 = param header, 2:no packed */
4097
4098
4099        kfree(pmlmepriv->wps_beacon_ie);
4100        pmlmepriv->wps_beacon_ie = NULL;
4101
4102        if (ie_len>0) {
4103                pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
4104                pmlmepriv->wps_beacon_ie_len = ie_len;
4105                if (pmlmepriv->wps_beacon_ie == NULL) {
4106                        DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
4107                        return -EINVAL;
4108                }
4109
4110                memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
4111
4112                update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
4113
4114                pmlmeext->bstart_bss = true;
4115        }
4116
4117
4118        return ret;
4119
4120}
4121
4122static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
4123{
4124        int ret = 0;
4125        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4126        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4127        int ie_len;
4128
4129        DBG_871X("%s, len =%d\n", __func__, len);
4130
4131        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4132                return -EINVAL;
4133
4134        ie_len = len-12-2;/*  12 = param header, 2:no packed */
4135
4136
4137        kfree(pmlmepriv->wps_probe_resp_ie);
4138        pmlmepriv->wps_probe_resp_ie = NULL;
4139
4140        if (ie_len>0) {
4141                pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
4142                pmlmepriv->wps_probe_resp_ie_len = ie_len;
4143                if (pmlmepriv->wps_probe_resp_ie == NULL) {
4144                        DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
4145                        return -EINVAL;
4146                }
4147                memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
4148        }
4149
4150
4151        return ret;
4152
4153}
4154
4155static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
4156{
4157        int ret = 0;
4158        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4159        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4160        int ie_len;
4161
4162        DBG_871X("%s, len =%d\n", __func__, len);
4163
4164        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4165                return -EINVAL;
4166
4167        ie_len = len-12-2;/*  12 = param header, 2:no packed */
4168
4169
4170        kfree(pmlmepriv->wps_assoc_resp_ie);
4171        pmlmepriv->wps_assoc_resp_ie = NULL;
4172
4173        if (ie_len>0) {
4174                pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
4175                pmlmepriv->wps_assoc_resp_ie_len = ie_len;
4176                if (pmlmepriv->wps_assoc_resp_ie == NULL) {
4177                        DBG_871X("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
4178                        return -EINVAL;
4179                }
4180
4181                memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
4182        }
4183
4184
4185        return ret;
4186
4187}
4188
4189static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
4190{
4191        int ret = 0;
4192        struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
4193        struct mlme_priv *mlmepriv = &(adapter->mlmepriv);
4194        struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
4195        struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
4196        int ie_len;
4197        u8 *ssid_ie;
4198        char ssid[NDIS_802_11_LENGTH_SSID + 1];
4199        sint ssid_len;
4200        u8 ignore_broadcast_ssid;
4201
4202        if (check_fwstate(mlmepriv, WIFI_AP_STATE) != true)
4203                return -EPERM;
4204
4205        if (param->u.bcn_ie.reserved[0] != 0xea)
4206                return -EINVAL;
4207
4208        mlmeinfo->hidden_ssid_mode = ignore_broadcast_ssid = param->u.bcn_ie.reserved[1];
4209
4210        ie_len = len-12-2;/*  12 = param header, 2:no packed */
4211        ssid_ie = rtw_get_ie(param->u.bcn_ie.buf,  WLAN_EID_SSID, &ssid_len, ie_len);
4212
4213        if (ssid_ie && ssid_len > 0 && ssid_len <= NDIS_802_11_LENGTH_SSID) {
4214                struct wlan_bssid_ex *pbss_network = &mlmepriv->cur_network.network;
4215                struct wlan_bssid_ex *pbss_network_ext = &mlmeinfo->network;
4216
4217                memcpy(ssid, ssid_ie+2, ssid_len);
4218                ssid[ssid_len] = 0x0;
4219
4220                if (0)
4221                        DBG_871X(FUNC_ADPT_FMT" ssid:(%s,%d), from ie:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
4222                                 ssid, ssid_len,
4223                                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
4224                                 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
4225
4226                memcpy(pbss_network->Ssid.Ssid, (void *)ssid, ssid_len);
4227                pbss_network->Ssid.SsidLength = ssid_len;
4228                memcpy(pbss_network_ext->Ssid.Ssid, (void *)ssid, ssid_len);
4229                pbss_network_ext->Ssid.SsidLength = ssid_len;
4230
4231                if (0)
4232                        DBG_871X(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
4233                                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
4234                                 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
4235        }
4236
4237        DBG_871X(FUNC_ADPT_FMT" ignore_broadcast_ssid:%d, %s,%d\n", FUNC_ADPT_ARG(adapter),
4238                ignore_broadcast_ssid, ssid, ssid_len);
4239
4240        return ret;
4241}
4242
4243static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
4244{
4245        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4246        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4247
4248        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4249                return -EINVAL;
4250
4251        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
4252            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
4253            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
4254                return -EINVAL;
4255        }
4256
4257        return rtw_acl_remove_sta(padapter, param->sta_addr);
4258
4259}
4260
4261static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
4262{
4263        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4264        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4265
4266        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4267                return -EINVAL;
4268
4269        if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
4270            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
4271            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
4272                return -EINVAL;
4273        }
4274
4275        return rtw_acl_add_sta(padapter, param->sta_addr);
4276
4277}
4278
4279static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
4280{
4281        int ret = 0;
4282        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4283        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4284
4285        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
4286                return -EINVAL;
4287
4288        rtw_set_macaddr_acl(padapter, param->u.mlme.command);
4289
4290        return ret;
4291}
4292
4293static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
4294{
4295        struct ieee_param *param;
4296        int ret = 0;
4297        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4298
4299        /* DBG_871X("%s\n", __func__); */
4300
4301        /*
4302        * this function is expect to call in master mode, which allows no power saving
4303        * so, we just check hw_init_completed
4304        */
4305
4306        if (padapter->hw_init_completed ==false) {
4307                ret = -EPERM;
4308                goto out;
4309        }
4310
4311
4312        /* if (p->length < sizeof(struct ieee_param) || !p->pointer) { */
4313        if (!p->pointer) {
4314                ret = -EINVAL;
4315                goto out;
4316        }
4317
4318        param = rtw_malloc(p->length);
4319        if (param == NULL) {
4320                ret = -ENOMEM;
4321                goto out;
4322        }
4323
4324        if (copy_from_user(param, p->pointer, p->length)) {
4325                kfree(param);
4326                ret = -EFAULT;
4327                goto out;
4328        }
4329
4330        /* DBG_871X("%s, cmd =%d\n", __func__, param->cmd); */
4331
4332        switch (param->cmd) {
4333                case RTL871X_HOSTAPD_FLUSH:
4334
4335                        ret = rtw_hostapd_sta_flush(dev);
4336
4337                        break;
4338
4339                case RTL871X_HOSTAPD_ADD_STA:
4340
4341                        ret = rtw_add_sta(dev, param);
4342
4343                        break;
4344
4345                case RTL871X_HOSTAPD_REMOVE_STA:
4346
4347                        ret = rtw_del_sta(dev, param);
4348
4349                        break;
4350
4351                case RTL871X_HOSTAPD_SET_BEACON:
4352
4353                        ret = rtw_set_beacon(dev, param, p->length);
4354
4355                        break;
4356
4357                case RTL871X_SET_ENCRYPTION:
4358
4359                        ret = rtw_set_encryption(dev, param, p->length);
4360
4361                        break;
4362
4363                case RTL871X_HOSTAPD_GET_WPAIE_STA:
4364
4365                        ret = rtw_get_sta_wpaie(dev, param);
4366
4367                        break;
4368
4369                case RTL871X_HOSTAPD_SET_WPS_BEACON:
4370
4371                        ret = rtw_set_wps_beacon(dev, param, p->length);
4372
4373                        break;
4374
4375                case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
4376
4377                        ret = rtw_set_wps_probe_resp(dev, param, p->length);
4378
4379                        break;
4380
4381                case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
4382
4383                        ret = rtw_set_wps_assoc_resp(dev, param, p->length);
4384
4385                        break;
4386
4387                case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
4388
4389                        ret = rtw_set_hidden_ssid(dev, param, p->length);
4390
4391                        break;
4392
4393                case RTL871X_HOSTAPD_GET_INFO_STA:
4394
4395                        ret = rtw_ioctl_get_sta_data(dev, param, p->length);
4396
4397                        break;
4398
4399                case RTL871X_HOSTAPD_SET_MACADDR_ACL:
4400
4401                        ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
4402
4403                        break;
4404
4405                case RTL871X_HOSTAPD_ACL_ADD_STA:
4406
4407                        ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
4408
4409                        break;
4410
4411                case RTL871X_HOSTAPD_ACL_REMOVE_STA:
4412
4413                        ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
4414
4415                        break;
4416
4417                default:
4418                        DBG_871X("Unknown hostapd request: %d\n", param->cmd);
4419                        ret = -EOPNOTSUPP;
4420                        break;
4421
4422        }
4423
4424        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
4425                ret = -EFAULT;
4426
4427
4428        kfree(param);
4429
4430out:
4431
4432        return ret;
4433
4434}
4435
4436static int rtw_wx_set_priv(struct net_device *dev,
4437                                struct iw_request_info *info,
4438                                union iwreq_data *awrq,
4439                                char *extra)
4440{
4441
4442#ifdef DEBUG_RTW_WX_SET_PRIV
4443        char *ext_dbg;
4444#endif
4445
4446        int ret = 0;
4447        int len = 0;
4448        char *ext;
4449
4450        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4451        struct iw_point *dwrq = (struct iw_point*)awrq;
4452
4453        /* RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, ("+rtw_wx_set_priv\n")); */
4454        if (dwrq->length == 0)
4455                return -EFAULT;
4456
4457        len = dwrq->length;
4458        if (!(ext = vmalloc(len)))
4459                return -ENOMEM;
4460
4461        if (copy_from_user(ext, dwrq->pointer, len)) {
4462                vfree(ext);
4463                return -EFAULT;
4464        }
4465
4466
4467        /* RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_notice_, */
4468        /*       ("rtw_wx_set_priv: %s req =%s\n", */
4469        /*        dev->name, ext)); */
4470
4471        #ifdef DEBUG_RTW_WX_SET_PRIV
4472        if (!(ext_dbg = vmalloc(len))) {
4473                vfree(ext, len);
4474                return -ENOMEM;
4475        }
4476
4477        memcpy(ext_dbg, ext, len);
4478        #endif
4479
4480        /* added for wps2.0 @20110524 */
4481        if (dwrq->flags == 0x8766 && len > 8) {
4482                u32 cp_sz;
4483                struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4484                u8 *probereq_wpsie = ext;
4485                int probereq_wpsie_len = len;
4486                u8 wps_oui[4]={0x0, 0x50, 0xf2, 0x04};
4487
4488                if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
4489                        (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
4490                        cp_sz = probereq_wpsie_len>MAX_WPS_IE_LEN ? MAX_WPS_IE_LEN:probereq_wpsie_len;
4491
4492                        if (pmlmepriv->wps_probe_req_ie) {
4493                                pmlmepriv->wps_probe_req_ie_len = 0;
4494                                kfree(pmlmepriv->wps_probe_req_ie);
4495                                pmlmepriv->wps_probe_req_ie = NULL;
4496                        }
4497
4498                        pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
4499                        if (pmlmepriv->wps_probe_req_ie == NULL) {
4500                                printk("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
4501                                ret =  -EINVAL;
4502                                goto FREE_EXT;
4503
4504                        }
4505
4506                        memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
4507                        pmlmepriv->wps_probe_req_ie_len = cp_sz;
4508
4509                }
4510
4511                goto FREE_EXT;
4512
4513        }
4514
4515        if (len >= WEXT_CSCAN_HEADER_SIZE
4516                && !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
4517                ret = rtw_wx_set_scan(dev, info, awrq, ext);
4518                goto FREE_EXT;
4519        }
4520
4521FREE_EXT:
4522
4523        vfree(ext);
4524        #ifdef DEBUG_RTW_WX_SET_PRIV
4525        vfree(ext_dbg);
4526        #endif
4527
4528        /* DBG_871X("rtw_wx_set_priv: (SIOCSIWPRIV) %s ret =%d\n", */
4529        /*              dev->name, ret); */
4530
4531        return ret;
4532
4533}
4534
4535static int rtw_pm_set(struct net_device *dev,
4536                               struct iw_request_info *info,
4537                               union iwreq_data *wrqu, char *extra)
4538{
4539        int ret = 0;
4540        unsigned        mode = 0;
4541        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4542
4543        DBG_871X("[%s] extra = %s\n", __func__, extra);
4544
4545        if (!memcmp(extra, "lps =", 4)) {
4546                sscanf(extra+4, "%u", &mode);
4547                ret = rtw_pm_set_lps(padapter, mode);
4548        } else if (!memcmp(extra, "ips =", 4)) {
4549                sscanf(extra+4, "%u", &mode);
4550                ret = rtw_pm_set_ips(padapter, mode);
4551        } else {
4552                ret = -EINVAL;
4553        }
4554
4555        return ret;
4556}
4557
4558static int rtw_mp_efuse_get(struct net_device *dev,
4559                        struct iw_request_info *info,
4560                        union iwreq_data *wdata, char *extra)
4561{
4562        int err = 0;
4563        return err;
4564}
4565
4566static int rtw_mp_efuse_set(struct net_device *dev,
4567                        struct iw_request_info *info,
4568                        union iwreq_data *wdata, char *extra)
4569{
4570        int err = 0;
4571        return err;
4572}
4573
4574static int rtw_tdls(struct net_device *dev,
4575                                struct iw_request_info *info,
4576                                union iwreq_data *wrqu, char *extra)
4577{
4578        int ret = 0;
4579        return ret;
4580}
4581
4582
4583static int rtw_tdls_get(struct net_device *dev,
4584                                struct iw_request_info *info,
4585                                union iwreq_data *wrqu, char *extra)
4586{
4587        int ret = 0;
4588        return ret;
4589}
4590
4591
4592
4593
4594
4595#ifdef CONFIG_INTEL_WIDI
4596static int rtw_widi_set(struct net_device *dev,
4597                               struct iw_request_info *info,
4598                               union iwreq_data *wrqu, char *extra)
4599{
4600        int ret = 0;
4601        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4602
4603        process_intel_widi_cmd(padapter, extra);
4604
4605        return ret;
4606}
4607
4608static int rtw_widi_set_probe_request(struct net_device *dev,
4609                               struct iw_request_info *info,
4610                               union iwreq_data *wrqu, char *extra)
4611{
4612        int     ret = 0;
4613        u8 *pbuf = NULL;
4614        struct adapter  *padapter = (struct adapter *)rtw_netdev_priv(dev);
4615
4616        pbuf = rtw_malloc(sizeof(l2_msg_t));
4617        if (pbuf) {
4618                if (copy_from_user(pbuf, wrqu->data.pointer, wrqu->data.length))
4619                        ret = -EFAULT;
4620                /* memcpy(pbuf, wrqu->data.pointer, wrqu->data.length); */
4621
4622                if (wrqu->data.flags == 0)
4623                        intel_widi_wk_cmd(padapter, INTEL_WIDI_ISSUE_PROB_WK, pbuf, sizeof(l2_msg_t));
4624                else if (wrqu->data.flags == 1)
4625                        rtw_set_wfd_rds_sink_info(padapter, (l2_msg_t *)pbuf);
4626        }
4627        return ret;
4628}
4629#endif /*  CONFIG_INTEL_WIDI */
4630
4631static int rtw_test(
4632        struct net_device *dev,
4633        struct iw_request_info *info,
4634        union iwreq_data *wrqu, char *extra)
4635{
4636        u32 len;
4637        u8 *pbuf, *pch;
4638        char *ptmp;
4639        u8 *delim = ",";
4640        struct adapter *padapter = rtw_netdev_priv(dev);
4641
4642
4643        DBG_871X("+%s\n", __func__);
4644        len = wrqu->data.length;
4645
4646        pbuf = rtw_zmalloc(len);
4647        if (pbuf == NULL) {
4648                DBG_871X("%s: no memory!\n", __func__);
4649                return -ENOMEM;
4650        }
4651
4652        if (copy_from_user(pbuf, wrqu->data.pointer, len)) {
4653                kfree(pbuf);
4654                DBG_871X("%s: copy from user fail!\n", __func__);
4655                return -EFAULT;
4656        }
4657        DBG_871X("%s: string =\"%s\"\n", __func__, pbuf);
4658
4659        ptmp = (char*)pbuf;
4660        pch = strsep(&ptmp, delim);
4661        if ((pch == NULL) || (strlen(pch) == 0)) {
4662                kfree(pbuf);
4663                DBG_871X("%s: parameter error(level 1)!\n", __func__);
4664                return -EFAULT;
4665        }
4666
4667        if (strcmp(pch, "bton") == 0)
4668                rtw_btcoex_SetManualControl(padapter, false);
4669
4670        if (strcmp(pch, "btoff") == 0)
4671                rtw_btcoex_SetManualControl(padapter, true);
4672
4673        if (strcmp(pch, "h2c") == 0) {
4674                u8 param[8];
4675                u8 count = 0;
4676                u32 tmp;
4677                u8 i;
4678                u32 pos;
4679                s32 ret;
4680
4681
4682                do {
4683                        pch = strsep(&ptmp, delim);
4684                        if ((pch == NULL) || (strlen(pch) == 0))
4685                                break;
4686
4687                        sscanf(pch, "%x", &tmp);
4688                        param[count++] = (u8)tmp;
4689                } while (count < 8);
4690
4691                if (count == 0) {
4692                        kfree(pbuf);
4693                        DBG_871X("%s: parameter error(level 2)!\n", __func__);
4694                        return -EFAULT;
4695                }
4696
4697                ret = rtw_hal_fill_h2c_cmd(padapter, param[0], count-1, &param[1]);
4698
4699                pos = sprintf(extra, "H2C ID = 0x%02x content =", param[0]);
4700                for (i = 1; i<count; i++)
4701                        pos += sprintf(extra+pos, "%02x,", param[i]);
4702                extra[pos] = 0;
4703                pos--;
4704                pos += sprintf(extra+pos, " %s", ret == _FAIL?"FAIL":"OK");
4705
4706                wrqu->data.length = strlen(extra) + 1;
4707        }
4708
4709        kfree(pbuf);
4710        return 0;
4711}
4712
4713static iw_handler rtw_handlers[] = {
4714        NULL,                                   /* SIOCSIWCOMMIT */
4715        rtw_wx_get_name,                /* SIOCGIWNAME */
4716        dummy,                                  /* SIOCSIWNWID */
4717        dummy,                                  /* SIOCGIWNWID */
4718        rtw_wx_set_freq,                /* SIOCSIWFREQ */
4719        rtw_wx_get_freq,                /* SIOCGIWFREQ */
4720        rtw_wx_set_mode,                /* SIOCSIWMODE */
4721        rtw_wx_get_mode,                /* SIOCGIWMODE */
4722        dummy,                                  /* SIOCSIWSENS */
4723        rtw_wx_get_sens,                /* SIOCGIWSENS */
4724        NULL,                                   /* SIOCSIWRANGE */
4725        rtw_wx_get_range,               /* SIOCGIWRANGE */
4726        rtw_wx_set_priv,                /* SIOCSIWPRIV */
4727        NULL,                                   /* SIOCGIWPRIV */
4728        NULL,                                   /* SIOCSIWSTATS */
4729        NULL,                                   /* SIOCGIWSTATS */
4730        dummy,                                  /* SIOCSIWSPY */
4731        dummy,                                  /* SIOCGIWSPY */
4732        NULL,                                   /* SIOCGIWTHRSPY */
4733        NULL,                                   /* SIOCWIWTHRSPY */
4734        rtw_wx_set_wap,         /* SIOCSIWAP */
4735        rtw_wx_get_wap,         /* SIOCGIWAP */
4736        rtw_wx_set_mlme,                /* request MLME operation; uses struct iw_mlme */
4737        dummy,                                  /* SIOCGIWAPLIST -- depricated */
4738        rtw_wx_set_scan,                /* SIOCSIWSCAN */
4739        rtw_wx_get_scan,                /* SIOCGIWSCAN */
4740        rtw_wx_set_essid,               /* SIOCSIWESSID */
4741        rtw_wx_get_essid,               /* SIOCGIWESSID */
4742        dummy,                                  /* SIOCSIWNICKN */
4743        rtw_wx_get_nick,                /* SIOCGIWNICKN */
4744        NULL,                                   /* -- hole -- */
4745        NULL,                                   /* -- hole -- */
4746        rtw_wx_set_rate,                /* SIOCSIWRATE */
4747        rtw_wx_get_rate,                /* SIOCGIWRATE */
4748        rtw_wx_set_rts,                 /* SIOCSIWRTS */
4749        rtw_wx_get_rts,                 /* SIOCGIWRTS */
4750        rtw_wx_set_frag,                /* SIOCSIWFRAG */
4751        rtw_wx_get_frag,                /* SIOCGIWFRAG */
4752        dummy,                                  /* SIOCSIWTXPOW */
4753        dummy,                                  /* SIOCGIWTXPOW */
4754        dummy,                                  /* SIOCSIWRETRY */
4755        rtw_wx_get_retry,               /* SIOCGIWRETRY */
4756        rtw_wx_set_enc,                 /* SIOCSIWENCODE */
4757        rtw_wx_get_enc,                 /* SIOCGIWENCODE */
4758        dummy,                                  /* SIOCSIWPOWER */
4759        rtw_wx_get_power,               /* SIOCGIWPOWER */
4760        NULL,                                   /*---hole---*/
4761        NULL,                                   /*---hole---*/
4762        rtw_wx_set_gen_ie,              /* SIOCSIWGENIE */
4763        NULL,                                   /* SIOCGWGENIE */
4764        rtw_wx_set_auth,                /* SIOCSIWAUTH */
4765        NULL,                                   /* SIOCGIWAUTH */
4766        rtw_wx_set_enc_ext,             /* SIOCSIWENCODEEXT */
4767        NULL,                                   /* SIOCGIWENCODEEXT */
4768        rtw_wx_set_pmkid,               /* SIOCSIWPMKSA */
4769        NULL,                                   /*---hole---*/
4770};
4771
4772static const struct iw_priv_args rtw_private_args[] = {
4773        {
4774                SIOCIWFIRSTPRIV + 0x0,
4775                IW_PRIV_TYPE_CHAR | 0x7FF, 0, "write"
4776        },
4777        {
4778                SIOCIWFIRSTPRIV + 0x1,
4779                IW_PRIV_TYPE_CHAR | 0x7FF,
4780                IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "read"
4781        },
4782        {
4783                SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
4784        },
4785        {
4786                SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
4787        },
4788        {
4789                SIOCIWFIRSTPRIV + 0x4,
4790                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
4791        },
4792        {
4793                SIOCIWFIRSTPRIV + 0x5,
4794                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setpid"
4795        },
4796        {
4797                SIOCIWFIRSTPRIV + 0x6,
4798                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
4799        },
4800/* for PLATFORM_MT53XX */
4801        {
4802                SIOCIWFIRSTPRIV + 0x7,
4803                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "get_sensitivity"
4804        },
4805        {
4806                SIOCIWFIRSTPRIV + 0x8,
4807                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_prob_req_ie"
4808        },
4809        {
4810                SIOCIWFIRSTPRIV + 0x9,
4811                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_assoc_req_ie"
4812        },
4813
4814/* for RTK_DMP_PLATFORM */
4815        {
4816                SIOCIWFIRSTPRIV + 0xA,
4817                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "channel_plan"
4818        },
4819
4820        {
4821                SIOCIWFIRSTPRIV + 0xB,
4822                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dbg"
4823        },
4824        {
4825                SIOCIWFIRSTPRIV + 0xC,
4826                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "rfw"
4827        },
4828        {
4829                SIOCIWFIRSTPRIV + 0xD,
4830                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "rfr"
4831        },
4832        {
4833                SIOCIWFIRSTPRIV + 0x10,
4834                IW_PRIV_TYPE_CHAR | 1024, 0, "p2p_set"
4835        },
4836        {
4837                SIOCIWFIRSTPRIV + 0x11,
4838                IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK , "p2p_get"
4839        },
4840        {
4841                SIOCIWFIRSTPRIV + 0x12, 0, 0, "NULL"
4842        },
4843        {
4844                SIOCIWFIRSTPRIV + 0x13,
4845                IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64 , "p2p_get2"
4846        },
4847        {
4848                SIOCIWFIRSTPRIV + 0x14,
4849                IW_PRIV_TYPE_CHAR  | 64, 0, "tdls"
4850        },
4851        {
4852                SIOCIWFIRSTPRIV + 0x15,
4853                IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024 , "tdls_get"
4854        },
4855        {
4856                SIOCIWFIRSTPRIV + 0x16,
4857                IW_PRIV_TYPE_CHAR | 64, 0, "pm_set"
4858        },
4859
4860        {SIOCIWFIRSTPRIV + 0x18, IW_PRIV_TYPE_CHAR | IFNAMSIZ , 0 , "rereg_nd_name"},
4861        {SIOCIWFIRSTPRIV + 0x1A, IW_PRIV_TYPE_CHAR | 1024, 0, "efuse_set"},
4862        {SIOCIWFIRSTPRIV + 0x1B, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "efuse_get"},
4863        {
4864                SIOCIWFIRSTPRIV + 0x1D,
4865                IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 0x7FF, "test"
4866        },
4867
4868#ifdef CONFIG_INTEL_WIDI
4869        {
4870                SIOCIWFIRSTPRIV + 0x1E,
4871                IW_PRIV_TYPE_CHAR | 1024, 0, "widi_set"
4872        },
4873        {
4874                SIOCIWFIRSTPRIV + 0x1F,
4875                IW_PRIV_TYPE_CHAR | 128, 0, "widi_prob_req"
4876        },
4877#endif /*  CONFIG_INTEL_WIDI */
4878
4879#ifdef CONFIG_WOWLAN
4880                { MP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "wow_mode" }, /* set */
4881#endif
4882#ifdef CONFIG_AP_WOWLAN
4883                { MP_AP_WOW_ENABLE , IW_PRIV_TYPE_CHAR | 1024, 0, "ap_wow_mode" }, /* set */
4884#endif
4885};
4886
4887static iw_handler rtw_private_handler[] = {
4888        rtw_wx_write32,                                 /* 0x00 */
4889        rtw_wx_read32,                                  /* 0x01 */
4890        rtw_drvext_hdl,                                 /* 0x02 */
4891        rtw_mp_ioctl_hdl,                               /* 0x03 */
4892
4893/*  for MM DTV platform */
4894        rtw_get_ap_info,                                        /* 0x04 */
4895
4896        rtw_set_pid,                                            /* 0x05 */
4897        rtw_wps_start,                                  /* 0x06 */
4898
4899/*  for PLATFORM_MT53XX */
4900        rtw_wx_get_sensitivity,                 /* 0x07 */
4901        rtw_wx_set_mtk_wps_probe_ie,    /* 0x08 */
4902        rtw_wx_set_mtk_wps_ie,                  /* 0x09 */
4903
4904/*  for RTK_DMP_PLATFORM */
4905/*  Set Channel depend on the country code */
4906        rtw_wx_set_channel_plan,                /* 0x0A */
4907
4908        rtw_dbg_port,                                   /* 0x0B */
4909        rtw_wx_write_rf,                                        /* 0x0C */
4910        rtw_wx_read_rf,                                 /* 0x0D */
4911        rtw_wx_priv_null,                               /* 0x0E */
4912        rtw_wx_priv_null,                               /* 0x0F */
4913        rtw_p2p_set,                                    /* 0x10 */
4914        rtw_p2p_get,                                    /* 0x11 */
4915        NULL,                                                   /* 0x12 */
4916        rtw_p2p_get2,                                   /* 0x13 */
4917
4918        rtw_tdls,                                               /* 0x14 */
4919        rtw_tdls_get,                                   /* 0x15 */
4920
4921        rtw_pm_set,                                             /* 0x16 */
4922        rtw_wx_priv_null,                               /* 0x17 */
4923        rtw_rereg_nd_name,                              /* 0x18 */
4924        rtw_wx_priv_null,                               /* 0x19 */
4925        rtw_mp_efuse_set,                               /* 0x1A */
4926        rtw_mp_efuse_get,                               /* 0x1B */
4927        NULL,                                                   /*  0x1C is reserved for hostapd */
4928        rtw_test,                                               /*  0x1D */
4929#ifdef CONFIG_INTEL_WIDI
4930        rtw_widi_set,                                   /* 0x1E */
4931        rtw_widi_set_probe_request,             /* 0x1F */
4932#endif /*  CONFIG_INTEL_WIDI */
4933};
4934
4935static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
4936{
4937        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
4938        struct iw_statistics *piwstats =&padapter->iwstats;
4939        int tmp_level = 0;
4940        int tmp_qual = 0;
4941        int tmp_noise = 0;
4942
4943        if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
4944                piwstats->qual.qual = 0;
4945                piwstats->qual.level = 0;
4946                piwstats->qual.noise = 0;
4947                /* DBG_871X("No link  level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); */
4948        } else {
4949                #ifdef CONFIG_SIGNAL_DISPLAY_DBM
4950                tmp_level = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
4951                #else
4952                #ifdef CONFIG_SKIP_SIGNAL_SCALE_MAPPING
4953                {
4954                        /* Do signal scale mapping when using percentage as the unit of signal strength, since the scale mapping is skipped in odm */
4955
4956                        struct hal_com_data *pHal = GET_HAL_DATA(padapter);
4957
4958                        tmp_level = (u8)odm_SignalScaleMapping(&pHal->odmpriv, padapter->recvpriv.signal_strength);
4959                }
4960                #else
4961                tmp_level = padapter->recvpriv.signal_strength;
4962                #endif
4963                #endif
4964
4965                tmp_qual = padapter->recvpriv.signal_qual;
4966#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
4967                if (rtw_linked_check(padapter)) {
4968                        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4969                        struct noise_info info;
4970                        info.bPauseDIG = true;
4971                        info.IGIValue = 0x1e;
4972                        info.max_time = 100;/* ms */
4973                        info.chan = pmlmeext->cur_channel ;/* rtw_get_oper_ch(padapter); */
4974                        rtw_ps_deny(padapter, PS_DENY_IOCTL);
4975                        LeaveAllPowerSaveModeDirect(padapter);
4976
4977                        rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&info, false);
4978                        /* ODM_InbandNoise_Monitor(podmpriv, true, 0x20, 100); */
4979                        rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL);
4980                        rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&(info.chan), &(padapter->recvpriv.noise));
4981                        DBG_871X("chan:%d, noise_level:%d\n", info.chan, padapter->recvpriv.noise);
4982                }
4983#endif
4984                tmp_noise = padapter->recvpriv.noise;
4985                DBG_871X("level:%d, qual:%d, noise:%d, rssi (%d)\n", tmp_level, tmp_qual, tmp_noise, padapter->recvpriv.rssi);
4986
4987                piwstats->qual.level = tmp_level;
4988                piwstats->qual.qual = tmp_qual;
4989                piwstats->qual.noise = tmp_noise;
4990        }
4991        piwstats->qual.updated = IW_QUAL_ALL_UPDATED ;/* IW_QUAL_DBM; */
4992
4993        #ifdef CONFIG_SIGNAL_DISPLAY_DBM
4994        piwstats->qual.updated = piwstats->qual.updated | IW_QUAL_DBM;
4995        #endif
4996
4997        return &padapter->iwstats;
4998}
4999
5000struct iw_handler_def rtw_handlers_def = {
5001        .standard = rtw_handlers,
5002        .num_standard = ARRAY_SIZE(rtw_handlers),
5003#if defined(CONFIG_WEXT_PRIV)
5004        .private = rtw_private_handler,
5005        .private_args = (struct iw_priv_args *)rtw_private_args,
5006        .num_private = ARRAY_SIZE(rtw_private_handler),
5007        .num_private_args = ARRAY_SIZE(rtw_private_args),
5008#endif
5009        .get_wireless_stats = rtw_get_wireless_stats,
5010};
5011
5012/*  copy from net/wireless/wext.c start */
5013/* ---------------------------------------------------------------- */
5014/*
5015 * Calculate size of private arguments
5016 */
5017static const char iw_priv_type_size[] = {
5018        0,                              /* IW_PRIV_TYPE_NONE */
5019        1,                              /* IW_PRIV_TYPE_BYTE */
5020        1,                              /* IW_PRIV_TYPE_CHAR */
5021        0,                              /* Not defined */
5022        sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
5023        sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
5024        sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
5025        0,                              /* Not defined */
5026};
5027
5028static int get_priv_size(__u16 args)
5029{
5030        int num = args & IW_PRIV_SIZE_MASK;
5031        int type = (args & IW_PRIV_TYPE_MASK) >> 12;
5032
5033        return num * iw_priv_type_size[type];
5034}
5035/*  copy from net/wireless/wext.c end */
5036
5037static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_data)
5038{
5039        int err = 0;
5040        u8 *input = NULL;
5041        u32 input_len = 0;
5042        const char delim[] = " ";
5043        u8 *output = NULL;
5044        u32 output_len = 0;
5045        u32 count = 0;
5046        u8 *buffer = NULL;
5047        u32 buffer_len = 0;
5048        char *ptr = NULL;
5049        u8 cmdname[17] = {0}; /*  IFNAMSIZ+1 */
5050        u32 cmdlen;
5051        s32 len;
5052        u8 *extra = NULL;
5053        u32 extra_size = 0;
5054
5055        s32 k;
5056        const iw_handler *priv;         /* Private ioctl */
5057        const struct iw_priv_args *priv_args;   /* Private ioctl description */
5058        u32 num_priv;                           /* Number of ioctl */
5059        u32 num_priv_args;                      /* Number of descriptions */
5060        iw_handler handler;
5061        int temp;
5062        int subcmd = 0;                         /* sub-ioctl index */
5063        int offset = 0;                         /* Space for sub-ioctl index */
5064
5065        union iwreq_data wdata;
5066
5067
5068        memcpy(&wdata, wrq_data, sizeof(wdata));
5069
5070        input_len = 2048;
5071        input = rtw_zmalloc(input_len);
5072        if (NULL == input)
5073                return -ENOMEM;
5074        if (copy_from_user(input, wdata.data.pointer, input_len)) {
5075                err = -EFAULT;
5076                goto exit;
5077        }
5078        ptr = input;
5079        len = strlen(input);
5080
5081        sscanf(ptr, "%16s", cmdname);
5082        cmdlen = strlen(cmdname);
5083        DBG_8192C("%s: cmd =%s\n", __func__, cmdname);
5084
5085        /*  skip command string */
5086        if (cmdlen > 0)
5087                cmdlen += 1; /*  skip one space */
5088        ptr += cmdlen;
5089        len -= cmdlen;
5090        DBG_8192C("%s: parameters =%s\n", __func__, ptr);
5091
5092        priv = rtw_private_handler;
5093        priv_args = rtw_private_args;
5094        num_priv = ARRAY_SIZE(rtw_private_handler);
5095        num_priv_args = ARRAY_SIZE(rtw_private_args);
5096
5097        if (num_priv_args == 0) {
5098                err = -EOPNOTSUPP;
5099                goto exit;
5100        }
5101
5102        /* Search the correct ioctl */
5103        k = -1;
5104        while ((++k < num_priv_args) && strcmp(priv_args[k].name, cmdname));
5105
5106        /* If not found... */
5107        if (k == num_priv_args) {
5108                err = -EOPNOTSUPP;
5109                goto exit;
5110        }
5111
5112        /* Watch out for sub-ioctls ! */
5113        if (priv_args[k].cmd < SIOCDEVPRIVATE) {
5114                int j = -1;
5115
5116                /* Find the matching *real* ioctl */
5117                while ((++j < num_priv_args) && ((priv_args[j].name[0] != '\0') ||
5118                        (priv_args[j].set_args != priv_args[k].set_args) ||
5119                        (priv_args[j].get_args != priv_args[k].get_args)));
5120
5121                /* If not found... */
5122                if (j == num_priv_args) {
5123                        err = -EINVAL;
5124                        goto exit;
5125                }
5126
5127                /* Save sub-ioctl number */
5128                subcmd = priv_args[k].cmd;
5129                /* Reserve one int (simplify alignment issues) */
5130                offset = sizeof(__u32);
5131                /* Use real ioctl definition from now on */
5132                k = j;
5133        }
5134
5135        buffer = rtw_zmalloc(4096);
5136        if (NULL == buffer) {
5137                err = -ENOMEM;
5138                goto exit;
5139        }
5140
5141        /* If we have to set some data */
5142        if ((priv_args[k].set_args & IW_PRIV_TYPE_MASK) &&
5143                (priv_args[k].set_args & IW_PRIV_SIZE_MASK)) {
5144                u8 *str;
5145
5146                switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
5147                        case IW_PRIV_TYPE_BYTE:
5148                                /* Fetch args */
5149                                count = 0;
5150                                do {
5151                                        str = strsep(&ptr, delim);
5152                                        if (NULL == str) break;
5153                                        sscanf(str, "%i", &temp);
5154                                        buffer[count++] = (u8)temp;
5155                                } while (1);
5156                                buffer_len = count;
5157
5158                                /* Number of args to fetch */
5159                                wdata.data.length = count;
5160                                if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
5161                                        wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
5162
5163                                break;
5164
5165                        case IW_PRIV_TYPE_INT:
5166                                /* Fetch args */
5167                                count = 0;
5168                                do {
5169                                        str = strsep(&ptr, delim);
5170                                        if (NULL == str) break;
5171                                        sscanf(str, "%i", &temp);
5172                                        ((s32*)buffer)[count++] = (s32)temp;
5173                                } while (1);
5174                                buffer_len = count * sizeof(s32);
5175
5176                                /* Number of args to fetch */
5177                                wdata.data.length = count;
5178                                if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
5179                                        wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
5180
5181                                break;
5182
5183                        case IW_PRIV_TYPE_CHAR:
5184                                if (len > 0) {
5185                                        /* Size of the string to fetch */
5186                                        wdata.data.length = len;
5187                                        if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
5188                                                wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
5189
5190                                        /* Fetch string */
5191                                        memcpy(buffer, ptr, wdata.data.length);
5192                                } else {
5193                                        wdata.data.length = 1;
5194                                        buffer[0] = '\0';
5195                                }
5196                                buffer_len = wdata.data.length;
5197                                break;
5198
5199                        default:
5200                                DBG_8192C("%s: Not yet implemented...\n", __func__);
5201                                err = -1;
5202                                goto exit;
5203                }
5204
5205                if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
5206                        (wdata.data.length != (priv_args[k].set_args & IW_PRIV_SIZE_MASK))) {
5207                        DBG_8192C("%s: The command %s needs exactly %d argument(s)...\n",
5208                                        __func__, cmdname, priv_args[k].set_args & IW_PRIV_SIZE_MASK);
5209                        err = -EINVAL;
5210                        goto exit;
5211                }
5212        } else { /* if args to set */
5213                wdata.data.length = 0L;
5214        }
5215
5216        /* Those two tests are important. They define how the driver
5217        * will have to handle the data */
5218        if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
5219                ((get_priv_size(priv_args[k].set_args) + offset) <= IFNAMSIZ)) {
5220                /* First case : all SET args fit within wrq */
5221                if (offset)
5222                        wdata.mode = subcmd;
5223                memcpy(wdata.name + offset, buffer, IFNAMSIZ - offset);
5224        } else {
5225                if ((priv_args[k].set_args == 0) &&
5226                        (priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
5227                        (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ)) {
5228                        /* Second case : no SET args, GET args fit within wrq */
5229                        if (offset)
5230                                wdata.mode = subcmd;
5231                } else {
5232                        /* Third case : args won't fit in wrq, or variable number of args */
5233                        if (copy_to_user(wdata.data.pointer, buffer, buffer_len)) {
5234                                err = -EFAULT;
5235                                goto exit;
5236                        }
5237                        wdata.data.flags = subcmd;
5238                }
5239        }
5240
5241        kfree(input);
5242        input = NULL;
5243
5244        extra_size = 0;
5245        if (IW_IS_SET(priv_args[k].cmd)) {
5246                /* Size of set arguments */
5247                extra_size = get_priv_size(priv_args[k].set_args);
5248
5249                /* Does it fits in iwr ? */
5250                if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
5251                        ((extra_size + offset) <= IFNAMSIZ))
5252                        extra_size = 0;
5253        } else {
5254                /* Size of get arguments */
5255                extra_size = get_priv_size(priv_args[k].get_args);
5256
5257                /* Does it fits in iwr ? */
5258                if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
5259                        (extra_size <= IFNAMSIZ))
5260                        extra_size = 0;
5261        }
5262
5263        if (extra_size == 0) {
5264                extra = (u8 *)&wdata;
5265                kfree(buffer);
5266                buffer = NULL;
5267        } else
5268                extra = buffer;
5269
5270        handler = priv[priv_args[k].cmd - SIOCIWFIRSTPRIV];
5271        err = handler(dev, NULL, &wdata, extra);
5272
5273        /* If we have to get some data */
5274        if ((priv_args[k].get_args & IW_PRIV_TYPE_MASK) &&
5275                (priv_args[k].get_args & IW_PRIV_SIZE_MASK)) {
5276                int j;
5277                int n = 0;      /* number of args */
5278                u8 str[20] = {0};
5279
5280                /* Check where is the returned data */
5281                if ((priv_args[k].get_args & IW_PRIV_SIZE_FIXED) &&
5282                        (get_priv_size(priv_args[k].get_args) <= IFNAMSIZ))
5283                        n = priv_args[k].get_args & IW_PRIV_SIZE_MASK;
5284                else
5285                        n = wdata.data.length;
5286
5287                output = rtw_zmalloc(4096);
5288                if (NULL == output) {
5289                        err =  -ENOMEM;
5290                        goto exit;
5291                }
5292
5293                switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
5294                        case IW_PRIV_TYPE_BYTE:
5295                                /* Display args */
5296                                for (j = 0; j < n; j++) {
5297                                        sprintf(str, "%d  ", extra[j]);
5298                                        len = strlen(str);
5299                                        output_len = strlen(output);
5300                                        if ((output_len + len + 1) > 4096) {
5301                                                err = -E2BIG;
5302                                                goto exit;
5303                                        }
5304                                        memcpy(output+output_len, str, len);
5305                                }
5306                                break;
5307
5308                        case IW_PRIV_TYPE_INT:
5309                                /* Display args */
5310                                for (j = 0; j < n; j++) {
5311                                        sprintf(str, "%d  ", ((__s32*)extra)[j]);
5312                                        len = strlen(str);
5313                                        output_len = strlen(output);
5314                                        if ((output_len + len + 1) > 4096) {
5315                                                err = -E2BIG;
5316                                                goto exit;
5317                                        }
5318                                        memcpy(output+output_len, str, len);
5319                                }
5320                                break;
5321
5322                        case IW_PRIV_TYPE_CHAR:
5323                                /* Display args */
5324                                memcpy(output, extra, n);
5325                                break;
5326
5327                        default:
5328                                DBG_8192C("%s: Not yet implemented...\n", __func__);
5329                                err = -1;
5330                                goto exit;
5331                }
5332
5333                output_len = strlen(output) + 1;
5334                wrq_data->data.length = output_len;
5335                if (copy_to_user(wrq_data->data.pointer, output, output_len)) {
5336                        err = -EFAULT;
5337                        goto exit;
5338                }
5339        } else { /* if args to set */
5340                wrq_data->data.length = 0;
5341        }
5342
5343exit:
5344        kfree(input);
5345        kfree(buffer);
5346        kfree(output);
5347
5348        return err;
5349}
5350
5351int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
5352{
5353        struct iwreq *wrq = (struct iwreq *)rq;
5354        int ret = 0;
5355
5356        switch (cmd) {
5357                case RTL_IOCTL_WPA_SUPPLICANT:
5358                        ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
5359                        break;
5360                case RTL_IOCTL_HOSTAPD:
5361                        ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
5362                        break;
5363                case SIOCDEVPRIVATE:
5364                        ret = rtw_ioctl_wext_private(dev, &wrq->u);
5365                        break;
5366                default:
5367                        ret = -EOPNOTSUPP;
5368                        break;
5369        }
5370
5371        return ret;
5372}
5373