linux/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7
   8#include <drv_types.h>
   9#include <rtw_debug.h>
  10
  11u8 rtw_validate_bssid(u8 *bssid)
  12{
  13        u8 ret = true;
  14
  15        if (is_zero_mac_addr(bssid)
  16                || is_broadcast_mac_addr(bssid)
  17                || is_multicast_mac_addr(bssid)
  18        ) {
  19                ret = false;
  20        }
  21
  22        return ret;
  23}
  24
  25u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
  26{
  27        u8 ret = true;
  28
  29        if (ssid->ssid_length > 32) {
  30                ret = false;
  31                goto exit;
  32        }
  33
  34exit:
  35        return ret;
  36}
  37
  38u8 rtw_do_join(struct adapter *padapter)
  39{
  40        struct list_head        *plist, *phead;
  41        u8 *pibss = NULL;
  42        struct  mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  43        struct __queue  *queue  = &(pmlmepriv->scanned_queue);
  44        u8 ret = _SUCCESS;
  45
  46        spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
  47        phead = get_list_head(queue);
  48        plist = get_next(phead);
  49
  50        pmlmepriv->cur_network.join_res = -2;
  51
  52        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
  53
  54        pmlmepriv->pscanned = plist;
  55
  56        pmlmepriv->to_join = true;
  57
  58        if (list_empty(&queue->queue)) {
  59                spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
  60                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
  61
  62                /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
  63                /* we try to issue sitesurvey firstly */
  64
  65                if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false
  66                        || rtw_to_roam(padapter) > 0
  67                ) {
  68                        /*  submit site_survey_cmd */
  69                        ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
  70                        if (ret != _SUCCESS)
  71                                pmlmepriv->to_join = false;
  72
  73                } else {
  74                        pmlmepriv->to_join = false;
  75                        ret = _FAIL;
  76                }
  77
  78                goto exit;
  79        } else {
  80                int select_ret;
  81                spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
  82                select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
  83                if (select_ret == _SUCCESS) {
  84                        pmlmepriv->to_join = false;
  85                        _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
  86                } else {
  87                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
  88                                /*  submit createbss_cmd to change to a ADHOC_MASTER */
  89
  90                                /* pmlmepriv->lock has been acquired by caller... */
  91                                struct wlan_bssid_ex    *pdev_network = &(padapter->registrypriv.dev_network);
  92
  93                                pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
  94
  95                                pibss = padapter->registrypriv.dev_network.mac_address;
  96
  97                                memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
  98
  99                                rtw_update_registrypriv_dev_network(padapter);
 100
 101                                rtw_generate_random_ibss(pibss);
 102
 103                                if (rtw_createbss_cmd(padapter) != _SUCCESS) {
 104                                        ret =  false;
 105                                        goto exit;
 106                                }
 107
 108                                pmlmepriv->to_join = false;
 109
 110                        } else {
 111                                /*  can't associate ; reset under-linking */
 112                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 113
 114                                /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
 115                                /* we try to issue sitesurvey firstly */
 116                                if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false
 117                                        || rtw_to_roam(padapter) > 0
 118                                ) {
 119                                        ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
 120                                        if (ret != _SUCCESS)
 121                                                pmlmepriv->to_join = false;
 122
 123                                } else {
 124                                        ret = _FAIL;
 125                                        pmlmepriv->to_join = false;
 126                                }
 127                        }
 128
 129                }
 130
 131        }
 132
 133exit:
 134        return ret;
 135}
 136
 137u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
 138{
 139        u8 status = _SUCCESS;
 140
 141        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 142        struct wlan_network *pnetwork = &pmlmepriv->cur_network;
 143
 144        netdev_dbg(padapter->pnetdev, "set ssid [%s] fw_state = 0x%08x\n",
 145                   ssid->ssid, get_fwstate(pmlmepriv));
 146
 147        if (padapter->hw_init_completed == false) {
 148                status = _FAIL;
 149                goto exit;
 150        }
 151
 152        spin_lock_bh(&pmlmepriv->lock);
 153
 154        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
 155                goto handle_tkip_countermeasure;
 156        else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
 157                goto release_mlme_lock;
 158
 159        if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
 160                if ((pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length) &&
 161                    (!memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length))) {
 162                        if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)) {
 163                                if (rtw_is_same_ibss(padapter, pnetwork) == false) {
 164                                        /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
 165                                        rtw_disassoc_cmd(padapter, 0, true);
 166
 167                                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
 168                                                rtw_indicate_disconnect(padapter);
 169
 170                                        rtw_free_assoc_resources(padapter, 1);
 171
 172                                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
 173                                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
 174                                                set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
 175                                        }
 176                                } else {
 177                                        goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
 178                                }
 179                        } else {
 180                                rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
 181                        }
 182                } else {
 183                        rtw_disassoc_cmd(padapter, 0, true);
 184
 185                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
 186                                rtw_indicate_disconnect(padapter);
 187
 188                        rtw_free_assoc_resources(padapter, 1);
 189
 190                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
 191                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
 192                                set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
 193                        }
 194                }
 195        }
 196
 197handle_tkip_countermeasure:
 198        if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
 199                status = _FAIL;
 200                goto release_mlme_lock;
 201        }
 202
 203        if (rtw_validate_ssid(ssid) == false) {
 204                status = _FAIL;
 205                goto release_mlme_lock;
 206        }
 207
 208        memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
 209        pmlmepriv->assoc_by_bssid = false;
 210
 211        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
 212                pmlmepriv->to_join = true;
 213        else
 214                status = rtw_do_join(padapter);
 215
 216release_mlme_lock:
 217        spin_unlock_bh(&pmlmepriv->lock);
 218
 219exit:
 220
 221        return status;
 222}
 223
 224u8 rtw_set_802_11_connect(struct adapter *padapter, u8 *bssid, struct ndis_802_11_ssid *ssid)
 225{
 226        u8 status = _SUCCESS;
 227        bool bssid_valid = true;
 228        bool ssid_valid = true;
 229        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 230
 231        if (!ssid || rtw_validate_ssid(ssid) == false)
 232                ssid_valid = false;
 233
 234        if (!bssid || rtw_validate_bssid(bssid) == false)
 235                bssid_valid = false;
 236
 237        if (!ssid_valid && !bssid_valid) {
 238                status = _FAIL;
 239                goto exit;
 240        }
 241
 242        if (padapter->hw_init_completed == false) {
 243                status = _FAIL;
 244                goto exit;
 245        }
 246
 247        spin_lock_bh(&pmlmepriv->lock);
 248
 249        netdev_dbg(padapter->pnetdev, FUNC_ADPT_FMT "  fw_state = 0x%08x\n",
 250                   FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
 251
 252        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
 253                goto handle_tkip_countermeasure;
 254        else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
 255                goto release_mlme_lock;
 256
 257handle_tkip_countermeasure:
 258        if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
 259                status = _FAIL;
 260                goto release_mlme_lock;
 261        }
 262
 263        if (ssid && ssid_valid)
 264                memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
 265        else
 266                memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
 267
 268        if (bssid && bssid_valid) {
 269                memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
 270                pmlmepriv->assoc_by_bssid = true;
 271        } else {
 272                pmlmepriv->assoc_by_bssid = false;
 273        }
 274
 275        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
 276                pmlmepriv->to_join = true;
 277        else
 278                status = rtw_do_join(padapter);
 279
 280release_mlme_lock:
 281        spin_unlock_bh(&pmlmepriv->lock);
 282
 283exit:
 284        return status;
 285}
 286
 287u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
 288        enum ndis_802_11_network_infrastructure networktype)
 289{
 290        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 291        struct  wlan_network    *cur_network = &pmlmepriv->cur_network;
 292        enum ndis_802_11_network_infrastructure *pold_state = &(cur_network->network.infrastructure_mode);
 293
 294        if (*pold_state != networktype) {
 295                if (*pold_state == Ndis802_11APMode) {
 296                        /* change to other mode from Ndis802_11APMode */
 297                        cur_network->join_res = -1;
 298
 299                        stop_ap_mode(padapter);
 300                }
 301
 302                spin_lock_bh(&pmlmepriv->lock);
 303
 304                if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || (*pold_state == Ndis802_11IBSS))
 305                        rtw_disassoc_cmd(padapter, 0, true);
 306
 307                if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
 308                        (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
 309                        rtw_free_assoc_resources(padapter, 1);
 310
 311                if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
 312                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
 313                                rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */
 314               }
 315
 316                *pold_state = networktype;
 317
 318                _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
 319
 320                switch (networktype) {
 321                case Ndis802_11IBSS:
 322                        set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
 323                        break;
 324
 325                case Ndis802_11Infrastructure:
 326                        set_fwstate(pmlmepriv, WIFI_STATION_STATE);
 327                        break;
 328
 329                case Ndis802_11APMode:
 330                        set_fwstate(pmlmepriv, WIFI_AP_STATE);
 331                        start_ap_mode(padapter);
 332                        /* rtw_indicate_connect(padapter); */
 333
 334                        break;
 335
 336                case Ndis802_11AutoUnknown:
 337                case Ndis802_11InfrastructureMax:
 338                        break;
 339                }
 340
 341                /* SecClearAllKeys(adapter); */
 342
 343                spin_unlock_bh(&pmlmepriv->lock);
 344        }
 345        return true;
 346}
 347
 348
 349u8 rtw_set_802_11_disassociate(struct adapter *padapter)
 350{
 351        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 352
 353        spin_lock_bh(&pmlmepriv->lock);
 354
 355        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
 356                rtw_disassoc_cmd(padapter, 0, true);
 357                rtw_indicate_disconnect(padapter);
 358                /* modify for CONFIG_IEEE80211W, none 11w can use it */
 359                rtw_free_assoc_resources_cmd(padapter);
 360                rtw_pwr_wakeup(padapter);
 361        }
 362
 363        spin_unlock_bh(&pmlmepriv->lock);
 364
 365        return true;
 366}
 367
 368u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
 369{
 370        struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
 371        u8 res = true;
 372
 373        if (padapter == NULL) {
 374                res = false;
 375                goto exit;
 376        }
 377        if (padapter->hw_init_completed == false) {
 378                res = false;
 379                goto exit;
 380        }
 381
 382        if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) ||
 383                (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) {
 384                /*  Scan or linking is in progress, do nothing. */
 385                res = true;
 386
 387        } else {
 388                if (rtw_is_scan_deny(padapter))
 389                        return _SUCCESS;
 390
 391                spin_lock_bh(&pmlmepriv->lock);
 392
 393                res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
 394
 395                spin_unlock_bh(&pmlmepriv->lock);
 396        }
 397exit:
 398
 399        return res;
 400}
 401
 402u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_authentication_mode authmode)
 403{
 404        struct security_priv *psecuritypriv = &padapter->securitypriv;
 405        int res;
 406        u8 ret;
 407
 408        psecuritypriv->ndisauthtype = authmode;
 409
 410        if (psecuritypriv->ndisauthtype > 3)
 411                psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
 412
 413        res = rtw_set_auth(padapter, psecuritypriv);
 414
 415        if (res == _SUCCESS)
 416                ret = true;
 417        else
 418                ret = false;
 419
 420        return ret;
 421}
 422
 423u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
 424{
 425
 426        signed int              keyid, res;
 427        struct security_priv *psecuritypriv = &(padapter->securitypriv);
 428        u8 ret = _SUCCESS;
 429
 430        keyid = wep->key_index & 0x3fffffff;
 431
 432        if (keyid >= 4) {
 433                ret = false;
 434                goto exit;
 435        }
 436
 437        switch (wep->key_length) {
 438        case 5:
 439                psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
 440                break;
 441        case 13:
 442                psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
 443                break;
 444        default:
 445                psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
 446                break;
 447        }
 448
 449        memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->key_material), wep->key_length);
 450
 451        psecuritypriv->dot11DefKeylen[keyid] = wep->key_length;
 452
 453        psecuritypriv->dot11PrivacyKeyIndex = keyid;
 454
 455        res = rtw_set_key(padapter, psecuritypriv, keyid, 1, true);
 456
 457        if (res == _FAIL)
 458                ret = false;
 459exit:
 460
 461        return ret;
 462}
 463
 464/*
 465* rtw_get_cur_max_rate -
 466* @adapter: pointer to struct adapter structure
 467*
 468* Return 0 or 100Kbps
 469*/
 470u16 rtw_get_cur_max_rate(struct adapter *adapter)
 471{
 472        int     i = 0;
 473        u16 rate = 0, max_rate = 0;
 474        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 475        struct wlan_bssid_ex    *pcur_bss = &pmlmepriv->cur_network.network;
 476        struct sta_info *psta = NULL;
 477        u8 short_GI = 0;
 478
 479        if ((check_fwstate(pmlmepriv, _FW_LINKED) != true)
 480                && (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true))
 481                return 0;
 482
 483        psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
 484        if (psta == NULL)
 485                return 0;
 486
 487        short_GI = query_ra_short_GI(psta);
 488
 489        if (is_supported_ht(psta->wireless_mode)) {
 490                max_rate = rtw_mcs_rate(psta->bw_mode == CHANNEL_WIDTH_40 ? 1 : 0,
 491                                        short_GI,
 492                                        psta->htpriv.ht_cap.mcs.rx_mask);
 493        } else {
 494                while ((pcur_bss->supported_rates[i] != 0) && (pcur_bss->supported_rates[i] != 0xFF)) {
 495                        rate = pcur_bss->supported_rates[i]&0x7F;
 496                        if (rate > max_rate)
 497                                max_rate = rate;
 498                        i++;
 499                }
 500
 501                max_rate = max_rate*10/2;
 502        }
 503
 504        return max_rate;
 505}
 506