1/* 2 * Marvell Wireless LAN device driver: association and ad-hoc start/join 3 * 4 * Copyright (C) 2011-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 "decl.h" 21#include "ioctl.h" 22#include "util.h" 23#include "fw.h" 24#include "main.h" 25#include "wmm.h" 26#include "11n.h" 27#include "11ac.h" 28 29#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) 30 31/* 32 * Append a generic IE as a pass through TLV to a TLV buffer. 33 * 34 * This function is called from the network join command preparation routine. 35 * 36 * If the IE buffer has been setup by the application, this routine appends 37 * the buffer as a pass through TLV type to the request. 38 */ 39static int 40mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer) 41{ 42 int ret_len = 0; 43 struct mwifiex_ie_types_header ie_header; 44 45 /* Null Checks */ 46 if (!buffer) 47 return 0; 48 if (!(*buffer)) 49 return 0; 50 51 /* 52 * If there is a generic ie buffer setup, append it to the return 53 * parameter buffer pointer. 54 */ 55 if (priv->gen_ie_buf_len) { 56 dev_dbg(priv->adapter->dev, 57 "info: %s: append generic ie len %d to %p\n", 58 __func__, priv->gen_ie_buf_len, *buffer); 59 60 /* Wrap the generic IE buffer with a pass through TLV type */ 61 ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); 62 ie_header.len = cpu_to_le16(priv->gen_ie_buf_len); 63 memcpy(*buffer, &ie_header, sizeof(ie_header)); 64 65 /* Increment the return size and the return buffer pointer 66 param */ 67 *buffer += sizeof(ie_header); 68 ret_len += sizeof(ie_header); 69 70 /* Copy the generic IE buffer to the output buffer, advance 71 pointer */ 72 memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len); 73 74 /* Increment the return size and the return buffer pointer 75 param */ 76 *buffer += priv->gen_ie_buf_len; 77 ret_len += priv->gen_ie_buf_len; 78 79 /* Reset the generic IE buffer */ 80 priv->gen_ie_buf_len = 0; 81 } 82 83 /* return the length appended to the buffer */ 84 return ret_len; 85} 86 87/* 88 * Append TSF tracking info from the scan table for the target AP. 89 * 90 * This function is called from the network join command preparation routine. 91 * 92 * The TSF table TSF sent to the firmware contains two TSF values: 93 * - The TSF of the target AP from its previous beacon/probe response 94 * - The TSF timestamp of our local MAC at the time we observed the 95 * beacon/probe response. 96 * 97 * The firmware uses the timestamp values to set an initial TSF value 98 * in the MAC for the new association after a reassociation attempt. 99 */ 100static int 101mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, 102 struct mwifiex_bssdescriptor *bss_desc) 103{ 104 struct mwifiex_ie_types_tsf_timestamp tsf_tlv; 105 __le64 tsf_val; 106 107 /* Null Checks */ 108 if (buffer == NULL) 109 return 0; 110 if (*buffer == NULL) 111 return 0; 112 113 memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp)); 114 115 tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP); 116 tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val)); 117 118 memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); 119 *buffer += sizeof(tsf_tlv.header); 120 121 /* TSF at the time when beacon/probe_response was received */ 122 tsf_val = cpu_to_le64(bss_desc->fw_tsf); 123 memcpy(*buffer, &tsf_val, sizeof(tsf_val)); 124 *buffer += sizeof(tsf_val); 125 126 tsf_val = cpu_to_le64(bss_desc->timestamp); 127 128 dev_dbg(priv->adapter->dev, 129 "info: %s: TSF offset calc: %016llx - %016llx\n", 130 __func__, bss_desc->timestamp, bss_desc->fw_tsf); 131 132 memcpy(*buffer, &tsf_val, sizeof(tsf_val)); 133 *buffer += sizeof(tsf_val); 134 135 return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val)); 136} 137 138/* 139 * This function finds out the common rates between rate1 and rate2. 140 * 141 * It will fill common rates in rate1 as output if found. 142 * 143 * NOTE: Setting the MSB of the basic rates needs to be taken 144 * care of, either before or after calling this function. 145 */ 146static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, 147 u32 rate1_size, u8 *rate2, u32 rate2_size) 148{ 149 int ret; 150 u8 *ptr = rate1, *tmp; 151 u32 i, j; 152 153 tmp = kmemdup(rate1, rate1_size, GFP_KERNEL); 154 if (!tmp) { 155 dev_err(priv->adapter->dev, "failed to alloc tmp buf\n"); 156 return -ENOMEM; 157 } 158 159 memset(rate1, 0, rate1_size); 160 161 for (i = 0; i < rate2_size && rate2[i]; i++) { 162 for (j = 0; j < rate1_size && tmp[j]; j++) { 163 /* Check common rate, excluding the bit for 164 basic rate */ 165 if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) { 166 *rate1++ = tmp[j]; 167 break; 168 } 169 } 170 } 171 172 dev_dbg(priv->adapter->dev, "info: Tx data rate set to %#x\n", 173 priv->data_rate); 174 175 if (!priv->is_data_rate_auto) { 176 while (*ptr) { 177 if ((*ptr & 0x7f) == priv->data_rate) { 178 ret = 0; 179 goto done; 180 } 181 ptr++; 182 } 183 dev_err(priv->adapter->dev, "previously set fixed data rate %#x" 184 " is not compatible with the network\n", 185 priv->data_rate); 186 187 ret = -1; 188 goto done; 189 } 190 191 ret = 0; 192done: 193 kfree(tmp); 194 return ret; 195} 196 197/* 198 * This function creates the intersection of the rates supported by a 199 * target BSS and our adapter settings for use in an assoc/join command. 200 */ 201static int 202mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, 203 struct mwifiex_bssdescriptor *bss_desc, 204 u8 *out_rates, u32 *out_rates_size) 205{ 206 u8 card_rates[MWIFIEX_SUPPORTED_RATES]; 207 u32 card_rates_size; 208 209 /* Copy AP supported rates */ 210 memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); 211 /* Get the STA supported rates */ 212 card_rates_size = mwifiex_get_active_data_rates(priv, card_rates); 213 /* Get the common rates between AP and STA supported rates */ 214 if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES, 215 card_rates, card_rates_size)) { 216 *out_rates_size = 0; 217 dev_err(priv->adapter->dev, "%s: cannot get common rates\n", 218 __func__); 219 return -1; 220 } 221 222 *out_rates_size = 223 min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES); 224 225 return 0; 226} 227 228/* 229 * This function appends a WPS IE. It is called from the network join command 230 * preparation routine. 231 * 232 * If the IE buffer has been setup by the application, this routine appends 233 * the buffer as a WPS TLV type to the request. 234 */ 235static int 236mwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer) 237{ 238 int retLen = 0; 239 struct mwifiex_ie_types_header ie_header; 240 241 if (!buffer || !*buffer) 242 return 0; 243 244 /* 245 * If there is a wps ie buffer setup, append it to the return 246 * parameter buffer pointer. 247 */ 248 if (priv->wps_ie_len) { 249 dev_dbg(priv->adapter->dev, "cmd: append wps ie %d to %p\n", 250 priv->wps_ie_len, *buffer); 251 252 /* Wrap the generic IE buffer with a pass through TLV type */ 253 ie_header.type = cpu_to_le16(TLV_TYPE_MGMT_IE); 254 ie_header.len = cpu_to_le16(priv->wps_ie_len); 255 memcpy(*buffer, &ie_header, sizeof(ie_header)); 256 *buffer += sizeof(ie_header); 257 retLen += sizeof(ie_header); 258 259 memcpy(*buffer, priv->wps_ie, priv->wps_ie_len); 260 *buffer += priv->wps_ie_len; 261 retLen += priv->wps_ie_len; 262 263 } 264 265 kfree(priv->wps_ie); 266 priv->wps_ie_len = 0; 267 return retLen; 268} 269 270/* 271 * This function appends a WAPI IE. 272 * 273 * This function is called from the network join command preparation routine. 274 * 275 * If the IE buffer has been setup by the application, this routine appends 276 * the buffer as a WAPI TLV type to the request. 277 */ 278static int 279mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer) 280{ 281 int retLen = 0; 282 struct mwifiex_ie_types_header ie_header; 283 284 /* Null Checks */ 285 if (buffer == NULL) 286 return 0; 287 if (*buffer == NULL) 288 return 0; 289 290 /* 291 * If there is a wapi ie buffer setup, append it to the return 292 * parameter buffer pointer. 293 */ 294 if (priv->wapi_ie_len) { 295 dev_dbg(priv->adapter->dev, "cmd: append wapi ie %d to %p\n", 296 priv->wapi_ie_len, *buffer); 297 298 /* Wrap the generic IE buffer with a pass through TLV type */ 299 ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE); 300 ie_header.len = cpu_to_le16(priv->wapi_ie_len); 301 memcpy(*buffer, &ie_header, sizeof(ie_header)); 302 303 /* Increment the return size and the return buffer pointer 304 param */ 305 *buffer += sizeof(ie_header); 306 retLen += sizeof(ie_header); 307 308 /* Copy the wapi IE buffer to the output buffer, advance 309 pointer */ 310 memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len); 311 312 /* Increment the return size and the return buffer pointer 313 param */ 314 *buffer += priv->wapi_ie_len; 315 retLen += priv->wapi_ie_len; 316 317 } 318 /* return the length appended to the buffer */ 319 return retLen; 320} 321 322/* 323 * This function appends rsn ie tlv for wpa/wpa2 security modes. 324 * It is called from the network join command preparation routine. 325 */ 326static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv, 327 u8 **buffer) 328{ 329 struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv; 330 int rsn_ie_len; 331 332 if (!buffer || !(*buffer)) 333 return 0; 334 335 rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer); 336 rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]); 337 rsn_ie_tlv->header.type = cpu_to_le16( 338 le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF); 339 rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]); 340 rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len) 341 & 0x00FF); 342 if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2)) 343 memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2], 344 le16_to_cpu(rsn_ie_tlv->header.len)); 345 else 346 return -1; 347 348 rsn_ie_len = sizeof(rsn_ie_tlv->header) + 349 le16_to_cpu(rsn_ie_tlv->header.len); 350 *buffer += rsn_ie_len; 351 352 return rsn_ie_len; 353} 354 355/* 356 * This function prepares command for association. 357 * 358 * This sets the following parameters - 359 * - Peer MAC address 360 * - Listen interval 361 * - Beacon interval 362 * - Capability information 363 * 364 * ...and the following TLVs, as required - 365 * - SSID TLV 366 * - PHY TLV 367 * - SS TLV 368 * - Rates TLV 369 * - Authentication TLV 370 * - Channel TLV 371 * - WPA/WPA2 IE 372 * - 11n TLV 373 * - Vendor specific TLV 374 * - WMM TLV 375 * - WAPI IE 376 * - Generic IE 377 * - TSF TLV 378 * 379 * Preparation also includes - 380 * - Setting command ID and proper size 381 * - Ensuring correct endian-ness 382 */ 383int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, 384 struct host_cmd_ds_command *cmd, 385 struct mwifiex_bssdescriptor *bss_desc) 386{ 387 struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate; 388 struct mwifiex_ie_types_ssid_param_set *ssid_tlv; 389 struct mwifiex_ie_types_phy_param_set *phy_tlv; 390 struct mwifiex_ie_types_ss_param_set *ss_tlv; 391 struct mwifiex_ie_types_rates_param_set *rates_tlv; 392 struct mwifiex_ie_types_auth_type *auth_tlv; 393 struct mwifiex_ie_types_chan_list_param_set *chan_tlv; 394 u8 rates[MWIFIEX_SUPPORTED_RATES]; 395 u32 rates_size; 396 u16 tmp_cap; 397 u8 *pos; 398 int rsn_ie_len = 0; 399 400 pos = (u8 *) assoc; 401 402 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE); 403 404 /* Save so we know which BSS Desc to use in the response handler */ 405 priv->attempted_bss_desc = bss_desc; 406 407 memcpy(assoc->peer_sta_addr, 408 bss_desc->mac_address, sizeof(assoc->peer_sta_addr)); 409 pos += sizeof(assoc->peer_sta_addr); 410 411 /* Set the listen interval */ 412 assoc->listen_interval = cpu_to_le16(priv->listen_interval); 413 /* Set the beacon period */ 414 assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period); 415 416 pos += sizeof(assoc->cap_info_bitmap); 417 pos += sizeof(assoc->listen_interval); 418 pos += sizeof(assoc->beacon_period); 419 pos += sizeof(assoc->dtim_period); 420 421 ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos; 422 ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID); 423 ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len); 424 memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid, 425 le16_to_cpu(ssid_tlv->header.len)); 426 pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len); 427 428 phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos; 429 phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS); 430 phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set)); 431 memcpy(&phy_tlv->fh_ds.ds_param_set, 432 &bss_desc->phy_param_set.ds_param_set.current_chan, 433 sizeof(phy_tlv->fh_ds.ds_param_set)); 434 pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len); 435 436 ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos; 437 ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS); 438 ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set)); 439 pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len); 440 441 /* Get the common rates supported between the driver and the BSS Desc */ 442 if (mwifiex_setup_rates_from_bssdesc 443 (priv, bss_desc, rates, &rates_size)) 444 return -1; 445 446 /* Save the data rates into Current BSS state structure */ 447 priv->curr_bss_params.num_of_rates = rates_size; 448 memcpy(&priv->curr_bss_params.data_rates, rates, rates_size); 449 450 /* Setup the Rates TLV in the association command */ 451 rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos; 452 rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); 453 rates_tlv->header.len = cpu_to_le16((u16) rates_size); 454 memcpy(rates_tlv->rates, rates, rates_size); 455 pos += sizeof(rates_tlv->header) + rates_size; 456 dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: rates size = %d\n", 457 rates_size); 458 459 /* Add the Authentication type to be used for Auth frames */ 460 auth_tlv = (struct mwifiex_ie_types_auth_type *) pos; 461 auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); 462 auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type)); 463 if (priv->sec_info.wep_enabled) 464 auth_tlv->auth_type = cpu_to_le16( 465 (u16) priv->sec_info.authentication_mode); 466 else 467 auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM); 468 469 pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len); 470 471 if (IS_SUPPORT_MULTI_BANDS(priv->adapter) && 472 !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && 473 (!bss_desc->disable_11n) && 474 (priv->adapter->config_bands & BAND_GN || 475 priv->adapter->config_bands & BAND_AN) && 476 (bss_desc->bcn_ht_cap) 477 ) 478 ) { 479 /* Append a channel TLV for the channel the attempted AP was 480 found on */ 481 chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; 482 chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 483 chan_tlv->header.len = 484 cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); 485 486 memset(chan_tlv->chan_scan_param, 0x00, 487 sizeof(struct mwifiex_chan_scan_param_set)); 488 chan_tlv->chan_scan_param[0].chan_number = 489 (bss_desc->phy_param_set.ds_param_set.current_chan); 490 dev_dbg(priv->adapter->dev, "info: Assoc: TLV Chan = %d\n", 491 chan_tlv->chan_scan_param[0].chan_number); 492 493 chan_tlv->chan_scan_param[0].radio_type = 494 mwifiex_band_to_radio_type((u8) bss_desc->bss_band); 495 496 dev_dbg(priv->adapter->dev, "info: Assoc: TLV Band = %d\n", 497 chan_tlv->chan_scan_param[0].radio_type); 498 pos += sizeof(chan_tlv->header) + 499 sizeof(struct mwifiex_chan_scan_param_set); 500 } 501 502 if (!priv->wps.session_enable) { 503 if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) 504 rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); 505 506 if (rsn_ie_len == -1) 507 return -1; 508 } 509 510 if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && 511 (!bss_desc->disable_11n) && 512 (priv->adapter->config_bands & BAND_GN || 513 priv->adapter->config_bands & BAND_AN)) 514 mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); 515 516 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 517 !bss_desc->disable_11n && !bss_desc->disable_11ac && 518 priv->adapter->config_bands & BAND_AAC) 519 mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos); 520 521 /* Append vendor specific IE TLV */ 522 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); 523 524 mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie, 525 bss_desc->bcn_ht_cap); 526 if (priv->sec_info.wapi_enabled && priv->wapi_ie_len) 527 mwifiex_cmd_append_wapi_ie(priv, &pos); 528 529 if (priv->wps.session_enable && priv->wps_ie_len) 530 mwifiex_cmd_append_wps_ie(priv, &pos); 531 532 mwifiex_cmd_append_generic_ie(priv, &pos); 533 534 mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc); 535 536 mwifiex_11h_process_join(priv, &pos, bss_desc); 537 538 cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN); 539 540 /* Set the Capability info at last */ 541 tmp_cap = bss_desc->cap_info_bitmap; 542 543 if (priv->adapter->config_bands == BAND_B) 544 tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; 545 546 tmp_cap &= CAPINFO_MASK; 547 dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", 548 tmp_cap, CAPINFO_MASK); 549 assoc->cap_info_bitmap = cpu_to_le16(tmp_cap); 550 551 return 0; 552} 553 554/* 555 * Association firmware command response handler 556 * 557 * The response buffer for the association command has the following 558 * memory layout. 559 * 560 * For cases where an association response was not received (indicated 561 * by the CapInfo and AId field): 562 * 563 * .------------------------------------------------------------. 564 * | Header(4 * sizeof(t_u16)): Standard command response hdr | 565 * .------------------------------------------------------------. 566 * | cap_info/Error Return(t_u16): | 567 * | 0xFFFF(-1): Internal error | 568 * | 0xFFFE(-2): Authentication unhandled message | 569 * | 0xFFFD(-3): Authentication refused | 570 * | 0xFFFC(-4): Timeout waiting for AP response | 571 * .------------------------------------------------------------. 572 * | status_code(t_u16): | 573 * | If cap_info is -1: | 574 * | An internal firmware failure prevented the | 575 * | command from being processed. The status_code | 576 * | will be set to 1. | 577 * | | 578 * | If cap_info is -2: | 579 * | An authentication frame was received but was | 580 * | not handled by the firmware. IEEE Status | 581 * | code for the failure is returned. | 582 * | | 583 * | If cap_info is -3: | 584 * | An authentication frame was received and the | 585 * | status_code is the IEEE Status reported in the | 586 * | response. | 587 * | | 588 * | If cap_info is -4: | 589 * | (1) Association response timeout | 590 * | (2) Authentication response timeout | 591 * .------------------------------------------------------------. 592 * | a_id(t_u16): 0xFFFF | 593 * .------------------------------------------------------------. 594 * 595 * 596 * For cases where an association response was received, the IEEE 597 * standard association response frame is returned: 598 * 599 * .------------------------------------------------------------. 600 * | Header(4 * sizeof(t_u16)): Standard command response hdr | 601 * .------------------------------------------------------------. 602 * | cap_info(t_u16): IEEE Capability | 603 * .------------------------------------------------------------. 604 * | status_code(t_u16): IEEE Status Code | 605 * .------------------------------------------------------------. 606 * | a_id(t_u16): IEEE Association ID | 607 * .------------------------------------------------------------. 608 * | IEEE IEs(variable): Any received IEs comprising the | 609 * | remaining portion of a received | 610 * | association response frame. | 611 * .------------------------------------------------------------. 612 * 613 * For simplistic handling, the status_code field can be used to determine 614 * an association success (0) or failure (non-zero). 615 */ 616int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, 617 struct host_cmd_ds_command *resp) 618{ 619 struct mwifiex_adapter *adapter = priv->adapter; 620 int ret = 0; 621 struct ieee_types_assoc_rsp *assoc_rsp; 622 struct mwifiex_bssdescriptor *bss_desc; 623 bool enable_data = true; 624 u16 cap_info, status_code; 625 626 assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; 627 628 cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap); 629 status_code = le16_to_cpu(assoc_rsp->status_code); 630 631 priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, 632 sizeof(priv->assoc_rsp_buf)); 633 634 memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); 635 636 if (status_code) { 637 priv->adapter->dbg.num_cmd_assoc_failure++; 638 dev_err(priv->adapter->dev, 639 "ASSOC_RESP: failed, status code=%d err=%#x a_id=%#x\n", 640 status_code, cap_info, le16_to_cpu(assoc_rsp->a_id)); 641 642 if (cap_info == MWIFIEX_TIMEOUT_FOR_AP_RESP) { 643 if (status_code == MWIFIEX_STATUS_CODE_AUTH_TIMEOUT) 644 ret = WLAN_STATUS_AUTH_TIMEOUT; 645 else 646 ret = WLAN_STATUS_UNSPECIFIED_FAILURE; 647 } else { 648 ret = status_code; 649 } 650 651 goto done; 652 } 653 654 /* Send a Media Connected event, according to the Spec */ 655 priv->media_connected = true; 656 657 priv->adapter->ps_state = PS_STATE_AWAKE; 658 priv->adapter->pps_uapsd_mode = false; 659 priv->adapter->tx_lock_flag = false; 660 661 /* Set the attempted BSSID Index to current */ 662 bss_desc = priv->attempted_bss_desc; 663 664 dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: %s\n", 665 bss_desc->ssid.ssid); 666 667 /* Make a copy of current BSSID descriptor */ 668 memcpy(&priv->curr_bss_params.bss_descriptor, 669 bss_desc, sizeof(struct mwifiex_bssdescriptor)); 670 671 /* Update curr_bss_params */ 672 priv->curr_bss_params.bss_descriptor.channel 673 = bss_desc->phy_param_set.ds_param_set.current_chan; 674 675 priv->curr_bss_params.band = (u8) bss_desc->bss_band; 676 677 if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) 678 priv->curr_bss_params.wmm_enabled = true; 679 else 680 priv->curr_bss_params.wmm_enabled = false; 681 682 if ((priv->wmm_required || bss_desc->bcn_ht_cap) && 683 priv->curr_bss_params.wmm_enabled) 684 priv->wmm_enabled = true; 685 else 686 priv->wmm_enabled = false; 687 688 priv->curr_bss_params.wmm_uapsd_enabled = false; 689 690 if (priv->wmm_enabled) 691 priv->curr_bss_params.wmm_uapsd_enabled 692 = ((bss_desc->wmm_ie.qos_info_bitmap & 693 IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); 694 695 dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: curr_pkt_filter is %#x\n", 696 priv->curr_pkt_filter); 697 if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) 698 priv->wpa_is_gtk_set = false; 699 700 if (priv->wmm_enabled) { 701 /* Don't re-enable carrier until we get the WMM_GET_STATUS 702 event */ 703 enable_data = false; 704 } else { 705 /* Since WMM is not enabled, setup the queues with the 706 defaults */ 707 mwifiex_wmm_setup_queue_priorities(priv, NULL); 708 mwifiex_wmm_setup_ac_downgrade(priv); 709 } 710 711 if (enable_data) 712 dev_dbg(priv->adapter->dev, 713 "info: post association, re-enabling data flow\n"); 714 715 /* Reset SNR/NF/RSSI values */ 716 priv->data_rssi_last = 0; 717 priv->data_nf_last = 0; 718 priv->data_rssi_avg = 0; 719 priv->data_nf_avg = 0; 720 priv->bcn_rssi_last = 0; 721 priv->bcn_nf_last = 0; 722 priv->bcn_rssi_avg = 0; 723 priv->bcn_nf_avg = 0; 724 priv->rxpd_rate = 0; 725 priv->rxpd_htinfo = 0; 726 727 mwifiex_save_curr_bcn(priv); 728 729 priv->adapter->dbg.num_cmd_assoc_success++; 730 731 dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: associated\n"); 732 733 /* Add the ra_list here for infra mode as there will be only 1 ra 734 always */ 735 mwifiex_ralist_add(priv, 736 priv->curr_bss_params.bss_descriptor.mac_address); 737 738 if (!netif_carrier_ok(priv->netdev)) 739 netif_carrier_on(priv->netdev); 740 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); 741 742 if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) 743 priv->scan_block = true; 744 745done: 746 /* Need to indicate IOCTL complete */ 747 if (adapter->curr_cmd->wait_q_enabled) { 748 if (ret) 749 adapter->cmd_wait_q.status = -1; 750 else 751 adapter->cmd_wait_q.status = 0; 752 } 753 754 return ret; 755} 756 757/* 758 * This function prepares command for ad-hoc start. 759 * 760 * Driver will fill up SSID, BSS mode, IBSS parameters, physical 761 * parameters, probe delay, and capability information. Firmware 762 * will fill up beacon period, basic rates and operational rates. 763 * 764 * In addition, the following TLVs are added - 765 * - Channel TLV 766 * - Vendor specific IE 767 * - WPA/WPA2 IE 768 * - HT Capabilities IE 769 * - HT Information IE 770 * 771 * Preparation also includes - 772 * - Setting command ID and proper size 773 * - Ensuring correct endian-ness 774 */ 775int 776mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, 777 struct host_cmd_ds_command *cmd, 778 struct cfg80211_ssid *req_ssid) 779{ 780 int rsn_ie_len = 0; 781 struct mwifiex_adapter *adapter = priv->adapter; 782 struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start = 783 &cmd->params.adhoc_start; 784 struct mwifiex_bssdescriptor *bss_desc; 785 u32 cmd_append_size = 0; 786 u32 i; 787 u16 tmp_cap; 788 struct mwifiex_ie_types_chan_list_param_set *chan_tlv; 789 u8 radio_type; 790 791 struct mwifiex_ie_types_htcap *ht_cap; 792 struct mwifiex_ie_types_htinfo *ht_info; 793 u8 *pos = (u8 *) adhoc_start + 794 sizeof(struct host_cmd_ds_802_11_ad_hoc_start); 795 796 if (!adapter) 797 return -1; 798 799 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START); 800 801 bss_desc = &priv->curr_bss_params.bss_descriptor; 802 priv->attempted_bss_desc = bss_desc; 803 804 /* 805 * Fill in the parameters for 2 data structures: 806 * 1. struct host_cmd_ds_802_11_ad_hoc_start command 807 * 2. bss_desc 808 * Driver will fill up SSID, bss_mode,IBSS param, Physical Param, 809 * probe delay, and Cap info. 810 * Firmware will fill up beacon period, Basic rates 811 * and operational rates. 812 */ 813 814 memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); 815 816 memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len); 817 818 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n", 819 adhoc_start->ssid); 820 821 memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN); 822 memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len); 823 824 bss_desc->ssid.ssid_len = req_ssid->ssid_len; 825 826 /* Set the BSS mode */ 827 adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS; 828 bss_desc->bss_mode = NL80211_IFTYPE_ADHOC; 829 adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period); 830 bss_desc->beacon_period = priv->beacon_period; 831 832 /* Set Physical param set */ 833/* Parameter IE Id */ 834#define DS_PARA_IE_ID 3 835/* Parameter IE length */ 836#define DS_PARA_IE_LEN 1 837 838 adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID; 839 adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN; 840 841 if (!mwifiex_get_cfp(priv, adapter->adhoc_start_band, 842 (u16) priv->adhoc_channel, 0)) { 843 struct mwifiex_chan_freq_power *cfp; 844 cfp = mwifiex_get_cfp(priv, adapter->adhoc_start_band, 845 FIRST_VALID_CHANNEL, 0); 846 if (cfp) 847 priv->adhoc_channel = (u8) cfp->channel; 848 } 849 850 if (!priv->adhoc_channel) { 851 dev_err(adapter->dev, "ADHOC_S_CMD: adhoc_channel cannot be 0\n"); 852 return -1; 853 } 854 855 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: creating ADHOC on channel %d\n", 856 priv->adhoc_channel); 857 858 priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel; 859 priv->curr_bss_params.band = adapter->adhoc_start_band; 860 861 bss_desc->channel = priv->adhoc_channel; 862 adhoc_start->phy_param_set.ds_param_set.current_chan = 863 priv->adhoc_channel; 864 865 memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set, 866 sizeof(union ieee_types_phy_param_set)); 867 868 /* Set IBSS param set */ 869/* IBSS parameter IE Id */ 870#define IBSS_PARA_IE_ID 6 871/* IBSS parameter IE length */ 872#define IBSS_PARA_IE_LEN 2 873 874 adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID; 875 adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN; 876 adhoc_start->ss_param_set.ibss_param_set.atim_window 877 = cpu_to_le16(priv->atim_window); 878 memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set, 879 sizeof(union ieee_types_ss_param_set)); 880 881 /* Set Capability info */ 882 bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; 883 tmp_cap = WLAN_CAPABILITY_IBSS; 884 885 /* Set up privacy in bss_desc */ 886 if (priv->sec_info.encryption_mode) { 887 /* Ad-Hoc capability privacy on */ 888 dev_dbg(adapter->dev, 889 "info: ADHOC_S_CMD: wep_status set privacy to WEP\n"); 890 bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; 891 tmp_cap |= WLAN_CAPABILITY_PRIVACY; 892 } else { 893 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: wep_status NOT set," 894 " setting privacy to ACCEPT ALL\n"); 895 bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; 896 } 897 898 memset(adhoc_start->data_rate, 0, sizeof(adhoc_start->data_rate)); 899 mwifiex_get_active_data_rates(priv, adhoc_start->data_rate); 900 if ((adapter->adhoc_start_band & BAND_G) && 901 (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { 902 if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, 903 HostCmd_ACT_GEN_SET, 0, 904 &priv->curr_pkt_filter, false)) { 905 dev_err(adapter->dev, 906 "ADHOC_S_CMD: G Protection config failed\n"); 907 return -1; 908 } 909 } 910 /* Find the last non zero */ 911 for (i = 0; i < sizeof(adhoc_start->data_rate); i++) 912 if (!adhoc_start->data_rate[i]) 913 break; 914 915 priv->curr_bss_params.num_of_rates = i; 916 917 /* Copy the ad-hoc creating rates into Current BSS rate structure */ 918 memcpy(&priv->curr_bss_params.data_rates, 919 &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates); 920 921 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%4ph\n", 922 adhoc_start->data_rate); 923 924 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n"); 925 926 if (IS_SUPPORT_MULTI_BANDS(adapter)) { 927 /* Append a channel TLV */ 928 chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; 929 chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 930 chan_tlv->header.len = 931 cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); 932 933 memset(chan_tlv->chan_scan_param, 0x00, 934 sizeof(struct mwifiex_chan_scan_param_set)); 935 chan_tlv->chan_scan_param[0].chan_number = 936 (u8) priv->curr_bss_params.bss_descriptor.channel; 937 938 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Chan = %d\n", 939 chan_tlv->chan_scan_param[0].chan_number); 940 941 chan_tlv->chan_scan_param[0].radio_type 942 = mwifiex_band_to_radio_type(priv->curr_bss_params.band); 943 if (adapter->adhoc_start_band & BAND_GN || 944 adapter->adhoc_start_band & BAND_AN) { 945 if (adapter->sec_chan_offset == 946 IEEE80211_HT_PARAM_CHA_SEC_ABOVE) 947 chan_tlv->chan_scan_param[0].radio_type |= 948 (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4); 949 else if (adapter->sec_chan_offset == 950 IEEE80211_HT_PARAM_CHA_SEC_BELOW) 951 chan_tlv->chan_scan_param[0].radio_type |= 952 (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4); 953 } 954 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n", 955 chan_tlv->chan_scan_param[0].radio_type); 956 pos += sizeof(chan_tlv->header) + 957 sizeof(struct mwifiex_chan_scan_param_set); 958 cmd_append_size += 959 sizeof(chan_tlv->header) + 960 sizeof(struct mwifiex_chan_scan_param_set); 961 } 962 963 /* Append vendor specific IE TLV */ 964 cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, 965 MWIFIEX_VSIE_MASK_ADHOC, &pos); 966 967 if (priv->sec_info.wpa_enabled) { 968 rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); 969 if (rsn_ie_len == -1) 970 return -1; 971 cmd_append_size += rsn_ie_len; 972 } 973 974 if (adapter->adhoc_11n_enabled) { 975 /* Fill HT CAPABILITY */ 976 ht_cap = (struct mwifiex_ie_types_htcap *) pos; 977 memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); 978 ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); 979 ht_cap->header.len = 980 cpu_to_le16(sizeof(struct ieee80211_ht_cap)); 981 radio_type = mwifiex_band_to_radio_type( 982 priv->adapter->config_bands); 983 mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); 984 985 if (adapter->sec_chan_offset == 986 IEEE80211_HT_PARAM_CHA_SEC_NONE) { 987 u16 tmp_ht_cap; 988 989 tmp_ht_cap = le16_to_cpu(ht_cap->ht_cap.cap_info); 990 tmp_ht_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; 991 tmp_ht_cap &= ~IEEE80211_HT_CAP_SGI_40; 992 ht_cap->ht_cap.cap_info = cpu_to_le16(tmp_ht_cap); 993 } 994 995 pos += sizeof(struct mwifiex_ie_types_htcap); 996 cmd_append_size += sizeof(struct mwifiex_ie_types_htcap); 997 998 /* Fill HT INFORMATION */ 999 ht_info = (struct mwifiex_ie_types_htinfo *) pos; 1000 memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo)); 1001 ht_info->header.type = cpu_to_le16(WLAN_EID_HT_OPERATION); 1002 ht_info->header.len = 1003 cpu_to_le16(sizeof(struct ieee80211_ht_operation)); 1004 1005 ht_info->ht_oper.primary_chan = 1006 (u8) priv->curr_bss_params.bss_descriptor.channel; 1007 if (adapter->sec_chan_offset) { 1008 ht_info->ht_oper.ht_param = adapter->sec_chan_offset; 1009 ht_info->ht_oper.ht_param |= 1010 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; 1011 } 1012 ht_info->ht_oper.operation_mode = 1013 cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); 1014 ht_info->ht_oper.basic_set[0] = 0xff; 1015 pos += sizeof(struct mwifiex_ie_types_htinfo); 1016 cmd_append_size += 1017 sizeof(struct mwifiex_ie_types_htinfo); 1018 } 1019 1020 cmd->size = 1021 cpu_to_le16((u16)(sizeof(struct host_cmd_ds_802_11_ad_hoc_start) 1022 + S_DS_GEN + cmd_append_size)); 1023 1024 if (adapter->adhoc_start_band == BAND_B) 1025 tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; 1026 else 1027 tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME; 1028 1029 adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap); 1030 1031 return 0; 1032} 1033 1034/* 1035 * This function prepares command for ad-hoc join. 1036 * 1037 * Most of the parameters are set up by copying from the target BSS descriptor 1038 * from the scan response. 1039 * 1040 * In addition, the following TLVs are added - 1041 * - Channel TLV 1042 * - Vendor specific IE 1043 * - WPA/WPA2 IE 1044 * - 11n IE 1045 * 1046 * Preparation also includes - 1047 * - Setting command ID and proper size 1048 * - Ensuring correct endian-ness 1049 */ 1050int 1051mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, 1052 struct host_cmd_ds_command *cmd, 1053 struct mwifiex_bssdescriptor *bss_desc) 1054{ 1055 int rsn_ie_len = 0; 1056 struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join = 1057 &cmd->params.adhoc_join; 1058 struct mwifiex_ie_types_chan_list_param_set *chan_tlv; 1059 u32 cmd_append_size = 0; 1060 u16 tmp_cap; 1061 u32 i, rates_size = 0; 1062 u16 curr_pkt_filter; 1063 u8 *pos = 1064 (u8 *) adhoc_join + 1065 sizeof(struct host_cmd_ds_802_11_ad_hoc_join); 1066 1067/* Use G protection */ 1068#define USE_G_PROTECTION 0x02 1069 if (bss_desc->erp_flags & USE_G_PROTECTION) { 1070 curr_pkt_filter = 1071 priv-> 1072 curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; 1073 1074 if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, 1075 HostCmd_ACT_GEN_SET, 0, 1076 &curr_pkt_filter, false)) { 1077 dev_err(priv->adapter->dev, 1078 "ADHOC_J_CMD: G Protection config failed\n"); 1079 return -1; 1080 } 1081 } 1082 1083 priv->attempted_bss_desc = bss_desc; 1084 1085 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN); 1086 1087 adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS; 1088 1089 adhoc_join->bss_descriptor.beacon_period 1090 = cpu_to_le16(bss_desc->beacon_period); 1091 1092 memcpy(&adhoc_join->bss_descriptor.bssid, 1093 &bss_desc->mac_address, ETH_ALEN); 1094 1095 memcpy(&adhoc_join->bss_descriptor.ssid, 1096 &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len); 1097 1098 memcpy(&adhoc_join->bss_descriptor.phy_param_set, 1099 &bss_desc->phy_param_set, 1100 sizeof(union ieee_types_phy_param_set)); 1101 1102 memcpy(&adhoc_join->bss_descriptor.ss_param_set, 1103 &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set)); 1104 1105 tmp_cap = bss_desc->cap_info_bitmap; 1106 1107 tmp_cap &= CAPINFO_MASK; 1108 1109 dev_dbg(priv->adapter->dev, 1110 "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", 1111 tmp_cap, CAPINFO_MASK); 1112 1113 /* Information on BSSID descriptor passed to FW */ 1114 dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n", 1115 adhoc_join->bss_descriptor.bssid, 1116 adhoc_join->bss_descriptor.ssid); 1117 1118 for (i = 0; i < MWIFIEX_SUPPORTED_RATES && 1119 bss_desc->supported_rates[i]; i++) 1120 ; 1121 rates_size = i; 1122 1123 /* Copy Data Rates from the Rates recorded in scan response */ 1124 memset(adhoc_join->bss_descriptor.data_rates, 0, 1125 sizeof(adhoc_join->bss_descriptor.data_rates)); 1126 memcpy(adhoc_join->bss_descriptor.data_rates, 1127 bss_desc->supported_rates, rates_size); 1128 1129 /* Copy the adhoc join rates into Current BSS state structure */ 1130 priv->curr_bss_params.num_of_rates = rates_size; 1131 memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates, 1132 rates_size); 1133 1134 /* Copy the channel information */ 1135 priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel; 1136 priv->curr_bss_params.band = (u8) bss_desc->bss_band; 1137 1138 if (priv->sec_info.wep_enabled || priv->sec_info.wpa_enabled) 1139 tmp_cap |= WLAN_CAPABILITY_PRIVACY; 1140 1141 if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) { 1142 /* Append a channel TLV */ 1143 chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; 1144 chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 1145 chan_tlv->header.len = 1146 cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); 1147 1148 memset(chan_tlv->chan_scan_param, 0x00, 1149 sizeof(struct mwifiex_chan_scan_param_set)); 1150 chan_tlv->chan_scan_param[0].chan_number = 1151 (bss_desc->phy_param_set.ds_param_set.current_chan); 1152 dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Chan=%d\n", 1153 chan_tlv->chan_scan_param[0].chan_number); 1154 1155 chan_tlv->chan_scan_param[0].radio_type = 1156 mwifiex_band_to_radio_type((u8) bss_desc->bss_band); 1157 1158 dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Band=%d\n", 1159 chan_tlv->chan_scan_param[0].radio_type); 1160 pos += sizeof(chan_tlv->header) + 1161 sizeof(struct mwifiex_chan_scan_param_set); 1162 cmd_append_size += sizeof(chan_tlv->header) + 1163 sizeof(struct mwifiex_chan_scan_param_set); 1164 } 1165 1166 if (priv->sec_info.wpa_enabled) 1167 rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); 1168 if (rsn_ie_len == -1) 1169 return -1; 1170 cmd_append_size += rsn_ie_len; 1171 1172 if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) 1173 cmd_append_size += mwifiex_cmd_append_11n_tlv(priv, 1174 bss_desc, &pos); 1175 1176 /* Append vendor specific IE TLV */ 1177 cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, 1178 MWIFIEX_VSIE_MASK_ADHOC, &pos); 1179 1180 cmd->size = cpu_to_le16 1181 ((u16) (sizeof(struct host_cmd_ds_802_11_ad_hoc_join) 1182 + S_DS_GEN + cmd_append_size)); 1183 1184 adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); 1185 1186 return 0; 1187} 1188 1189/* 1190 * This function handles the command response of ad-hoc start and 1191 * ad-hoc join. 1192 * 1193 * The function generates a device-connected event to notify 1194 * the applications, in case of successful ad-hoc start/join, and 1195 * saves the beacon buffer. 1196 */ 1197int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, 1198 struct host_cmd_ds_command *resp) 1199{ 1200 int ret = 0; 1201 struct mwifiex_adapter *adapter = priv->adapter; 1202 struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result; 1203 struct mwifiex_bssdescriptor *bss_desc; 1204 u16 reason_code; 1205 1206 adhoc_result = &resp->params.adhoc_result; 1207 1208 bss_desc = priv->attempted_bss_desc; 1209 1210 /* Join result code 0 --> SUCCESS */ 1211 reason_code = le16_to_cpu(resp->result); 1212 if (reason_code) { 1213 dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n"); 1214 if (priv->media_connected) 1215 mwifiex_reset_connect_state(priv, reason_code); 1216 1217 memset(&priv->curr_bss_params.bss_descriptor, 1218 0x00, sizeof(struct mwifiex_bssdescriptor)); 1219 1220 ret = -1; 1221 goto done; 1222 } 1223 1224 /* Send a Media Connected event, according to the Spec */ 1225 priv->media_connected = true; 1226 1227 if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) { 1228 dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n", 1229 bss_desc->ssid.ssid); 1230 1231 /* Update the created network descriptor with the new BSSID */ 1232 memcpy(bss_desc->mac_address, 1233 adhoc_result->bssid, ETH_ALEN); 1234 1235 priv->adhoc_state = ADHOC_STARTED; 1236 } else { 1237 /* 1238 * Now the join cmd should be successful. 1239 * If BSSID has changed use SSID to compare instead of BSSID 1240 */ 1241 dev_dbg(priv->adapter->dev, "info: ADHOC_J_RESP %s\n", 1242 bss_desc->ssid.ssid); 1243 1244 /* 1245 * Make a copy of current BSSID descriptor, only needed for 1246 * join since the current descriptor is already being used 1247 * for adhoc start 1248 */ 1249 memcpy(&priv->curr_bss_params.bss_descriptor, 1250 bss_desc, sizeof(struct mwifiex_bssdescriptor)); 1251 1252 priv->adhoc_state = ADHOC_JOINED; 1253 } 1254 1255 dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: channel = %d\n", 1256 priv->adhoc_channel); 1257 dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: BSSID = %pM\n", 1258 priv->curr_bss_params.bss_descriptor.mac_address); 1259 1260 if (!netif_carrier_ok(priv->netdev)) 1261 netif_carrier_on(priv->netdev); 1262 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); 1263 1264 mwifiex_save_curr_bcn(priv); 1265 1266done: 1267 /* Need to indicate IOCTL complete */ 1268 if (adapter->curr_cmd->wait_q_enabled) { 1269 if (ret) 1270 adapter->cmd_wait_q.status = -1; 1271 else 1272 adapter->cmd_wait_q.status = 0; 1273 1274 } 1275 1276 return ret; 1277} 1278 1279/* 1280 * This function associates to a specific BSS discovered in a scan. 1281 * 1282 * It clears any past association response stored for application 1283 * retrieval and calls the command preparation routine to send the 1284 * command to firmware. 1285 */ 1286int mwifiex_associate(struct mwifiex_private *priv, 1287 struct mwifiex_bssdescriptor *bss_desc) 1288{ 1289 /* Return error if the adapter is not STA role or table entry 1290 * is not marked as infra. 1291 */ 1292 if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) || 1293 (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) 1294 return -1; 1295 1296 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 1297 !bss_desc->disable_11n && !bss_desc->disable_11ac && 1298 priv->adapter->config_bands & BAND_AAC) 1299 mwifiex_set_11ac_ba_params(priv); 1300 else 1301 mwifiex_set_ba_params(priv); 1302 1303 /* Clear any past association response stored for application 1304 retrieval */ 1305 priv->assoc_rsp_size = 0; 1306 1307 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE, 1308 HostCmd_ACT_GEN_SET, 0, bss_desc, true); 1309} 1310 1311/* 1312 * This function starts an ad-hoc network. 1313 * 1314 * It calls the command preparation routine to send the command to firmware. 1315 */ 1316int 1317mwifiex_adhoc_start(struct mwifiex_private *priv, 1318 struct cfg80211_ssid *adhoc_ssid) 1319{ 1320 dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n", 1321 priv->adhoc_channel); 1322 dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", 1323 priv->curr_bss_params.bss_descriptor.channel); 1324 dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", 1325 priv->curr_bss_params.band); 1326 1327 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 1328 priv->adapter->config_bands & BAND_AAC) 1329 mwifiex_set_11ac_ba_params(priv); 1330 else 1331 mwifiex_set_ba_params(priv); 1332 1333 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START, 1334 HostCmd_ACT_GEN_SET, 0, adhoc_ssid, true); 1335} 1336 1337/* 1338 * This function joins an ad-hoc network found in a previous scan. 1339 * 1340 * It calls the command preparation routine to send the command to firmware, 1341 * if already not connected to the requested SSID. 1342 */ 1343int mwifiex_adhoc_join(struct mwifiex_private *priv, 1344 struct mwifiex_bssdescriptor *bss_desc) 1345{ 1346 dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n", 1347 priv->curr_bss_params.bss_descriptor.ssid.ssid); 1348 dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n", 1349 priv->curr_bss_params.bss_descriptor.ssid.ssid_len); 1350 dev_dbg(priv->adapter->dev, "info: adhoc join: ssid =%s\n", 1351 bss_desc->ssid.ssid); 1352 dev_dbg(priv->adapter->dev, "info: adhoc join: ssid_len =%u\n", 1353 bss_desc->ssid.ssid_len); 1354 1355 /* Check if the requested SSID is already joined */ 1356 if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len && 1357 !mwifiex_ssid_cmp(&bss_desc->ssid, 1358 &priv->curr_bss_params.bss_descriptor.ssid) && 1359 (priv->curr_bss_params.bss_descriptor.bss_mode == 1360 NL80211_IFTYPE_ADHOC)) { 1361 dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: new ad-hoc SSID" 1362 " is the same as current; not attempting to re-join\n"); 1363 return -1; 1364 } 1365 1366 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 1367 !bss_desc->disable_11n && !bss_desc->disable_11ac && 1368 priv->adapter->config_bands & BAND_AAC) 1369 mwifiex_set_11ac_ba_params(priv); 1370 else 1371 mwifiex_set_ba_params(priv); 1372 1373 dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", 1374 priv->curr_bss_params.bss_descriptor.channel); 1375 dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", 1376 priv->curr_bss_params.band); 1377 1378 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, 1379 HostCmd_ACT_GEN_SET, 0, bss_desc, true); 1380} 1381 1382/* 1383 * This function deauthenticates/disconnects from infra network by sending 1384 * deauthentication request. 1385 */ 1386static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) 1387{ 1388 u8 mac_address[ETH_ALEN]; 1389 int ret; 1390 1391 if (!mac || is_zero_ether_addr(mac)) 1392 memcpy(mac_address, 1393 priv->curr_bss_params.bss_descriptor.mac_address, 1394 ETH_ALEN); 1395 else 1396 memcpy(mac_address, mac, ETH_ALEN); 1397 1398 ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, 1399 HostCmd_ACT_GEN_SET, 0, mac_address, true); 1400 1401 return ret; 1402} 1403 1404/* 1405 * This function deauthenticates/disconnects from a BSS. 1406 * 1407 * In case of infra made, it sends deauthentication request, and 1408 * in case of ad-hoc mode, a stop network request is sent to the firmware. 1409 * In AP mode, a command to stop bss is sent to firmware. 1410 */ 1411int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) 1412{ 1413 int ret = 0; 1414 1415 if (!priv->media_connected) 1416 return 0; 1417 1418 switch (priv->bss_mode) { 1419 case NL80211_IFTYPE_STATION: 1420 case NL80211_IFTYPE_P2P_CLIENT: 1421 ret = mwifiex_deauthenticate_infra(priv, mac); 1422 if (ret) 1423 cfg80211_disconnected(priv->netdev, 0, NULL, 0, 1424 GFP_KERNEL); 1425 break; 1426 case NL80211_IFTYPE_ADHOC: 1427 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP, 1428 HostCmd_ACT_GEN_SET, 0, NULL, true); 1429 case NL80211_IFTYPE_AP: 1430 return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, 1431 HostCmd_ACT_GEN_SET, 0, NULL, true); 1432 default: 1433 break; 1434 } 1435 1436 return ret; 1437} 1438 1439/* This function deauthenticates/disconnects from all BSS. */ 1440void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter) 1441{ 1442 struct mwifiex_private *priv; 1443 int i; 1444 1445 for (i = 0; i < adapter->priv_num; i++) { 1446 priv = adapter->priv[i]; 1447 if (priv) 1448 mwifiex_deauthenticate(priv, NULL); 1449 } 1450} 1451EXPORT_SYMBOL_GPL(mwifiex_deauthenticate_all); 1452 1453/* 1454 * This function converts band to radio type used in channel TLV. 1455 */ 1456u8 1457mwifiex_band_to_radio_type(u8 band) 1458{ 1459 switch (band) { 1460 case BAND_A: 1461 case BAND_AN: 1462 case BAND_A | BAND_AN: 1463 case BAND_A | BAND_AN | BAND_AAC: 1464 return HostCmd_SCAN_RADIO_TYPE_A; 1465 case BAND_B: 1466 case BAND_G: 1467 case BAND_B | BAND_G: 1468 default: 1469 return HostCmd_SCAN_RADIO_TYPE_BG; 1470 } 1471} 1472