root/drivers/net/wireless/marvell/mwifiex/uap_cmd.c

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

DEFINITIONS

This source file includes following definitions.
  1. mwifiex_set_secure_params
  2. mwifiex_set_ht_params
  3. mwifiex_set_vht_params
  4. mwifiex_set_tpc_params
  5. mwifiex_set_vht_width
  6. mwifiex_set_uap_rates
  7. mwifiex_set_sys_config_invalid_data
  8. mwifiex_uap_bss_wpa
  9. mwifiex_set_wmm_params
  10. mwifiex_uap_bss_wep
  11. mwifiex_config_uap_11d
  12. mwifiex_uap_bss_param_prepare
  13. mwifiex_uap_custom_ie_prepare
  14. mwifiex_cmd_uap_sys_config
  15. mwifiex_cmd_uap_sta_deauth
  16. mwifiex_uap_prepare_cmd
  17. mwifiex_uap_set_channel
  18. mwifiex_config_start_uap

   1 /*
   2  * Marvell Wireless LAN device driver: AP specific command handling
   3  *
   4  * Copyright (C) 2012-2014, Marvell International Ltd.
   5  *
   6  * This software file (the "File") is distributed by Marvell International
   7  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
   8  * (the "License").  You may use, redistribute and/or modify this File in
   9  * accordance with the terms and conditions of the License, a copy of which
  10  * is available by writing to the Free Software Foundation, Inc.,
  11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
  12  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  13  *
  14  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
  17  * this warranty disclaimer.
  18  */
  19 
  20 #include "main.h"
  21 #include "11ac.h"
  22 #include "11n.h"
  23 
  24 /* This function parses security related parameters from cfg80211_ap_settings
  25  * and sets into FW understandable bss_config structure.
  26  */
  27 int mwifiex_set_secure_params(struct mwifiex_private *priv,
  28                               struct mwifiex_uap_bss_param *bss_config,
  29                               struct cfg80211_ap_settings *params) {
  30         int i;
  31         struct mwifiex_wep_key wep_key;
  32 
  33         if (!params->privacy) {
  34                 bss_config->protocol = PROTOCOL_NO_SECURITY;
  35                 bss_config->key_mgmt = KEY_MGMT_NONE;
  36                 bss_config->wpa_cfg.length = 0;
  37                 priv->sec_info.wep_enabled = 0;
  38                 priv->sec_info.wpa_enabled = 0;
  39                 priv->sec_info.wpa2_enabled = 0;
  40 
  41                 return 0;
  42         }
  43 
  44         switch (params->auth_type) {
  45         case NL80211_AUTHTYPE_OPEN_SYSTEM:
  46                 bss_config->auth_mode = WLAN_AUTH_OPEN;
  47                 break;
  48         case NL80211_AUTHTYPE_SHARED_KEY:
  49                 bss_config->auth_mode = WLAN_AUTH_SHARED_KEY;
  50                 break;
  51         case NL80211_AUTHTYPE_NETWORK_EAP:
  52                 bss_config->auth_mode = WLAN_AUTH_LEAP;
  53                 break;
  54         default:
  55                 bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO;
  56                 break;
  57         }
  58 
  59         bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST;
  60 
  61         for (i = 0; i < params->crypto.n_akm_suites; i++) {
  62                 switch (params->crypto.akm_suites[i]) {
  63                 case WLAN_AKM_SUITE_8021X:
  64                         if (params->crypto.wpa_versions &
  65                             NL80211_WPA_VERSION_1) {
  66                                 bss_config->protocol = PROTOCOL_WPA;
  67                                 bss_config->key_mgmt = KEY_MGMT_EAP;
  68                         }
  69                         if (params->crypto.wpa_versions &
  70                             NL80211_WPA_VERSION_2) {
  71                                 bss_config->protocol |= PROTOCOL_WPA2;
  72                                 bss_config->key_mgmt = KEY_MGMT_EAP;
  73                         }
  74                         break;
  75                 case WLAN_AKM_SUITE_PSK:
  76                         if (params->crypto.wpa_versions &
  77                             NL80211_WPA_VERSION_1) {
  78                                 bss_config->protocol = PROTOCOL_WPA;
  79                                 bss_config->key_mgmt = KEY_MGMT_PSK;
  80                         }
  81                         if (params->crypto.wpa_versions &
  82                             NL80211_WPA_VERSION_2) {
  83                                 bss_config->protocol |= PROTOCOL_WPA2;
  84                                 bss_config->key_mgmt = KEY_MGMT_PSK;
  85                         }
  86                         break;
  87                 default:
  88                         break;
  89                 }
  90         }
  91         for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
  92                 switch (params->crypto.ciphers_pairwise[i]) {
  93                 case WLAN_CIPHER_SUITE_WEP40:
  94                 case WLAN_CIPHER_SUITE_WEP104:
  95                         break;
  96                 case WLAN_CIPHER_SUITE_TKIP:
  97                         if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
  98                                 bss_config->wpa_cfg.pairwise_cipher_wpa |=
  99                                                                 CIPHER_TKIP;
 100                         if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
 101                                 bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
 102                                                                 CIPHER_TKIP;
 103                         break;
 104                 case WLAN_CIPHER_SUITE_CCMP:
 105                         if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
 106                                 bss_config->wpa_cfg.pairwise_cipher_wpa |=
 107                                                                 CIPHER_AES_CCMP;
 108                         if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
 109                                 bss_config->wpa_cfg.pairwise_cipher_wpa2 |=
 110                                                                 CIPHER_AES_CCMP;
 111                 default:
 112                         break;
 113                 }
 114         }
 115 
 116         switch (params->crypto.cipher_group) {
 117         case WLAN_CIPHER_SUITE_WEP40:
 118         case WLAN_CIPHER_SUITE_WEP104:
 119                 if (priv->sec_info.wep_enabled) {
 120                         bss_config->protocol = PROTOCOL_STATIC_WEP;
 121                         bss_config->key_mgmt = KEY_MGMT_NONE;
 122                         bss_config->wpa_cfg.length = 0;
 123 
 124                         for (i = 0; i < NUM_WEP_KEYS; i++) {
 125                                 wep_key = priv->wep_key[i];
 126                                 bss_config->wep_cfg[i].key_index = i;
 127 
 128                                 if (priv->wep_key_curr_index == i)
 129                                         bss_config->wep_cfg[i].is_default = 1;
 130                                 else
 131                                         bss_config->wep_cfg[i].is_default = 0;
 132 
 133                                 bss_config->wep_cfg[i].length =
 134                                                              wep_key.key_length;
 135                                 memcpy(&bss_config->wep_cfg[i].key,
 136                                        &wep_key.key_material,
 137                                        wep_key.key_length);
 138                         }
 139                 }
 140                 break;
 141         case WLAN_CIPHER_SUITE_TKIP:
 142                 bss_config->wpa_cfg.group_cipher = CIPHER_TKIP;
 143                 break;
 144         case WLAN_CIPHER_SUITE_CCMP:
 145                 bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
 146                 break;
 147         default:
 148                 break;
 149         }
 150 
 151         return 0;
 152 }
 153 
 154 /* This function updates 11n related parameters from IE and sets them into
 155  * bss_config structure.
 156  */
 157 void
 158 mwifiex_set_ht_params(struct mwifiex_private *priv,
 159                       struct mwifiex_uap_bss_param *bss_cfg,
 160                       struct cfg80211_ap_settings *params)
 161 {
 162         const u8 *ht_ie;
 163 
 164         if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info))
 165                 return;
 166 
 167         ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
 168                                  params->beacon.tail_len);
 169         if (ht_ie) {
 170                 memcpy(&bss_cfg->ht_cap, ht_ie + 2,
 171                        sizeof(struct ieee80211_ht_cap));
 172                 priv->ap_11n_enabled = 1;
 173         } else {
 174                 memset(&bss_cfg->ht_cap, 0, sizeof(struct ieee80211_ht_cap));
 175                 bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
 176                 bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU;
 177         }
 178 
 179         return;
 180 }
 181 
 182 /* This function updates 11ac related parameters from IE
 183  * and sets them into bss_config structure.
 184  */
 185 void mwifiex_set_vht_params(struct mwifiex_private *priv,
 186                             struct mwifiex_uap_bss_param *bss_cfg,
 187                             struct cfg80211_ap_settings *params)
 188 {
 189         const u8 *vht_ie;
 190 
 191         vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
 192                                   params->beacon.tail_len);
 193         if (vht_ie) {
 194                 memcpy(&bss_cfg->vht_cap, vht_ie + 2,
 195                        sizeof(struct ieee80211_vht_cap));
 196                 priv->ap_11ac_enabled = 1;
 197         } else {
 198                 priv->ap_11ac_enabled = 0;
 199         }
 200 
 201         return;
 202 }
 203 
 204 /* This function updates 11ac related parameters from IE
 205  * and sets them into bss_config structure.
 206  */
 207 void mwifiex_set_tpc_params(struct mwifiex_private *priv,
 208                             struct mwifiex_uap_bss_param *bss_cfg,
 209                             struct cfg80211_ap_settings *params)
 210 {
 211         const u8 *tpc_ie;
 212 
 213         tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail,
 214                                   params->beacon.tail_len);
 215         if (tpc_ie)
 216                 bss_cfg->power_constraint = *(tpc_ie + 2);
 217         else
 218                 bss_cfg->power_constraint = 0;
 219 }
 220 
 221 /* Enable VHT only when cfg80211_ap_settings has VHT IE.
 222  * Otherwise disable VHT.
 223  */
 224 void mwifiex_set_vht_width(struct mwifiex_private *priv,
 225                            enum nl80211_chan_width width,
 226                            bool ap_11ac_enable)
 227 {
 228         struct mwifiex_adapter *adapter = priv->adapter;
 229         struct mwifiex_11ac_vht_cfg vht_cfg;
 230 
 231         vht_cfg.band_config = VHT_CFG_5GHZ;
 232         vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap;
 233 
 234         if (!ap_11ac_enable) {
 235                 vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET;
 236                 vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET;
 237         } else {
 238                 vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET;
 239                 vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET;
 240         }
 241 
 242         vht_cfg.misc_config  = VHT_CAP_UAP_ONLY;
 243 
 244         if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80)
 245                 vht_cfg.misc_config |= VHT_BW_80_160_80P80;
 246 
 247         mwifiex_send_cmd(priv, HostCmd_CMD_11AC_CFG,
 248                          HostCmd_ACT_GEN_SET, 0, &vht_cfg, true);
 249 
 250         return;
 251 }
 252 
 253 /* This function finds supported rates IE from beacon parameter and sets
 254  * these rates into bss_config structure.
 255  */
 256 void
 257 mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
 258                       struct cfg80211_ap_settings *params)
 259 {
 260         struct ieee_types_header *rate_ie;
 261         int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
 262         const u8 *var_pos = params->beacon.head + var_offset;
 263         int len = params->beacon.head_len - var_offset;
 264         u8 rate_len = 0;
 265 
 266         rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
 267         if (rate_ie) {
 268                 if (rate_ie->len > MWIFIEX_SUPPORTED_RATES)
 269                         return;
 270                 memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
 271                 rate_len = rate_ie->len;
 272         }
 273 
 274         rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
 275                                            params->beacon.tail,
 276                                            params->beacon.tail_len);
 277         if (rate_ie) {
 278                 if (rate_ie->len > MWIFIEX_SUPPORTED_RATES - rate_len)
 279                         return;
 280                 memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
 281         }
 282 
 283         return;
 284 }
 285 
 286 /* This function initializes some of mwifiex_uap_bss_param variables.
 287  * This helps FW in ignoring invalid values. These values may or may not
 288  * be get updated to valid ones at later stage.
 289  */
 290 void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config)
 291 {
 292         config->bcast_ssid_ctl = 0x7F;
 293         config->radio_ctl = 0x7F;
 294         config->dtim_period = 0x7F;
 295         config->beacon_period = 0x7FFF;
 296         config->auth_mode = 0x7F;
 297         config->rts_threshold = 0x7FFF;
 298         config->frag_threshold = 0x7FFF;
 299         config->retry_limit = 0x7F;
 300         config->qos_info = 0xFF;
 301 }
 302 
 303 /* This function parses BSS related parameters from structure
 304  * and prepares TLVs specific to WPA/WPA2 security.
 305  * These TLVs are appended to command buffer.
 306  */
 307 static void
 308 mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
 309 {
 310         struct host_cmd_tlv_pwk_cipher *pwk_cipher;
 311         struct host_cmd_tlv_gwk_cipher *gwk_cipher;
 312         struct host_cmd_tlv_passphrase *passphrase;
 313         struct host_cmd_tlv_akmp *tlv_akmp;
 314         struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
 315         u16 cmd_size = *param_size;
 316         u8 *tlv = *tlv_buf;
 317 
 318         tlv_akmp = (struct host_cmd_tlv_akmp *)tlv;
 319         tlv_akmp->header.type = cpu_to_le16(TLV_TYPE_UAP_AKMP);
 320         tlv_akmp->header.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) -
 321                                         sizeof(struct mwifiex_ie_types_header));
 322         tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation);
 323         tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt);
 324         cmd_size += sizeof(struct host_cmd_tlv_akmp);
 325         tlv += sizeof(struct host_cmd_tlv_akmp);
 326 
 327         if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) {
 328                 pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
 329                 pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
 330                 pwk_cipher->header.len =
 331                         cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
 332                                     sizeof(struct mwifiex_ie_types_header));
 333                 pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA);
 334                 pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa;
 335                 cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
 336                 tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
 337         }
 338 
 339         if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) {
 340                 pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv;
 341                 pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER);
 342                 pwk_cipher->header.len =
 343                         cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) -
 344                                     sizeof(struct mwifiex_ie_types_header));
 345                 pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2);
 346                 pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2;
 347                 cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher);
 348                 tlv += sizeof(struct host_cmd_tlv_pwk_cipher);
 349         }
 350 
 351         if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) {
 352                 gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv;
 353                 gwk_cipher->header.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER);
 354                 gwk_cipher->header.len =
 355                         cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) -
 356                                     sizeof(struct mwifiex_ie_types_header));
 357                 gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher;
 358                 cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher);
 359                 tlv += sizeof(struct host_cmd_tlv_gwk_cipher);
 360         }
 361 
 362         if (bss_cfg->wpa_cfg.length) {
 363                 passphrase = (struct host_cmd_tlv_passphrase *)tlv;
 364                 passphrase->header.type =
 365                                 cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE);
 366                 passphrase->header.len = cpu_to_le16(bss_cfg->wpa_cfg.length);
 367                 memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase,
 368                        bss_cfg->wpa_cfg.length);
 369                 cmd_size += sizeof(struct mwifiex_ie_types_header) +
 370                             bss_cfg->wpa_cfg.length;
 371                 tlv += sizeof(struct mwifiex_ie_types_header) +
 372                                 bss_cfg->wpa_cfg.length;
 373         }
 374 
 375         *param_size = cmd_size;
 376         *tlv_buf = tlv;
 377 
 378         return;
 379 }
 380 
 381 /* This function parses WMM related parameters from cfg80211_ap_settings
 382  * structure and updates bss_config structure.
 383  */
 384 void
 385 mwifiex_set_wmm_params(struct mwifiex_private *priv,
 386                        struct mwifiex_uap_bss_param *bss_cfg,
 387                        struct cfg80211_ap_settings *params)
 388 {
 389         const u8 *vendor_ie;
 390         const u8 *wmm_ie;
 391         u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
 392 
 393         vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
 394                                             WLAN_OUI_TYPE_MICROSOFT_WMM,
 395                                             params->beacon.tail,
 396                                             params->beacon.tail_len);
 397         if (vendor_ie) {
 398                 wmm_ie = vendor_ie;
 399                 if (*(wmm_ie + 1) > sizeof(struct mwifiex_types_wmm_info))
 400                         return;
 401                 memcpy(&bss_cfg->wmm_info, wmm_ie +
 402                        sizeof(struct ieee_types_header), *(wmm_ie + 1));
 403                 priv->wmm_enabled = 1;
 404         } else {
 405                 memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info));
 406                 memcpy(&bss_cfg->wmm_info.oui, wmm_oui, sizeof(wmm_oui));
 407                 bss_cfg->wmm_info.subtype = MWIFIEX_WMM_SUBTYPE;
 408                 bss_cfg->wmm_info.version = MWIFIEX_WMM_VERSION;
 409                 priv->wmm_enabled = 0;
 410         }
 411 
 412         bss_cfg->qos_info = 0x00;
 413         return;
 414 }
 415 /* This function parses BSS related parameters from structure
 416  * and prepares TLVs specific to WEP encryption.
 417  * These TLVs are appended to command buffer.
 418  */
 419 static void
 420 mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size)
 421 {
 422         struct host_cmd_tlv_wep_key *wep_key;
 423         u16 cmd_size = *param_size;
 424         int i;
 425         u8 *tlv = *tlv_buf;
 426         struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
 427 
 428         for (i = 0; i < NUM_WEP_KEYS; i++) {
 429                 if (bss_cfg->wep_cfg[i].length &&
 430                     (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 ||
 431                      bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) {
 432                         wep_key = (struct host_cmd_tlv_wep_key *)tlv;
 433                         wep_key->header.type =
 434                                 cpu_to_le16(TLV_TYPE_UAP_WEP_KEY);
 435                         wep_key->header.len =
 436                                 cpu_to_le16(bss_cfg->wep_cfg[i].length + 2);
 437                         wep_key->key_index = bss_cfg->wep_cfg[i].key_index;
 438                         wep_key->is_default = bss_cfg->wep_cfg[i].is_default;
 439                         memcpy(wep_key->key, bss_cfg->wep_cfg[i].key,
 440                                bss_cfg->wep_cfg[i].length);
 441                         cmd_size += sizeof(struct mwifiex_ie_types_header) + 2 +
 442                                     bss_cfg->wep_cfg[i].length;
 443                         tlv += sizeof(struct mwifiex_ie_types_header) + 2 +
 444                                     bss_cfg->wep_cfg[i].length;
 445                 }
 446         }
 447 
 448         *param_size = cmd_size;
 449         *tlv_buf = tlv;
 450 
 451         return;
 452 }
 453 
 454 /* This function enable 11D if userspace set the country IE.
 455  */
 456 void mwifiex_config_uap_11d(struct mwifiex_private *priv,
 457                             struct cfg80211_beacon_data *beacon_data)
 458 {
 459         enum state_11d_t state_11d;
 460         const u8 *country_ie;
 461 
 462         country_ie = cfg80211_find_ie(WLAN_EID_COUNTRY, beacon_data->tail,
 463                                       beacon_data->tail_len);
 464         if (country_ie) {
 465                 /* Send cmd to FW to enable 11D function */
 466                 state_11d = ENABLE_11D;
 467                 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
 468                                      HostCmd_ACT_GEN_SET, DOT11D_I,
 469                                      &state_11d, true)) {
 470                         mwifiex_dbg(priv->adapter, ERROR,
 471                                     "11D: failed to enable 11D\n");
 472                 }
 473         }
 474 }
 475 
 476 /* This function parses BSS related parameters from structure
 477  * and prepares TLVs. These TLVs are appended to command buffer.
 478 */
 479 static int
 480 mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 481 {
 482         struct host_cmd_tlv_dtim_period *dtim_period;
 483         struct host_cmd_tlv_beacon_period *beacon_period;
 484         struct host_cmd_tlv_ssid *ssid;
 485         struct host_cmd_tlv_bcast_ssid *bcast_ssid;
 486         struct host_cmd_tlv_channel_band *chan_band;
 487         struct host_cmd_tlv_frag_threshold *frag_threshold;
 488         struct host_cmd_tlv_rts_threshold *rts_threshold;
 489         struct host_cmd_tlv_retry_limit *retry_limit;
 490         struct host_cmd_tlv_encrypt_protocol *encrypt_protocol;
 491         struct host_cmd_tlv_auth_type *auth_type;
 492         struct host_cmd_tlv_rates *tlv_rates;
 493         struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer;
 494         struct host_cmd_tlv_power_constraint *pwr_ct;
 495         struct mwifiex_ie_types_htcap *htcap;
 496         struct mwifiex_ie_types_wmmcap *wmm_cap;
 497         struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
 498         int i;
 499         u16 cmd_size = *param_size;
 500 
 501         if (bss_cfg->ssid.ssid_len) {
 502                 ssid = (struct host_cmd_tlv_ssid *)tlv;
 503                 ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
 504                 ssid->header.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len);
 505                 memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len);
 506                 cmd_size += sizeof(struct mwifiex_ie_types_header) +
 507                             bss_cfg->ssid.ssid_len;
 508                 tlv += sizeof(struct mwifiex_ie_types_header) +
 509                                 bss_cfg->ssid.ssid_len;
 510 
 511                 bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv;
 512                 bcast_ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID);
 513                 bcast_ssid->header.len =
 514                                 cpu_to_le16(sizeof(bcast_ssid->bcast_ctl));
 515                 bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl;
 516                 cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid);
 517                 tlv += sizeof(struct host_cmd_tlv_bcast_ssid);
 518         }
 519         if (bss_cfg->rates[0]) {
 520                 tlv_rates = (struct host_cmd_tlv_rates *)tlv;
 521                 tlv_rates->header.type = cpu_to_le16(TLV_TYPE_UAP_RATES);
 522 
 523                 for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i];
 524                      i++)
 525                         tlv_rates->rates[i] = bss_cfg->rates[i];
 526 
 527                 tlv_rates->header.len = cpu_to_le16(i);
 528                 cmd_size += sizeof(struct host_cmd_tlv_rates) + i;
 529                 tlv += sizeof(struct host_cmd_tlv_rates) + i;
 530         }
 531         if (bss_cfg->channel &&
 532             (((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_BG &&
 533               bss_cfg->channel <= MAX_CHANNEL_BAND_BG) ||
 534             ((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_A &&
 535              bss_cfg->channel <= MAX_CHANNEL_BAND_A))) {
 536                 chan_band = (struct host_cmd_tlv_channel_band *)tlv;
 537                 chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
 538                 chan_band->header.len =
 539                         cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) -
 540                                     sizeof(struct mwifiex_ie_types_header));
 541                 chan_band->band_config = bss_cfg->band_cfg;
 542                 chan_band->channel = bss_cfg->channel;
 543                 cmd_size += sizeof(struct host_cmd_tlv_channel_band);
 544                 tlv += sizeof(struct host_cmd_tlv_channel_band);
 545         }
 546         if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD &&
 547             bss_cfg->beacon_period <= MAX_BEACON_PERIOD) {
 548                 beacon_period = (struct host_cmd_tlv_beacon_period *)tlv;
 549                 beacon_period->header.type =
 550                                         cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD);
 551                 beacon_period->header.len =
 552                         cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) -
 553                                     sizeof(struct mwifiex_ie_types_header));
 554                 beacon_period->period = cpu_to_le16(bss_cfg->beacon_period);
 555                 cmd_size += sizeof(struct host_cmd_tlv_beacon_period);
 556                 tlv += sizeof(struct host_cmd_tlv_beacon_period);
 557         }
 558         if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD &&
 559             bss_cfg->dtim_period <= MAX_DTIM_PERIOD) {
 560                 dtim_period = (struct host_cmd_tlv_dtim_period *)tlv;
 561                 dtim_period->header.type =
 562                         cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD);
 563                 dtim_period->header.len =
 564                         cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) -
 565                                     sizeof(struct mwifiex_ie_types_header));
 566                 dtim_period->period = bss_cfg->dtim_period;
 567                 cmd_size += sizeof(struct host_cmd_tlv_dtim_period);
 568                 tlv += sizeof(struct host_cmd_tlv_dtim_period);
 569         }
 570         if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) {
 571                 rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv;
 572                 rts_threshold->header.type =
 573                                         cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD);
 574                 rts_threshold->header.len =
 575                         cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) -
 576                                     sizeof(struct mwifiex_ie_types_header));
 577                 rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold);
 578                 cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
 579                 tlv += sizeof(struct host_cmd_tlv_frag_threshold);
 580         }
 581         if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) &&
 582             (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) {
 583                 frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv;
 584                 frag_threshold->header.type =
 585                                 cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD);
 586                 frag_threshold->header.len =
 587                         cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) -
 588                                     sizeof(struct mwifiex_ie_types_header));
 589                 frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold);
 590                 cmd_size += sizeof(struct host_cmd_tlv_frag_threshold);
 591                 tlv += sizeof(struct host_cmd_tlv_frag_threshold);
 592         }
 593         if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) {
 594                 retry_limit = (struct host_cmd_tlv_retry_limit *)tlv;
 595                 retry_limit->header.type =
 596                         cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT);
 597                 retry_limit->header.len =
 598                         cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) -
 599                                     sizeof(struct mwifiex_ie_types_header));
 600                 retry_limit->limit = (u8)bss_cfg->retry_limit;
 601                 cmd_size += sizeof(struct host_cmd_tlv_retry_limit);
 602                 tlv += sizeof(struct host_cmd_tlv_retry_limit);
 603         }
 604         if ((bss_cfg->protocol & PROTOCOL_WPA) ||
 605             (bss_cfg->protocol & PROTOCOL_WPA2) ||
 606             (bss_cfg->protocol & PROTOCOL_EAP))
 607                 mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size);
 608         else
 609                 mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size);
 610 
 611         if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) ||
 612             (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) {
 613                 auth_type = (struct host_cmd_tlv_auth_type *)tlv;
 614                 auth_type->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
 615                 auth_type->header.len =
 616                         cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) -
 617                         sizeof(struct mwifiex_ie_types_header));
 618                 auth_type->auth_type = (u8)bss_cfg->auth_mode;
 619                 cmd_size += sizeof(struct host_cmd_tlv_auth_type);
 620                 tlv += sizeof(struct host_cmd_tlv_auth_type);
 621         }
 622         if (bss_cfg->protocol) {
 623                 encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv;
 624                 encrypt_protocol->header.type =
 625                         cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL);
 626                 encrypt_protocol->header.len =
 627                         cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol)
 628                         - sizeof(struct mwifiex_ie_types_header));
 629                 encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol);
 630                 cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol);
 631                 tlv += sizeof(struct host_cmd_tlv_encrypt_protocol);
 632         }
 633 
 634         if (bss_cfg->ht_cap.cap_info) {
 635                 htcap = (struct mwifiex_ie_types_htcap *)tlv;
 636                 htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
 637                 htcap->header.len =
 638                                 cpu_to_le16(sizeof(struct ieee80211_ht_cap));
 639                 htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info;
 640                 htcap->ht_cap.ampdu_params_info =
 641                                              bss_cfg->ht_cap.ampdu_params_info;
 642                 memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs,
 643                        sizeof(struct ieee80211_mcs_info));
 644                 htcap->ht_cap.extended_ht_cap_info =
 645                                         bss_cfg->ht_cap.extended_ht_cap_info;
 646                 htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info;
 647                 htcap->ht_cap.antenna_selection_info =
 648                                         bss_cfg->ht_cap.antenna_selection_info;
 649                 cmd_size += sizeof(struct mwifiex_ie_types_htcap);
 650                 tlv += sizeof(struct mwifiex_ie_types_htcap);
 651         }
 652 
 653         if (bss_cfg->wmm_info.qos_info != 0xFF) {
 654                 wmm_cap = (struct mwifiex_ie_types_wmmcap *)tlv;
 655                 wmm_cap->header.type = cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC);
 656                 wmm_cap->header.len = cpu_to_le16(sizeof(wmm_cap->wmm_info));
 657                 memcpy(&wmm_cap->wmm_info, &bss_cfg->wmm_info,
 658                        sizeof(wmm_cap->wmm_info));
 659                 cmd_size += sizeof(struct mwifiex_ie_types_wmmcap);
 660                 tlv += sizeof(struct mwifiex_ie_types_wmmcap);
 661         }
 662 
 663         if (bss_cfg->sta_ao_timer) {
 664                 ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
 665                 ao_timer->header.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER);
 666                 ao_timer->header.len = cpu_to_le16(sizeof(*ao_timer) -
 667                                         sizeof(struct mwifiex_ie_types_header));
 668                 ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer);
 669                 cmd_size += sizeof(*ao_timer);
 670                 tlv += sizeof(*ao_timer);
 671         }
 672 
 673         if (bss_cfg->power_constraint) {
 674                 pwr_ct = (void *)tlv;
 675                 pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT);
 676                 pwr_ct->header.len = cpu_to_le16(sizeof(u8));
 677                 pwr_ct->constraint = bss_cfg->power_constraint;
 678                 cmd_size += sizeof(*pwr_ct);
 679                 tlv += sizeof(*pwr_ct);
 680         }
 681 
 682         if (bss_cfg->ps_sta_ao_timer) {
 683                 ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
 684                 ps_ao_timer->header.type =
 685                                 cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER);
 686                 ps_ao_timer->header.len = cpu_to_le16(sizeof(*ps_ao_timer) -
 687                                 sizeof(struct mwifiex_ie_types_header));
 688                 ps_ao_timer->sta_ao_timer =
 689                                         cpu_to_le32(bss_cfg->ps_sta_ao_timer);
 690                 cmd_size += sizeof(*ps_ao_timer);
 691                 tlv += sizeof(*ps_ao_timer);
 692         }
 693 
 694         *param_size = cmd_size;
 695 
 696         return 0;
 697 }
 698 
 699 /* This function parses custom IEs from IE list and prepares command buffer */
 700 static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
 701 {
 702         struct mwifiex_ie_list *ap_ie = cmd_buf;
 703         struct mwifiex_ie_types_header *tlv_ie = (void *)tlv;
 704 
 705         if (!ap_ie || !ap_ie->len)
 706                 return -1;
 707 
 708         *ie_size += le16_to_cpu(ap_ie->len) +
 709                         sizeof(struct mwifiex_ie_types_header);
 710 
 711         tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
 712         tlv_ie->len = ap_ie->len;
 713         tlv += sizeof(struct mwifiex_ie_types_header);
 714 
 715         memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
 716 
 717         return 0;
 718 }
 719 
 720 /* Parse AP config structure and prepare TLV based command structure
 721  * to be sent to FW for uAP configuration
 722  */
 723 static int
 724 mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
 725                            u32 type, void *cmd_buf)
 726 {
 727         u8 *tlv;
 728         u16 cmd_size, param_size, ie_size;
 729         struct host_cmd_ds_sys_config *sys_cfg;
 730 
 731         cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG);
 732         cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN);
 733         sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config;
 734         sys_cfg->action = cpu_to_le16(cmd_action);
 735         tlv = sys_cfg->tlv;
 736 
 737         switch (type) {
 738         case UAP_BSS_PARAMS_I:
 739                 param_size = cmd_size;
 740                 if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, &param_size))
 741                         return -1;
 742                 cmd->size = cpu_to_le16(param_size);
 743                 break;
 744         case UAP_CUSTOM_IE_I:
 745                 ie_size = cmd_size;
 746                 if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size))
 747                         return -1;
 748                 cmd->size = cpu_to_le16(ie_size);
 749                 break;
 750         default:
 751                 return -1;
 752         }
 753 
 754         return 0;
 755 }
 756 
 757 /* This function prepares AP specific deauth command with mac supplied in
 758  * function parameter.
 759  */
 760 static int mwifiex_cmd_uap_sta_deauth(struct mwifiex_private *priv,
 761                                       struct host_cmd_ds_command *cmd, u8 *mac)
 762 {
 763         struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth;
 764 
 765         cmd->command = cpu_to_le16(HostCmd_CMD_UAP_STA_DEAUTH);
 766         memcpy(sta_deauth->mac, mac, ETH_ALEN);
 767         sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
 768 
 769         cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) +
 770                                 S_DS_GEN);
 771         return 0;
 772 }
 773 
 774 /* This function prepares the AP specific commands before sending them
 775  * to the firmware.
 776  * This is a generic function which calls specific command preparation
 777  * routines based upon the command number.
 778  */
 779 int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
 780                             u16 cmd_action, u32 type,
 781                             void *data_buf, void *cmd_buf)
 782 {
 783         struct host_cmd_ds_command *cmd = cmd_buf;
 784 
 785         switch (cmd_no) {
 786         case HostCmd_CMD_UAP_SYS_CONFIG:
 787                 if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf))
 788                         return -1;
 789                 break;
 790         case HostCmd_CMD_UAP_BSS_START:
 791         case HostCmd_CMD_UAP_BSS_STOP:
 792         case HOST_CMD_APCMD_SYS_RESET:
 793         case HOST_CMD_APCMD_STA_LIST:
 794                 cmd->command = cpu_to_le16(cmd_no);
 795                 cmd->size = cpu_to_le16(S_DS_GEN);
 796                 break;
 797         case HostCmd_CMD_UAP_STA_DEAUTH:
 798                 if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf))
 799                         return -1;
 800                 break;
 801         case HostCmd_CMD_CHAN_REPORT_REQUEST:
 802                 if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf,
 803                                                           data_buf))
 804                         return -1;
 805                 break;
 806         default:
 807                 mwifiex_dbg(priv->adapter, ERROR,
 808                             "PREP_CMD: unknown cmd %#x\n", cmd_no);
 809                 return -1;
 810         }
 811 
 812         return 0;
 813 }
 814 
 815 void mwifiex_uap_set_channel(struct mwifiex_private *priv,
 816                              struct mwifiex_uap_bss_param *bss_cfg,
 817                              struct cfg80211_chan_def chandef)
 818 {
 819         u8 config_bands = 0, old_bands = priv->adapter->config_bands;
 820 
 821         priv->bss_chandef = chandef;
 822 
 823         bss_cfg->channel = ieee80211_frequency_to_channel(
 824                                                      chandef.chan->center_freq);
 825 
 826         /* Set appropriate bands */
 827         if (chandef.chan->band == NL80211_BAND_2GHZ) {
 828                 bss_cfg->band_cfg = BAND_CONFIG_BG;
 829                 config_bands = BAND_B | BAND_G;
 830 
 831                 if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
 832                         config_bands |= BAND_GN;
 833         } else {
 834                 bss_cfg->band_cfg = BAND_CONFIG_A;
 835                 config_bands = BAND_A;
 836 
 837                 if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
 838                         config_bands |= BAND_AN;
 839 
 840                 if (chandef.width > NL80211_CHAN_WIDTH_40)
 841                         config_bands |= BAND_AAC;
 842         }
 843 
 844         switch (chandef.width) {
 845         case NL80211_CHAN_WIDTH_5:
 846         case NL80211_CHAN_WIDTH_10:
 847         case NL80211_CHAN_WIDTH_20_NOHT:
 848         case NL80211_CHAN_WIDTH_20:
 849                 break;
 850         case NL80211_CHAN_WIDTH_40:
 851                 if (chandef.center_freq1 < chandef.chan->center_freq)
 852                         bss_cfg->band_cfg |= MWIFIEX_SEC_CHAN_BELOW;
 853                 else
 854                         bss_cfg->band_cfg |= MWIFIEX_SEC_CHAN_ABOVE;
 855                 break;
 856         case NL80211_CHAN_WIDTH_80:
 857         case NL80211_CHAN_WIDTH_80P80:
 858         case NL80211_CHAN_WIDTH_160:
 859                 bss_cfg->band_cfg |=
 860                     mwifiex_get_sec_chan_offset(bss_cfg->channel) << 4;
 861                 break;
 862         default:
 863                 mwifiex_dbg(priv->adapter,
 864                             WARN, "Unknown channel width: %d\n",
 865                             chandef.width);
 866                 break;
 867         }
 868 
 869         priv->adapter->config_bands = config_bands;
 870 
 871         if (old_bands != config_bands) {
 872                 mwifiex_send_domain_info_cmd_fw(priv->adapter->wiphy);
 873                 mwifiex_dnld_txpwr_table(priv);
 874         }
 875 }
 876 
 877 int mwifiex_config_start_uap(struct mwifiex_private *priv,
 878                              struct mwifiex_uap_bss_param *bss_cfg)
 879 {
 880         if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
 881                              HostCmd_ACT_GEN_SET,
 882                              UAP_BSS_PARAMS_I, bss_cfg, true)) {
 883                 mwifiex_dbg(priv->adapter, ERROR,
 884                             "Failed to set AP configuration\n");
 885                 return -1;
 886         }
 887 
 888         if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
 889                              HostCmd_ACT_GEN_SET, 0, NULL, true)) {
 890                 mwifiex_dbg(priv->adapter, ERROR,
 891                             "Failed to start the BSS\n");
 892                 return -1;
 893         }
 894 
 895         if (priv->sec_info.wep_enabled)
 896                 priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
 897         else
 898                 priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
 899 
 900         if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
 901                              HostCmd_ACT_GEN_SET, 0,
 902                              &priv->curr_pkt_filter, true))
 903                 return -1;
 904 
 905         return 0;
 906 }

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