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