root/drivers/staging/rtl8712/rtl871x_ioctl_set.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. validate_ssid
  2. do_join
  3. r8712_set_802_11_bssid
  4. r8712_set_802_11_ssid
  5. r8712_set_802_11_infrastructure_mode
  6. r8712_set_802_11_disassociate
  7. r8712_set_802_11_bssid_list_scan
  8. r8712_set_802_11_authentication_mode
  9. r8712_set_802_11_add_wep

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  * rtl871x_ioctl_set.c
   4  *
   5  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   6  * Linux device driver for RTL8192SU
   7  *
   8  * Modifications for inclusion into the Linux staging tree are
   9  * Copyright(c) 2010 Larry Finger. All rights reserved.
  10  *
  11  * Contact information:
  12  * WLAN FAE <wlanfae@realtek.com>
  13  * Larry Finger <Larry.Finger@lwfinger.net>
  14  *
  15  ******************************************************************************/
  16 
  17 #define _RTL871X_IOCTL_SET_C_
  18 
  19 #include "osdep_service.h"
  20 #include "drv_types.h"
  21 #include "rtl871x_ioctl_set.h"
  22 #include "usb_osintf.h"
  23 #include "usb_ops.h"
  24 
  25 
  26 static u8 validate_ssid(struct ndis_802_11_ssid *ssid)
  27 {
  28         u8 i;
  29 
  30         if (ssid->SsidLength > 32)
  31                 return false;
  32         for (i = 0; i < ssid->SsidLength; i++) {
  33                 /* wifi, printable ascii code must be supported */
  34                 if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e)))
  35                         return false;
  36         }
  37         return true;
  38 }
  39 
  40 static u8 do_join(struct _adapter *padapter)
  41 {
  42         struct list_head *plist, *phead;
  43         u8 *pibss = NULL;
  44         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
  45         struct  __queue *queue  = &(pmlmepriv->scanned_queue);
  46         int ret;
  47 
  48         phead = &queue->queue;
  49         plist = phead->next;
  50         pmlmepriv->cur_network.join_res = -2;
  51         pmlmepriv->fw_state |= _FW_UNDER_LINKING;
  52         pmlmepriv->pscanned = plist;
  53         pmlmepriv->to_join = true;
  54 
  55         /* adhoc mode will start with an empty queue, but skip checking */
  56         if (!check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) &&
  57             list_empty(&queue->queue)) {
  58                 if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
  59                         pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
  60                 /* when set_ssid/set_bssid for do_join(), but scanning queue
  61                  * is empty we try to issue sitesurvey firstly
  62                  */
  63                 if (!pmlmepriv->sitesurveyctrl.traffic_busy)
  64                         r8712_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid);
  65                 return true;
  66         }
  67 
  68         ret = r8712_select_and_join_from_scan(pmlmepriv);
  69         if (!ret) {
  70                 mod_timer(&pmlmepriv->assoc_timer,
  71                           jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
  72         } else {
  73                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
  74                         /* submit r8712_createbss_cmd to change to an
  75                          * ADHOC_MASTER pmlmepriv->lock has been
  76                          * acquired by caller...
  77                          */
  78                         struct wlan_bssid_ex *pdev_network =
  79                                 &(padapter->registrypriv.dev_network);
  80                         pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
  81                         pibss = padapter->registrypriv.dev_network.MacAddress;
  82                         memcpy(&pdev_network->Ssid,
  83                                &pmlmepriv->assoc_ssid,
  84                                sizeof(struct ndis_802_11_ssid));
  85                         r8712_update_registrypriv_dev_network(padapter);
  86                         r8712_generate_random_ibss(pibss);
  87                         if (r8712_createbss_cmd(padapter))
  88                                 return false;
  89                         pmlmepriv->to_join = false;
  90                 } else {
  91                         /* can't associate ; reset under-linking */
  92                         if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
  93                                 pmlmepriv->fw_state ^=
  94                                         _FW_UNDER_LINKING;
  95                         /* when set_ssid/set_bssid for do_join(), but
  96                          * there are no desired bss in scanning queue
  97                          * we try to issue sitesurvey first
  98                          */
  99                         if (!pmlmepriv->sitesurveyctrl.traffic_busy)
 100                                 r8712_sitesurvey_cmd(padapter,
 101                                                      &pmlmepriv->assoc_ssid);
 102                 }
 103         }
 104         return true;
 105 }
 106 
 107 u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid)
 108 {
 109         unsigned long irqL;
 110         u8 status = true;
 111         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 112 
 113         if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) {
 114                 status = false;
 115                 return status;
 116         }
 117         spin_lock_irqsave(&pmlmepriv->lock, irqL);
 118         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
 119             _FW_UNDER_LINKING)) {
 120                 status = check_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 121                 goto _Abort_Set_BSSID;
 122         }
 123         if (check_fwstate(pmlmepriv,
 124             _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
 125                 if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid,
 126                     ETH_ALEN)) {
 127                         if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 128                                 /* driver is in
 129                                  * WIFI_ADHOC_MASTER_STATE
 130                                  */
 131                                 goto _Abort_Set_BSSID;
 132                 } else {
 133                         r8712_disassoc_cmd(padapter);
 134                         if (check_fwstate(pmlmepriv, _FW_LINKED))
 135                                 r8712_ind_disconnect(padapter);
 136                         r8712_free_assoc_resources(padapter);
 137                         if ((check_fwstate(pmlmepriv,
 138                              WIFI_ADHOC_MASTER_STATE))) {
 139                                 _clr_fwstate_(pmlmepriv,
 140                                               WIFI_ADHOC_MASTER_STATE);
 141                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
 142                         }
 143                 }
 144         }
 145         memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
 146         pmlmepriv->assoc_by_bssid = true;
 147         status = do_join(padapter);
 148         goto done;
 149 _Abort_Set_BSSID:
 150 done:
 151         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 152         return status;
 153 }
 154 
 155 void r8712_set_802_11_ssid(struct _adapter *padapter,
 156                            struct ndis_802_11_ssid *ssid)
 157 {
 158         unsigned long irqL;
 159         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 160         struct wlan_network *pnetwork = &pmlmepriv->cur_network;
 161 
 162         if (!padapter->hw_init_completed)
 163                 return;
 164         spin_lock_irqsave(&pmlmepriv->lock, irqL);
 165         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
 166                 check_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 167                 goto _Abort_Set_SSID;
 168         }
 169         if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
 170                 if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
 171                     (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid,
 172                     ssid->SsidLength))) {
 173                         if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 174                                 if (!r8712_is_same_ibss(padapter,
 175                                      pnetwork)) {
 176                                         /* if in WIFI_ADHOC_MASTER_STATE or
 177                                          *  WIFI_ADHOC_STATE, create bss or
 178                                          * rejoin again
 179                                          */
 180                                         r8712_disassoc_cmd(padapter);
 181                                         if (check_fwstate(pmlmepriv,
 182                                             _FW_LINKED))
 183                                                 r8712_ind_disconnect(padapter);
 184                                         r8712_free_assoc_resources(padapter);
 185                                         if (check_fwstate(pmlmepriv,
 186                                              WIFI_ADHOC_MASTER_STATE)) {
 187                                                 _clr_fwstate_(pmlmepriv,
 188                                                     WIFI_ADHOC_MASTER_STATE);
 189                                                 set_fwstate(pmlmepriv,
 190                                                             WIFI_ADHOC_STATE);
 191                                         }
 192                                 } else {
 193                                         /* driver is in
 194                                          * WIFI_ADHOC_MASTER_STATE
 195                                          */
 196                                         goto _Abort_Set_SSID;
 197                                 }
 198                         }
 199                 } else {
 200                         r8712_disassoc_cmd(padapter);
 201                         if (check_fwstate(pmlmepriv, _FW_LINKED))
 202                                 r8712_ind_disconnect(padapter);
 203                         r8712_free_assoc_resources(padapter);
 204                         if (check_fwstate(pmlmepriv,
 205                             WIFI_ADHOC_MASTER_STATE)) {
 206                                 _clr_fwstate_(pmlmepriv,
 207                                               WIFI_ADHOC_MASTER_STATE);
 208                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
 209                         }
 210                 }
 211         }
 212         if (padapter->securitypriv.btkip_countermeasure)
 213                 goto _Abort_Set_SSID;
 214         if (!validate_ssid(ssid))
 215                 goto _Abort_Set_SSID;
 216         memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
 217         pmlmepriv->assoc_by_bssid = false;
 218         do_join(padapter);
 219         goto done;
 220 _Abort_Set_SSID:
 221 done:
 222         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 223 }
 224 
 225 void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
 226         enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
 227 {
 228         unsigned long irqL;
 229         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
 230         struct wlan_network     *cur_network = &pmlmepriv->cur_network;
 231         enum NDIS_802_11_NETWORK_INFRASTRUCTURE *pold_state =
 232                                 &(cur_network->network.InfrastructureMode);
 233 
 234         if (*pold_state != networktype) {
 235                 spin_lock_irqsave(&pmlmepriv->lock, irqL);
 236                 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
 237                     (*pold_state == Ndis802_11IBSS))
 238                         r8712_disassoc_cmd(padapter);
 239                 if (check_fwstate(pmlmepriv,
 240                     _FW_LINKED | WIFI_ADHOC_MASTER_STATE))
 241                         r8712_free_assoc_resources(padapter);
 242                 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
 243                     (*pold_state == Ndis802_11Infrastructure) ||
 244                     (*pold_state == Ndis802_11IBSS)) {
 245                         /* will clr Linked_state before this function,
 246                          * we must have checked whether issue dis-assoc_cmd or
 247                          * not
 248                          */
 249                         r8712_ind_disconnect(padapter);
 250                 }
 251                 *pold_state = networktype;
 252                 /* clear WIFI_STATION_STATE; WIFI_AP_STATE; WIFI_ADHOC_STATE;
 253                  * WIFI_ADHOC_MASTER_STATE
 254                  */
 255                 _clr_fwstate_(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE |
 256                               WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE);
 257                 switch (networktype) {
 258                 case Ndis802_11IBSS:
 259                         set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
 260                         break;
 261                 case Ndis802_11Infrastructure:
 262                         set_fwstate(pmlmepriv, WIFI_STATION_STATE);
 263                         break;
 264                 case Ndis802_11APMode:
 265                         set_fwstate(pmlmepriv, WIFI_AP_STATE);
 266                         break;
 267                 case Ndis802_11AutoUnknown:
 268                 case Ndis802_11InfrastructureMax:
 269                         break;
 270                 }
 271                 spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 272         }
 273 }
 274 
 275 u8 r8712_set_802_11_disassociate(struct _adapter *padapter)
 276 {
 277         unsigned long irqL;
 278         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 279 
 280         spin_lock_irqsave(&pmlmepriv->lock, irqL);
 281         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 282                 r8712_disassoc_cmd(padapter);
 283                 r8712_ind_disconnect(padapter);
 284                 r8712_free_assoc_resources(padapter);
 285         }
 286         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 287         return true;
 288 }
 289 
 290 u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter)
 291 {
 292         struct mlme_priv *pmlmepriv = NULL;
 293         unsigned long irqL;
 294         u8 ret = true;
 295 
 296         if (!padapter)
 297                 return false;
 298         pmlmepriv = &padapter->mlmepriv;
 299         if (!padapter->hw_init_completed)
 300                 return false;
 301         spin_lock_irqsave(&pmlmepriv->lock, irqL);
 302         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
 303             pmlmepriv->sitesurveyctrl.traffic_busy) {
 304                 /* Scan or linking is in progress, do nothing. */
 305                 ret = (u8)check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
 306         } else {
 307                 r8712_free_network_queue(padapter);
 308                 ret = r8712_sitesurvey_cmd(padapter, NULL);
 309         }
 310         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 311         return ret;
 312 }
 313 
 314 u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter,
 315                                 enum NDIS_802_11_AUTHENTICATION_MODE authmode)
 316 {
 317         struct security_priv *psecuritypriv = &padapter->securitypriv;
 318         u8 ret;
 319 
 320         psecuritypriv->ndisauthtype = authmode;
 321         if (psecuritypriv->ndisauthtype > 3)
 322                 psecuritypriv->AuthAlgrthm = 2; /* 802.1x */
 323         if (r8712_set_auth(padapter, psecuritypriv))
 324                 ret = false;
 325         else
 326                 ret = true;
 327         return ret;
 328 }
 329 
 330 int r8712_set_802_11_add_wep(struct _adapter *padapter,
 331                              struct NDIS_802_11_WEP *wep)
 332 {
 333         sint    keyid;
 334         struct security_priv *psecuritypriv = &padapter->securitypriv;
 335 
 336         keyid = wep->KeyIndex & 0x3fffffff;
 337         if (keyid >= WEP_KEYS)
 338                 return -EINVAL;
 339         switch (wep->KeyLength) {
 340         case 5:
 341                 psecuritypriv->PrivacyAlgrthm = _WEP40_;
 342                 break;
 343         case 13:
 344                 psecuritypriv->PrivacyAlgrthm = _WEP104_;
 345                 break;
 346         default:
 347                 psecuritypriv->PrivacyAlgrthm = _NO_PRIVACY_;
 348                 break;
 349         }
 350         memcpy(psecuritypriv->DefKey[keyid].skey, &wep->KeyMaterial,
 351                 wep->KeyLength);
 352         psecuritypriv->DefKeylen[keyid] = wep->KeyLength;
 353         psecuritypriv->PrivacyKeyIndex = keyid;
 354         return r8712_set_key(padapter, psecuritypriv, keyid);
 355 }

/* [<][>][^][v][top][bottom][index][help] */