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