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 = le16_to_cpu(adhoc_start->cap_info_bitmap); 884 tmp_cap &= ~WLAN_CAPABILITY_ESS; 885 tmp_cap |= WLAN_CAPABILITY_IBSS; 886 887 /* Set up privacy in bss_desc */ 888 if (priv->sec_info.encryption_mode) { 889 /* Ad-Hoc capability privacy on */ 890 dev_dbg(adapter->dev, 891 "info: ADHOC_S_CMD: wep_status set privacy to WEP\n"); 892 bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; 893 tmp_cap |= WLAN_CAPABILITY_PRIVACY; 894 } else { 895 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: wep_status NOT set," 896 " setting privacy to ACCEPT ALL\n"); 897 bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; 898 } 899 900 memset(adhoc_start->data_rate, 0, sizeof(adhoc_start->data_rate)); 901 mwifiex_get_active_data_rates(priv, adhoc_start->data_rate); 902 if ((adapter->adhoc_start_band & BAND_G) && 903 (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { 904 if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, 905 HostCmd_ACT_GEN_SET, 0, 906 &priv->curr_pkt_filter, false)) { 907 dev_err(adapter->dev, 908 "ADHOC_S_CMD: G Protection config failed\n"); 909 return -1; 910 } 911 } 912 /* Find the last non zero */ 913 for (i = 0; i < sizeof(adhoc_start->data_rate); i++) 914 if (!adhoc_start->data_rate[i]) 915 break; 916 917 priv->curr_bss_params.num_of_rates = i; 918 919 /* Copy the ad-hoc creating rates into Current BSS rate structure */ 920 memcpy(&priv->curr_bss_params.data_rates, 921 &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates); 922 923 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%4ph\n", 924 adhoc_start->data_rate); 925 926 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n"); 927 928 if (IS_SUPPORT_MULTI_BANDS(adapter)) { 929 /* Append a channel TLV */ 930 chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; 931 chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 932 chan_tlv->header.len = 933 cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); 934 935 memset(chan_tlv->chan_scan_param, 0x00, 936 sizeof(struct mwifiex_chan_scan_param_set)); 937 chan_tlv->chan_scan_param[0].chan_number = 938 (u8) priv->curr_bss_params.bss_descriptor.channel; 939 940 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Chan = %d\n", 941 chan_tlv->chan_scan_param[0].chan_number); 942 943 chan_tlv->chan_scan_param[0].radio_type 944 = mwifiex_band_to_radio_type(priv->curr_bss_params.band); 945 if (adapter->adhoc_start_band & BAND_GN || 946 adapter->adhoc_start_band & BAND_AN) { 947 if (adapter->sec_chan_offset == 948 IEEE80211_HT_PARAM_CHA_SEC_ABOVE) 949 chan_tlv->chan_scan_param[0].radio_type |= 950 (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4); 951 else if (adapter->sec_chan_offset == 952 IEEE80211_HT_PARAM_CHA_SEC_BELOW) 953 chan_tlv->chan_scan_param[0].radio_type |= 954 (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4); 955 } 956 dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n", 957 chan_tlv->chan_scan_param[0].radio_type); 958 pos += sizeof(chan_tlv->header) + 959 sizeof(struct mwifiex_chan_scan_param_set); 960 cmd_append_size += 961 sizeof(chan_tlv->header) + 962 sizeof(struct mwifiex_chan_scan_param_set); 963 } 964 965 /* Append vendor specific IE TLV */ 966 cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, 967 MWIFIEX_VSIE_MASK_ADHOC, &pos); 968 969 if (priv->sec_info.wpa_enabled) { 970 rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); 971 if (rsn_ie_len == -1) 972 return -1; 973 cmd_append_size += rsn_ie_len; 974 } 975 976 if (adapter->adhoc_11n_enabled) { 977 /* Fill HT CAPABILITY */ 978 ht_cap = (struct mwifiex_ie_types_htcap *) pos; 979 memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); 980 ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); 981 ht_cap->header.len = 982 cpu_to_le16(sizeof(struct ieee80211_ht_cap)); 983 radio_type = mwifiex_band_to_radio_type( 984 priv->adapter->config_bands); 985 mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); 986 987 if (adapter->sec_chan_offset == 988 IEEE80211_HT_PARAM_CHA_SEC_NONE) { 989 u16 tmp_ht_cap; 990 991 tmp_ht_cap = le16_to_cpu(ht_cap->ht_cap.cap_info); 992 tmp_ht_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; 993 tmp_ht_cap &= ~IEEE80211_HT_CAP_SGI_40; 994 ht_cap->ht_cap.cap_info = cpu_to_le16(tmp_ht_cap); 995 } 996 997 pos += sizeof(struct mwifiex_ie_types_htcap); 998 cmd_append_size += sizeof(struct mwifiex_ie_types_htcap); 999 1000 /* Fill HT INFORMATION */ 1001 ht_info = (struct mwifiex_ie_types_htinfo *) pos; 1002 memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo)); 1003 ht_info->header.type = cpu_to_le16(WLAN_EID_HT_OPERATION); 1004 ht_info->header.len = 1005 cpu_to_le16(sizeof(struct ieee80211_ht_operation)); 1006 1007 ht_info->ht_oper.primary_chan = 1008 (u8) priv->curr_bss_params.bss_descriptor.channel; 1009 if (adapter->sec_chan_offset) { 1010 ht_info->ht_oper.ht_param = adapter->sec_chan_offset; 1011 ht_info->ht_oper.ht_param |= 1012 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; 1013 } 1014 ht_info->ht_oper.operation_mode = 1015 cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); 1016 ht_info->ht_oper.basic_set[0] = 0xff; 1017 pos += sizeof(struct mwifiex_ie_types_htinfo); 1018 cmd_append_size += 1019 sizeof(struct mwifiex_ie_types_htinfo); 1020 } 1021 1022 cmd->size = 1023 cpu_to_le16((u16)(sizeof(struct host_cmd_ds_802_11_ad_hoc_start) 1024 + S_DS_GEN + cmd_append_size)); 1025 1026 if (adapter->adhoc_start_band == BAND_B) 1027 tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; 1028 else 1029 tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME; 1030 1031 adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap); 1032 1033 return 0; 1034} 1035 1036/* 1037 * This function prepares command for ad-hoc join. 1038 * 1039 * Most of the parameters are set up by copying from the target BSS descriptor 1040 * from the scan response. 1041 * 1042 * In addition, the following TLVs are added - 1043 * - Channel TLV 1044 * - Vendor specific IE 1045 * - WPA/WPA2 IE 1046 * - 11n IE 1047 * 1048 * Preparation also includes - 1049 * - Setting command ID and proper size 1050 * - Ensuring correct endian-ness 1051 */ 1052int 1053mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, 1054 struct host_cmd_ds_command *cmd, 1055 struct mwifiex_bssdescriptor *bss_desc) 1056{ 1057 int rsn_ie_len = 0; 1058 struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join = 1059 &cmd->params.adhoc_join; 1060 struct mwifiex_ie_types_chan_list_param_set *chan_tlv; 1061 u32 cmd_append_size = 0; 1062 u16 tmp_cap; 1063 u32 i, rates_size = 0; 1064 u16 curr_pkt_filter; 1065 u8 *pos = 1066 (u8 *) adhoc_join + 1067 sizeof(struct host_cmd_ds_802_11_ad_hoc_join); 1068 1069/* Use G protection */ 1070#define USE_G_PROTECTION 0x02 1071 if (bss_desc->erp_flags & USE_G_PROTECTION) { 1072 curr_pkt_filter = 1073 priv-> 1074 curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; 1075 1076 if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, 1077 HostCmd_ACT_GEN_SET, 0, 1078 &curr_pkt_filter, false)) { 1079 dev_err(priv->adapter->dev, 1080 "ADHOC_J_CMD: G Protection config failed\n"); 1081 return -1; 1082 } 1083 } 1084 1085 priv->attempted_bss_desc = bss_desc; 1086 1087 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN); 1088 1089 adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS; 1090 1091 adhoc_join->bss_descriptor.beacon_period 1092 = cpu_to_le16(bss_desc->beacon_period); 1093 1094 memcpy(&adhoc_join->bss_descriptor.bssid, 1095 &bss_desc->mac_address, ETH_ALEN); 1096 1097 memcpy(&adhoc_join->bss_descriptor.ssid, 1098 &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len); 1099 1100 memcpy(&adhoc_join->bss_descriptor.phy_param_set, 1101 &bss_desc->phy_param_set, 1102 sizeof(union ieee_types_phy_param_set)); 1103 1104 memcpy(&adhoc_join->bss_descriptor.ss_param_set, 1105 &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set)); 1106 1107 tmp_cap = bss_desc->cap_info_bitmap; 1108 1109 tmp_cap &= CAPINFO_MASK; 1110 1111 dev_dbg(priv->adapter->dev, 1112 "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", 1113 tmp_cap, CAPINFO_MASK); 1114 1115 /* Information on BSSID descriptor passed to FW */ 1116 dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n", 1117 adhoc_join->bss_descriptor.bssid, 1118 adhoc_join->bss_descriptor.ssid); 1119 1120 for (i = 0; i < MWIFIEX_SUPPORTED_RATES && 1121 bss_desc->supported_rates[i]; i++) 1122 ; 1123 rates_size = i; 1124 1125 /* Copy Data Rates from the Rates recorded in scan response */ 1126 memset(adhoc_join->bss_descriptor.data_rates, 0, 1127 sizeof(adhoc_join->bss_descriptor.data_rates)); 1128 memcpy(adhoc_join->bss_descriptor.data_rates, 1129 bss_desc->supported_rates, rates_size); 1130 1131 /* Copy the adhoc join rates into Current BSS state structure */ 1132 priv->curr_bss_params.num_of_rates = rates_size; 1133 memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates, 1134 rates_size); 1135 1136 /* Copy the channel information */ 1137 priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel; 1138 priv->curr_bss_params.band = (u8) bss_desc->bss_band; 1139 1140 if (priv->sec_info.wep_enabled || priv->sec_info.wpa_enabled) 1141 tmp_cap |= WLAN_CAPABILITY_PRIVACY; 1142 1143 if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) { 1144 /* Append a channel TLV */ 1145 chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; 1146 chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 1147 chan_tlv->header.len = 1148 cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); 1149 1150 memset(chan_tlv->chan_scan_param, 0x00, 1151 sizeof(struct mwifiex_chan_scan_param_set)); 1152 chan_tlv->chan_scan_param[0].chan_number = 1153 (bss_desc->phy_param_set.ds_param_set.current_chan); 1154 dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Chan=%d\n", 1155 chan_tlv->chan_scan_param[0].chan_number); 1156 1157 chan_tlv->chan_scan_param[0].radio_type = 1158 mwifiex_band_to_radio_type((u8) bss_desc->bss_band); 1159 1160 dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Band=%d\n", 1161 chan_tlv->chan_scan_param[0].radio_type); 1162 pos += sizeof(chan_tlv->header) + 1163 sizeof(struct mwifiex_chan_scan_param_set); 1164 cmd_append_size += sizeof(chan_tlv->header) + 1165 sizeof(struct mwifiex_chan_scan_param_set); 1166 } 1167 1168 if (priv->sec_info.wpa_enabled) 1169 rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); 1170 if (rsn_ie_len == -1) 1171 return -1; 1172 cmd_append_size += rsn_ie_len; 1173 1174 if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) 1175 cmd_append_size += mwifiex_cmd_append_11n_tlv(priv, 1176 bss_desc, &pos); 1177 1178 /* Append vendor specific IE TLV */ 1179 cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, 1180 MWIFIEX_VSIE_MASK_ADHOC, &pos); 1181 1182 cmd->size = cpu_to_le16 1183 ((u16) (sizeof(struct host_cmd_ds_802_11_ad_hoc_join) 1184 + S_DS_GEN + cmd_append_size)); 1185 1186 adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); 1187 1188 return 0; 1189} 1190 1191/* 1192 * This function handles the command response of ad-hoc start and 1193 * ad-hoc join. 1194 * 1195 * The function generates a device-connected event to notify 1196 * the applications, in case of successful ad-hoc start/join, and 1197 * saves the beacon buffer. 1198 */ 1199int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, 1200 struct host_cmd_ds_command *resp) 1201{ 1202 int ret = 0; 1203 struct mwifiex_adapter *adapter = priv->adapter; 1204 struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result; 1205 struct mwifiex_bssdescriptor *bss_desc; 1206 u16 reason_code; 1207 1208 adhoc_result = &resp->params.adhoc_result; 1209 1210 bss_desc = priv->attempted_bss_desc; 1211 1212 /* Join result code 0 --> SUCCESS */ 1213 reason_code = le16_to_cpu(resp->result); 1214 if (reason_code) { 1215 dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n"); 1216 if (priv->media_connected) 1217 mwifiex_reset_connect_state(priv, reason_code); 1218 1219 memset(&priv->curr_bss_params.bss_descriptor, 1220 0x00, sizeof(struct mwifiex_bssdescriptor)); 1221 1222 ret = -1; 1223 goto done; 1224 } 1225 1226 /* Send a Media Connected event, according to the Spec */ 1227 priv->media_connected = true; 1228 1229 if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) { 1230 dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n", 1231 bss_desc->ssid.ssid); 1232 1233 /* Update the created network descriptor with the new BSSID */ 1234 memcpy(bss_desc->mac_address, 1235 adhoc_result->bssid, ETH_ALEN); 1236 1237 priv->adhoc_state = ADHOC_STARTED; 1238 } else { 1239 /* 1240 * Now the join cmd should be successful. 1241 * If BSSID has changed use SSID to compare instead of BSSID 1242 */ 1243 dev_dbg(priv->adapter->dev, "info: ADHOC_J_RESP %s\n", 1244 bss_desc->ssid.ssid); 1245 1246 /* 1247 * Make a copy of current BSSID descriptor, only needed for 1248 * join since the current descriptor is already being used 1249 * for adhoc start 1250 */ 1251 memcpy(&priv->curr_bss_params.bss_descriptor, 1252 bss_desc, sizeof(struct mwifiex_bssdescriptor)); 1253 1254 priv->adhoc_state = ADHOC_JOINED; 1255 } 1256 1257 dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: channel = %d\n", 1258 priv->adhoc_channel); 1259 dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: BSSID = %pM\n", 1260 priv->curr_bss_params.bss_descriptor.mac_address); 1261 1262 if (!netif_carrier_ok(priv->netdev)) 1263 netif_carrier_on(priv->netdev); 1264 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); 1265 1266 mwifiex_save_curr_bcn(priv); 1267 1268done: 1269 /* Need to indicate IOCTL complete */ 1270 if (adapter->curr_cmd->wait_q_enabled) { 1271 if (ret) 1272 adapter->cmd_wait_q.status = -1; 1273 else 1274 adapter->cmd_wait_q.status = 0; 1275 1276 } 1277 1278 return ret; 1279} 1280 1281/* 1282 * This function associates to a specific BSS discovered in a scan. 1283 * 1284 * It clears any past association response stored for application 1285 * retrieval and calls the command preparation routine to send the 1286 * command to firmware. 1287 */ 1288int mwifiex_associate(struct mwifiex_private *priv, 1289 struct mwifiex_bssdescriptor *bss_desc) 1290{ 1291 /* Return error if the adapter is not STA role or table entry 1292 * is not marked as infra. 1293 */ 1294 if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) || 1295 (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) 1296 return -1; 1297 1298 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 1299 !bss_desc->disable_11n && !bss_desc->disable_11ac && 1300 priv->adapter->config_bands & BAND_AAC) 1301 mwifiex_set_11ac_ba_params(priv); 1302 else 1303 mwifiex_set_ba_params(priv); 1304 1305 /* Clear any past association response stored for application 1306 retrieval */ 1307 priv->assoc_rsp_size = 0; 1308 1309 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE, 1310 HostCmd_ACT_GEN_SET, 0, bss_desc, true); 1311} 1312 1313/* 1314 * This function starts an ad-hoc network. 1315 * 1316 * It calls the command preparation routine to send the command to firmware. 1317 */ 1318int 1319mwifiex_adhoc_start(struct mwifiex_private *priv, 1320 struct cfg80211_ssid *adhoc_ssid) 1321{ 1322 dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n", 1323 priv->adhoc_channel); 1324 dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", 1325 priv->curr_bss_params.bss_descriptor.channel); 1326 dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", 1327 priv->curr_bss_params.band); 1328 1329 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 1330 priv->adapter->config_bands & BAND_AAC) 1331 mwifiex_set_11ac_ba_params(priv); 1332 else 1333 mwifiex_set_ba_params(priv); 1334 1335 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START, 1336 HostCmd_ACT_GEN_SET, 0, adhoc_ssid, true); 1337} 1338 1339/* 1340 * This function joins an ad-hoc network found in a previous scan. 1341 * 1342 * It calls the command preparation routine to send the command to firmware, 1343 * if already not connected to the requested SSID. 1344 */ 1345int mwifiex_adhoc_join(struct mwifiex_private *priv, 1346 struct mwifiex_bssdescriptor *bss_desc) 1347{ 1348 dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n", 1349 priv->curr_bss_params.bss_descriptor.ssid.ssid); 1350 dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n", 1351 priv->curr_bss_params.bss_descriptor.ssid.ssid_len); 1352 dev_dbg(priv->adapter->dev, "info: adhoc join: ssid =%s\n", 1353 bss_desc->ssid.ssid); 1354 dev_dbg(priv->adapter->dev, "info: adhoc join: ssid_len =%u\n", 1355 bss_desc->ssid.ssid_len); 1356 1357 /* Check if the requested SSID is already joined */ 1358 if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len && 1359 !mwifiex_ssid_cmp(&bss_desc->ssid, 1360 &priv->curr_bss_params.bss_descriptor.ssid) && 1361 (priv->curr_bss_params.bss_descriptor.bss_mode == 1362 NL80211_IFTYPE_ADHOC)) { 1363 dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: new ad-hoc SSID" 1364 " is the same as current; not attempting to re-join\n"); 1365 return -1; 1366 } 1367 1368 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 1369 !bss_desc->disable_11n && !bss_desc->disable_11ac && 1370 priv->adapter->config_bands & BAND_AAC) 1371 mwifiex_set_11ac_ba_params(priv); 1372 else 1373 mwifiex_set_ba_params(priv); 1374 1375 dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", 1376 priv->curr_bss_params.bss_descriptor.channel); 1377 dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", 1378 priv->curr_bss_params.band); 1379 1380 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, 1381 HostCmd_ACT_GEN_SET, 0, bss_desc, true); 1382} 1383 1384/* 1385 * This function deauthenticates/disconnects from infra network by sending 1386 * deauthentication request. 1387 */ 1388static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) 1389{ 1390 u8 mac_address[ETH_ALEN]; 1391 int ret; 1392 1393 if (!mac || is_zero_ether_addr(mac)) 1394 memcpy(mac_address, 1395 priv->curr_bss_params.bss_descriptor.mac_address, 1396 ETH_ALEN); 1397 else 1398 memcpy(mac_address, mac, ETH_ALEN); 1399 1400 ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, 1401 HostCmd_ACT_GEN_SET, 0, mac_address, true); 1402 1403 return ret; 1404} 1405 1406/* 1407 * This function deauthenticates/disconnects from a BSS. 1408 * 1409 * In case of infra made, it sends deauthentication request, and 1410 * in case of ad-hoc mode, a stop network request is sent to the firmware. 1411 * In AP mode, a command to stop bss is sent to firmware. 1412 */ 1413int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) 1414{ 1415 int ret = 0; 1416 1417 if (!priv->media_connected) 1418 return 0; 1419 1420 switch (priv->bss_mode) { 1421 case NL80211_IFTYPE_STATION: 1422 case NL80211_IFTYPE_P2P_CLIENT: 1423 ret = mwifiex_deauthenticate_infra(priv, mac); 1424 if (ret) 1425 cfg80211_disconnected(priv->netdev, 0, NULL, 0, 1426 GFP_KERNEL); 1427 break; 1428 case NL80211_IFTYPE_ADHOC: 1429 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP, 1430 HostCmd_ACT_GEN_SET, 0, NULL, true); 1431 case NL80211_IFTYPE_AP: 1432 return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, 1433 HostCmd_ACT_GEN_SET, 0, NULL, true); 1434 default: 1435 break; 1436 } 1437 1438 return ret; 1439} 1440 1441/* This function deauthenticates/disconnects from all BSS. */ 1442void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter) 1443{ 1444 struct mwifiex_private *priv; 1445 int i; 1446 1447 for (i = 0; i < adapter->priv_num; i++) { 1448 priv = adapter->priv[i]; 1449 if (priv) 1450 mwifiex_deauthenticate(priv, NULL); 1451 } 1452} 1453EXPORT_SYMBOL_GPL(mwifiex_deauthenticate_all); 1454 1455/* 1456 * This function converts band to radio type used in channel TLV. 1457 */ 1458u8 1459mwifiex_band_to_radio_type(u8 band) 1460{ 1461 switch (band) { 1462 case BAND_A: 1463 case BAND_AN: 1464 case BAND_A | BAND_AN: 1465 case BAND_A | BAND_AN | BAND_AAC: 1466 return HostCmd_SCAN_RADIO_TYPE_A; 1467 case BAND_B: 1468 case BAND_G: 1469 case BAND_B | BAND_G: 1470 default: 1471 return HostCmd_SCAN_RADIO_TYPE_BG; 1472 } 1473} 1474