18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * NXP Wireless LAN device driver: association and ad-hoc start/join 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 2011-2020 NXP 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software file (the "File") is distributed by NXP 78c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License Version 2, June 1991 88c2ecf20Sopenharmony_ci * (the "License"). You may use, redistribute and/or modify this File in 98c2ecf20Sopenharmony_ci * accordance with the terms and conditions of the License, a copy of which 108c2ecf20Sopenharmony_ci * is available by writing to the Free Software Foundation, Inc., 118c2ecf20Sopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 128c2ecf20Sopenharmony_ci * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 158c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 168c2ecf20Sopenharmony_ci * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 178c2ecf20Sopenharmony_ci * this warranty disclaimer. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "decl.h" 218c2ecf20Sopenharmony_ci#include "ioctl.h" 228c2ecf20Sopenharmony_ci#include "util.h" 238c2ecf20Sopenharmony_ci#include "fw.h" 248c2ecf20Sopenharmony_ci#include "main.h" 258c2ecf20Sopenharmony_ci#include "wmm.h" 268c2ecf20Sopenharmony_ci#include "11n.h" 278c2ecf20Sopenharmony_ci#include "11ac.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * Append a generic IE as a pass through TLV to a TLV buffer. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * This function is called from the network join command preparation routine. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * If the IE buffer has been setup by the application, this routine appends 378c2ecf20Sopenharmony_ci * the buffer as a pass through TLV type to the request. 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_cistatic int 408c2ecf20Sopenharmony_cimwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci int ret_len = 0; 438c2ecf20Sopenharmony_ci struct mwifiex_ie_types_header ie_header; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* Null Checks */ 468c2ecf20Sopenharmony_ci if (!buffer) 478c2ecf20Sopenharmony_ci return 0; 488c2ecf20Sopenharmony_ci if (!(*buffer)) 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* 528c2ecf20Sopenharmony_ci * If there is a generic ie buffer setup, append it to the return 538c2ecf20Sopenharmony_ci * parameter buffer pointer. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci if (priv->gen_ie_buf_len) { 568c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 578c2ecf20Sopenharmony_ci "info: %s: append generic ie len %d to %p\n", 588c2ecf20Sopenharmony_ci __func__, priv->gen_ie_buf_len, *buffer); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* Wrap the generic IE buffer with a pass through TLV type */ 618c2ecf20Sopenharmony_ci ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); 628c2ecf20Sopenharmony_ci ie_header.len = cpu_to_le16(priv->gen_ie_buf_len); 638c2ecf20Sopenharmony_ci memcpy(*buffer, &ie_header, sizeof(ie_header)); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* Increment the return size and the return buffer pointer 668c2ecf20Sopenharmony_ci param */ 678c2ecf20Sopenharmony_ci *buffer += sizeof(ie_header); 688c2ecf20Sopenharmony_ci ret_len += sizeof(ie_header); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* Copy the generic IE buffer to the output buffer, advance 718c2ecf20Sopenharmony_ci pointer */ 728c2ecf20Sopenharmony_ci memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* Increment the return size and the return buffer pointer 758c2ecf20Sopenharmony_ci param */ 768c2ecf20Sopenharmony_ci *buffer += priv->gen_ie_buf_len; 778c2ecf20Sopenharmony_ci ret_len += priv->gen_ie_buf_len; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* Reset the generic IE buffer */ 808c2ecf20Sopenharmony_ci priv->gen_ie_buf_len = 0; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* return the length appended to the buffer */ 848c2ecf20Sopenharmony_ci return ret_len; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* 888c2ecf20Sopenharmony_ci * Append TSF tracking info from the scan table for the target AP. 898c2ecf20Sopenharmony_ci * 908c2ecf20Sopenharmony_ci * This function is called from the network join command preparation routine. 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * The TSF table TSF sent to the firmware contains two TSF values: 938c2ecf20Sopenharmony_ci * - The TSF of the target AP from its previous beacon/probe response 948c2ecf20Sopenharmony_ci * - The TSF timestamp of our local MAC at the time we observed the 958c2ecf20Sopenharmony_ci * beacon/probe response. 968c2ecf20Sopenharmony_ci * 978c2ecf20Sopenharmony_ci * The firmware uses the timestamp values to set an initial TSF value 988c2ecf20Sopenharmony_ci * in the MAC for the new association after a reassociation attempt. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_cistatic int 1018c2ecf20Sopenharmony_cimwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, 1028c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci struct mwifiex_ie_types_tsf_timestamp tsf_tlv; 1058c2ecf20Sopenharmony_ci __le64 tsf_val; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* Null Checks */ 1088c2ecf20Sopenharmony_ci if (buffer == NULL) 1098c2ecf20Sopenharmony_ci return 0; 1108c2ecf20Sopenharmony_ci if (*buffer == NULL) 1118c2ecf20Sopenharmony_ci return 0; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp)); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP); 1168c2ecf20Sopenharmony_ci tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val)); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); 1198c2ecf20Sopenharmony_ci *buffer += sizeof(tsf_tlv.header); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* TSF at the time when beacon/probe_response was received */ 1228c2ecf20Sopenharmony_ci tsf_val = cpu_to_le64(bss_desc->fw_tsf); 1238c2ecf20Sopenharmony_ci memcpy(*buffer, &tsf_val, sizeof(tsf_val)); 1248c2ecf20Sopenharmony_ci *buffer += sizeof(tsf_val); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci tsf_val = cpu_to_le64(bss_desc->timestamp); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 1298c2ecf20Sopenharmony_ci "info: %s: TSF offset calc: %016llx - %016llx\n", 1308c2ecf20Sopenharmony_ci __func__, bss_desc->timestamp, bss_desc->fw_tsf); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci memcpy(*buffer, &tsf_val, sizeof(tsf_val)); 1338c2ecf20Sopenharmony_ci *buffer += sizeof(tsf_val); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val)); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* 1398c2ecf20Sopenharmony_ci * This function finds out the common rates between rate1 and rate2. 1408c2ecf20Sopenharmony_ci * 1418c2ecf20Sopenharmony_ci * It will fill common rates in rate1 as output if found. 1428c2ecf20Sopenharmony_ci * 1438c2ecf20Sopenharmony_ci * NOTE: Setting the MSB of the basic rates needs to be taken 1448c2ecf20Sopenharmony_ci * care of, either before or after calling this function. 1458c2ecf20Sopenharmony_ci */ 1468c2ecf20Sopenharmony_cistatic int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, 1478c2ecf20Sopenharmony_ci u32 rate1_size, u8 *rate2, u32 rate2_size) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci int ret; 1508c2ecf20Sopenharmony_ci u8 *ptr = rate1, *tmp; 1518c2ecf20Sopenharmony_ci u32 i, j; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci tmp = kmemdup(rate1, rate1_size, GFP_KERNEL); 1548c2ecf20Sopenharmony_ci if (!tmp) { 1558c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, "failed to alloc tmp buf\n"); 1568c2ecf20Sopenharmony_ci return -ENOMEM; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci memset(rate1, 0, rate1_size); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci for (i = 0; i < rate2_size && rate2[i]; i++) { 1628c2ecf20Sopenharmony_ci for (j = 0; j < rate1_size && tmp[j]; j++) { 1638c2ecf20Sopenharmony_ci /* Check common rate, excluding the bit for 1648c2ecf20Sopenharmony_ci basic rate */ 1658c2ecf20Sopenharmony_ci if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) { 1668c2ecf20Sopenharmony_ci *rate1++ = tmp[j]; 1678c2ecf20Sopenharmony_ci break; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: Tx data rate set to %#x\n", 1738c2ecf20Sopenharmony_ci priv->data_rate); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (!priv->is_data_rate_auto) { 1768c2ecf20Sopenharmony_ci while (*ptr) { 1778c2ecf20Sopenharmony_ci if ((*ptr & 0x7f) == priv->data_rate) { 1788c2ecf20Sopenharmony_ci ret = 0; 1798c2ecf20Sopenharmony_ci goto done; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci ptr++; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 1848c2ecf20Sopenharmony_ci "previously set fixed data rate %#x\t" 1858c2ecf20Sopenharmony_ci "is not compatible with the network\n", 1868c2ecf20Sopenharmony_ci priv->data_rate); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci ret = -1; 1898c2ecf20Sopenharmony_ci goto done; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci ret = 0; 1938c2ecf20Sopenharmony_cidone: 1948c2ecf20Sopenharmony_ci kfree(tmp); 1958c2ecf20Sopenharmony_ci return ret; 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci/* 1998c2ecf20Sopenharmony_ci * This function creates the intersection of the rates supported by a 2008c2ecf20Sopenharmony_ci * target BSS and our adapter settings for use in an assoc/join command. 2018c2ecf20Sopenharmony_ci */ 2028c2ecf20Sopenharmony_cistatic int 2038c2ecf20Sopenharmony_cimwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, 2048c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc, 2058c2ecf20Sopenharmony_ci u8 *out_rates, u32 *out_rates_size) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci u8 card_rates[MWIFIEX_SUPPORTED_RATES]; 2088c2ecf20Sopenharmony_ci u32 card_rates_size; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* Copy AP supported rates */ 2118c2ecf20Sopenharmony_ci memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); 2128c2ecf20Sopenharmony_ci /* Get the STA supported rates */ 2138c2ecf20Sopenharmony_ci card_rates_size = mwifiex_get_active_data_rates(priv, card_rates); 2148c2ecf20Sopenharmony_ci /* Get the common rates between AP and STA supported rates */ 2158c2ecf20Sopenharmony_ci if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES, 2168c2ecf20Sopenharmony_ci card_rates, card_rates_size)) { 2178c2ecf20Sopenharmony_ci *out_rates_size = 0; 2188c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 2198c2ecf20Sopenharmony_ci "%s: cannot get common rates\n", 2208c2ecf20Sopenharmony_ci __func__); 2218c2ecf20Sopenharmony_ci return -1; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci *out_rates_size = 2258c2ecf20Sopenharmony_ci min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci return 0; 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci/* 2318c2ecf20Sopenharmony_ci * This function appends a WPS IE. It is called from the network join command 2328c2ecf20Sopenharmony_ci * preparation routine. 2338c2ecf20Sopenharmony_ci * 2348c2ecf20Sopenharmony_ci * If the IE buffer has been setup by the application, this routine appends 2358c2ecf20Sopenharmony_ci * the buffer as a WPS TLV type to the request. 2368c2ecf20Sopenharmony_ci */ 2378c2ecf20Sopenharmony_cistatic int 2388c2ecf20Sopenharmony_cimwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci int retLen = 0; 2418c2ecf20Sopenharmony_ci struct mwifiex_ie_types_header ie_header; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci if (!buffer || !*buffer) 2448c2ecf20Sopenharmony_ci return 0; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* 2478c2ecf20Sopenharmony_ci * If there is a wps ie buffer setup, append it to the return 2488c2ecf20Sopenharmony_ci * parameter buffer pointer. 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_ci if (priv->wps_ie_len) { 2518c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, 2528c2ecf20Sopenharmony_ci "cmd: append wps ie %d to %p\n", 2538c2ecf20Sopenharmony_ci priv->wps_ie_len, *buffer); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* Wrap the generic IE buffer with a pass through TLV type */ 2568c2ecf20Sopenharmony_ci ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); 2578c2ecf20Sopenharmony_ci ie_header.len = cpu_to_le16(priv->wps_ie_len); 2588c2ecf20Sopenharmony_ci memcpy(*buffer, &ie_header, sizeof(ie_header)); 2598c2ecf20Sopenharmony_ci *buffer += sizeof(ie_header); 2608c2ecf20Sopenharmony_ci retLen += sizeof(ie_header); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci memcpy(*buffer, priv->wps_ie, priv->wps_ie_len); 2638c2ecf20Sopenharmony_ci *buffer += priv->wps_ie_len; 2648c2ecf20Sopenharmony_ci retLen += priv->wps_ie_len; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci kfree(priv->wps_ie); 2698c2ecf20Sopenharmony_ci priv->wps_ie_len = 0; 2708c2ecf20Sopenharmony_ci return retLen; 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/* 2748c2ecf20Sopenharmony_ci * This function appends a WAPI IE. 2758c2ecf20Sopenharmony_ci * 2768c2ecf20Sopenharmony_ci * This function is called from the network join command preparation routine. 2778c2ecf20Sopenharmony_ci * 2788c2ecf20Sopenharmony_ci * If the IE buffer has been setup by the application, this routine appends 2798c2ecf20Sopenharmony_ci * the buffer as a WAPI TLV type to the request. 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_cistatic int 2828c2ecf20Sopenharmony_cimwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci int retLen = 0; 2858c2ecf20Sopenharmony_ci struct mwifiex_ie_types_header ie_header; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* Null Checks */ 2888c2ecf20Sopenharmony_ci if (buffer == NULL) 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci if (*buffer == NULL) 2918c2ecf20Sopenharmony_ci return 0; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* 2948c2ecf20Sopenharmony_ci * If there is a wapi ie buffer setup, append it to the return 2958c2ecf20Sopenharmony_ci * parameter buffer pointer. 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_ci if (priv->wapi_ie_len) { 2988c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, 2998c2ecf20Sopenharmony_ci "cmd: append wapi ie %d to %p\n", 3008c2ecf20Sopenharmony_ci priv->wapi_ie_len, *buffer); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci /* Wrap the generic IE buffer with a pass through TLV type */ 3038c2ecf20Sopenharmony_ci ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE); 3048c2ecf20Sopenharmony_ci ie_header.len = cpu_to_le16(priv->wapi_ie_len); 3058c2ecf20Sopenharmony_ci memcpy(*buffer, &ie_header, sizeof(ie_header)); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* Increment the return size and the return buffer pointer 3088c2ecf20Sopenharmony_ci param */ 3098c2ecf20Sopenharmony_ci *buffer += sizeof(ie_header); 3108c2ecf20Sopenharmony_ci retLen += sizeof(ie_header); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* Copy the wapi IE buffer to the output buffer, advance 3138c2ecf20Sopenharmony_ci pointer */ 3148c2ecf20Sopenharmony_ci memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* Increment the return size and the return buffer pointer 3178c2ecf20Sopenharmony_ci param */ 3188c2ecf20Sopenharmony_ci *buffer += priv->wapi_ie_len; 3198c2ecf20Sopenharmony_ci retLen += priv->wapi_ie_len; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci /* return the length appended to the buffer */ 3238c2ecf20Sopenharmony_ci return retLen; 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci/* 3278c2ecf20Sopenharmony_ci * This function appends rsn ie tlv for wpa/wpa2 security modes. 3288c2ecf20Sopenharmony_ci * It is called from the network join command preparation routine. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_cistatic int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv, 3318c2ecf20Sopenharmony_ci u8 **buffer) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv; 3348c2ecf20Sopenharmony_ci int rsn_ie_len; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (!buffer || !(*buffer)) 3378c2ecf20Sopenharmony_ci return 0; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer); 3408c2ecf20Sopenharmony_ci rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]); 3418c2ecf20Sopenharmony_ci rsn_ie_tlv->header.type = cpu_to_le16( 3428c2ecf20Sopenharmony_ci le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF); 3438c2ecf20Sopenharmony_ci rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]); 3448c2ecf20Sopenharmony_ci rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len) 3458c2ecf20Sopenharmony_ci & 0x00FF); 3468c2ecf20Sopenharmony_ci if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2)) 3478c2ecf20Sopenharmony_ci memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2], 3488c2ecf20Sopenharmony_ci le16_to_cpu(rsn_ie_tlv->header.len)); 3498c2ecf20Sopenharmony_ci else 3508c2ecf20Sopenharmony_ci return -1; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci rsn_ie_len = sizeof(rsn_ie_tlv->header) + 3538c2ecf20Sopenharmony_ci le16_to_cpu(rsn_ie_tlv->header.len); 3548c2ecf20Sopenharmony_ci *buffer += rsn_ie_len; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return rsn_ie_len; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci/* 3608c2ecf20Sopenharmony_ci * This function prepares command for association. 3618c2ecf20Sopenharmony_ci * 3628c2ecf20Sopenharmony_ci * This sets the following parameters - 3638c2ecf20Sopenharmony_ci * - Peer MAC address 3648c2ecf20Sopenharmony_ci * - Listen interval 3658c2ecf20Sopenharmony_ci * - Beacon interval 3668c2ecf20Sopenharmony_ci * - Capability information 3678c2ecf20Sopenharmony_ci * 3688c2ecf20Sopenharmony_ci * ...and the following TLVs, as required - 3698c2ecf20Sopenharmony_ci * - SSID TLV 3708c2ecf20Sopenharmony_ci * - PHY TLV 3718c2ecf20Sopenharmony_ci * - SS TLV 3728c2ecf20Sopenharmony_ci * - Rates TLV 3738c2ecf20Sopenharmony_ci * - Authentication TLV 3748c2ecf20Sopenharmony_ci * - Channel TLV 3758c2ecf20Sopenharmony_ci * - WPA/WPA2 IE 3768c2ecf20Sopenharmony_ci * - 11n TLV 3778c2ecf20Sopenharmony_ci * - Vendor specific TLV 3788c2ecf20Sopenharmony_ci * - WMM TLV 3798c2ecf20Sopenharmony_ci * - WAPI IE 3808c2ecf20Sopenharmony_ci * - Generic IE 3818c2ecf20Sopenharmony_ci * - TSF TLV 3828c2ecf20Sopenharmony_ci * 3838c2ecf20Sopenharmony_ci * Preparation also includes - 3848c2ecf20Sopenharmony_ci * - Setting command ID and proper size 3858c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 3868c2ecf20Sopenharmony_ci */ 3878c2ecf20Sopenharmony_ciint mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, 3888c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 3898c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate; 3928c2ecf20Sopenharmony_ci struct mwifiex_ie_types_ssid_param_set *ssid_tlv; 3938c2ecf20Sopenharmony_ci struct mwifiex_ie_types_phy_param_set *phy_tlv; 3948c2ecf20Sopenharmony_ci struct mwifiex_ie_types_ss_param_set *ss_tlv; 3958c2ecf20Sopenharmony_ci struct mwifiex_ie_types_rates_param_set *rates_tlv; 3968c2ecf20Sopenharmony_ci struct mwifiex_ie_types_auth_type *auth_tlv; 3978c2ecf20Sopenharmony_ci struct mwifiex_ie_types_chan_list_param_set *chan_tlv; 3988c2ecf20Sopenharmony_ci u8 rates[MWIFIEX_SUPPORTED_RATES]; 3998c2ecf20Sopenharmony_ci u32 rates_size; 4008c2ecf20Sopenharmony_ci u16 tmp_cap; 4018c2ecf20Sopenharmony_ci u8 *pos; 4028c2ecf20Sopenharmony_ci int rsn_ie_len = 0; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci pos = (u8 *) assoc; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci /* Save so we know which BSS Desc to use in the response handler */ 4098c2ecf20Sopenharmony_ci priv->attempted_bss_desc = bss_desc; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci memcpy(assoc->peer_sta_addr, 4128c2ecf20Sopenharmony_ci bss_desc->mac_address, sizeof(assoc->peer_sta_addr)); 4138c2ecf20Sopenharmony_ci pos += sizeof(assoc->peer_sta_addr); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci /* Set the listen interval */ 4168c2ecf20Sopenharmony_ci assoc->listen_interval = cpu_to_le16(priv->listen_interval); 4178c2ecf20Sopenharmony_ci /* Set the beacon period */ 4188c2ecf20Sopenharmony_ci assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci pos += sizeof(assoc->cap_info_bitmap); 4218c2ecf20Sopenharmony_ci pos += sizeof(assoc->listen_interval); 4228c2ecf20Sopenharmony_ci pos += sizeof(assoc->beacon_period); 4238c2ecf20Sopenharmony_ci pos += sizeof(assoc->dtim_period); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos; 4268c2ecf20Sopenharmony_ci ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID); 4278c2ecf20Sopenharmony_ci ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len); 4288c2ecf20Sopenharmony_ci memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid, 4298c2ecf20Sopenharmony_ci le16_to_cpu(ssid_tlv->header.len)); 4308c2ecf20Sopenharmony_ci pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos; 4338c2ecf20Sopenharmony_ci phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS); 4348c2ecf20Sopenharmony_ci phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set)); 4358c2ecf20Sopenharmony_ci memcpy(&phy_tlv->fh_ds.ds_param_set, 4368c2ecf20Sopenharmony_ci &bss_desc->phy_param_set.ds_param_set.current_chan, 4378c2ecf20Sopenharmony_ci sizeof(phy_tlv->fh_ds.ds_param_set)); 4388c2ecf20Sopenharmony_ci pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos; 4418c2ecf20Sopenharmony_ci ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS); 4428c2ecf20Sopenharmony_ci ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set)); 4438c2ecf20Sopenharmony_ci pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci /* Get the common rates supported between the driver and the BSS Desc */ 4468c2ecf20Sopenharmony_ci if (mwifiex_setup_rates_from_bssdesc 4478c2ecf20Sopenharmony_ci (priv, bss_desc, rates, &rates_size)) 4488c2ecf20Sopenharmony_ci return -1; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci /* Save the data rates into Current BSS state structure */ 4518c2ecf20Sopenharmony_ci priv->curr_bss_params.num_of_rates = rates_size; 4528c2ecf20Sopenharmony_ci memcpy(&priv->curr_bss_params.data_rates, rates, rates_size); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci /* Setup the Rates TLV in the association command */ 4558c2ecf20Sopenharmony_ci rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos; 4568c2ecf20Sopenharmony_ci rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); 4578c2ecf20Sopenharmony_ci rates_tlv->header.len = cpu_to_le16((u16) rates_size); 4588c2ecf20Sopenharmony_ci memcpy(rates_tlv->rates, rates, rates_size); 4598c2ecf20Sopenharmony_ci pos += sizeof(rates_tlv->header) + rates_size; 4608c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_CMD: rates size = %d\n", 4618c2ecf20Sopenharmony_ci rates_size); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci /* Add the Authentication type to be used for Auth frames */ 4648c2ecf20Sopenharmony_ci auth_tlv = (struct mwifiex_ie_types_auth_type *) pos; 4658c2ecf20Sopenharmony_ci auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); 4668c2ecf20Sopenharmony_ci auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type)); 4678c2ecf20Sopenharmony_ci if (priv->sec_info.wep_enabled) 4688c2ecf20Sopenharmony_ci auth_tlv->auth_type = cpu_to_le16( 4698c2ecf20Sopenharmony_ci (u16) priv->sec_info.authentication_mode); 4708c2ecf20Sopenharmony_ci else 4718c2ecf20Sopenharmony_ci auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM); 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (IS_SUPPORT_MULTI_BANDS(priv->adapter) && 4768c2ecf20Sopenharmony_ci !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && 4778c2ecf20Sopenharmony_ci (!bss_desc->disable_11n) && 4788c2ecf20Sopenharmony_ci (priv->adapter->config_bands & BAND_GN || 4798c2ecf20Sopenharmony_ci priv->adapter->config_bands & BAND_AN) && 4808c2ecf20Sopenharmony_ci (bss_desc->bcn_ht_cap) 4818c2ecf20Sopenharmony_ci ) 4828c2ecf20Sopenharmony_ci ) { 4838c2ecf20Sopenharmony_ci /* Append a channel TLV for the channel the attempted AP was 4848c2ecf20Sopenharmony_ci found on */ 4858c2ecf20Sopenharmony_ci chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; 4868c2ecf20Sopenharmony_ci chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 4878c2ecf20Sopenharmony_ci chan_tlv->header.len = 4888c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci memset(chan_tlv->chan_scan_param, 0x00, 4918c2ecf20Sopenharmony_ci sizeof(struct mwifiex_chan_scan_param_set)); 4928c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].chan_number = 4938c2ecf20Sopenharmony_ci (bss_desc->phy_param_set.ds_param_set.current_chan); 4948c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Chan = %d\n", 4958c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].chan_number); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].radio_type = 4988c2ecf20Sopenharmony_ci mwifiex_band_to_radio_type((u8) bss_desc->bss_band); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Band = %d\n", 5018c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].radio_type); 5028c2ecf20Sopenharmony_ci pos += sizeof(chan_tlv->header) + 5038c2ecf20Sopenharmony_ci sizeof(struct mwifiex_chan_scan_param_set); 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci if (!priv->wps.session_enable) { 5078c2ecf20Sopenharmony_ci if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) 5088c2ecf20Sopenharmony_ci rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci if (rsn_ie_len == -1) 5118c2ecf20Sopenharmony_ci return -1; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && 5158c2ecf20Sopenharmony_ci (!bss_desc->disable_11n) && 5168c2ecf20Sopenharmony_ci (priv->adapter->config_bands & BAND_GN || 5178c2ecf20Sopenharmony_ci priv->adapter->config_bands & BAND_AN)) 5188c2ecf20Sopenharmony_ci mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 5218c2ecf20Sopenharmony_ci !bss_desc->disable_11n && !bss_desc->disable_11ac && 5228c2ecf20Sopenharmony_ci priv->adapter->config_bands & BAND_AAC) 5238c2ecf20Sopenharmony_ci mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos); 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci /* Append vendor specific IE TLV */ 5268c2ecf20Sopenharmony_ci mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie, 5298c2ecf20Sopenharmony_ci bss_desc->bcn_ht_cap); 5308c2ecf20Sopenharmony_ci if (priv->sec_info.wapi_enabled && priv->wapi_ie_len) 5318c2ecf20Sopenharmony_ci mwifiex_cmd_append_wapi_ie(priv, &pos); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci if (priv->wps.session_enable && priv->wps_ie_len) 5348c2ecf20Sopenharmony_ci mwifiex_cmd_append_wps_ie(priv, &pos); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci mwifiex_cmd_append_generic_ie(priv, &pos); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci mwifiex_11h_process_join(priv, &pos, bss_desc); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /* Set the Capability info at last */ 5458c2ecf20Sopenharmony_ci tmp_cap = bss_desc->cap_info_bitmap; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci if (priv->adapter->config_bands == BAND_B) 5488c2ecf20Sopenharmony_ci tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci tmp_cap &= CAPINFO_MASK; 5518c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 5528c2ecf20Sopenharmony_ci "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", 5538c2ecf20Sopenharmony_ci tmp_cap, CAPINFO_MASK); 5548c2ecf20Sopenharmony_ci assoc->cap_info_bitmap = cpu_to_le16(tmp_cap); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci return 0; 5578c2ecf20Sopenharmony_ci} 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic const char *assoc_failure_reason_to_str(u16 cap_info) 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci switch (cap_info) { 5628c2ecf20Sopenharmony_ci case CONNECT_ERR_AUTH_ERR_STA_FAILURE: 5638c2ecf20Sopenharmony_ci return "CONNECT_ERR_AUTH_ERR_STA_FAILURE"; 5648c2ecf20Sopenharmony_ci case CONNECT_ERR_AUTH_MSG_UNHANDLED: 5658c2ecf20Sopenharmony_ci return "CONNECT_ERR_AUTH_MSG_UNHANDLED"; 5668c2ecf20Sopenharmony_ci case CONNECT_ERR_ASSOC_ERR_TIMEOUT: 5678c2ecf20Sopenharmony_ci return "CONNECT_ERR_ASSOC_ERR_TIMEOUT"; 5688c2ecf20Sopenharmony_ci case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED: 5698c2ecf20Sopenharmony_ci return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED"; 5708c2ecf20Sopenharmony_ci case CONNECT_ERR_STA_FAILURE: 5718c2ecf20Sopenharmony_ci return "CONNECT_ERR_STA_FAILURE"; 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci return "Unknown connect failure"; 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci/* 5778c2ecf20Sopenharmony_ci * Association firmware command response handler 5788c2ecf20Sopenharmony_ci * 5798c2ecf20Sopenharmony_ci * The response buffer for the association command has the following 5808c2ecf20Sopenharmony_ci * memory layout. 5818c2ecf20Sopenharmony_ci * 5828c2ecf20Sopenharmony_ci * For cases where an association response was not received (indicated 5838c2ecf20Sopenharmony_ci * by the CapInfo and AId field): 5848c2ecf20Sopenharmony_ci * 5858c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 5868c2ecf20Sopenharmony_ci * | Header(4 * sizeof(t_u16)): Standard command response hdr | 5878c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 5888c2ecf20Sopenharmony_ci * | cap_info/Error Return(t_u16): | 5898c2ecf20Sopenharmony_ci * | 0xFFFF(-1): Internal error | 5908c2ecf20Sopenharmony_ci * | 0xFFFE(-2): Authentication unhandled message | 5918c2ecf20Sopenharmony_ci * | 0xFFFD(-3): Authentication refused | 5928c2ecf20Sopenharmony_ci * | 0xFFFC(-4): Timeout waiting for AP response | 5938c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 5948c2ecf20Sopenharmony_ci * | status_code(t_u16): | 5958c2ecf20Sopenharmony_ci * | If cap_info is -1: | 5968c2ecf20Sopenharmony_ci * | An internal firmware failure prevented the | 5978c2ecf20Sopenharmony_ci * | command from being processed. The status_code | 5988c2ecf20Sopenharmony_ci * | will be set to 1. | 5998c2ecf20Sopenharmony_ci * | | 6008c2ecf20Sopenharmony_ci * | If cap_info is -2: | 6018c2ecf20Sopenharmony_ci * | An authentication frame was received but was | 6028c2ecf20Sopenharmony_ci * | not handled by the firmware. IEEE Status | 6038c2ecf20Sopenharmony_ci * | code for the failure is returned. | 6048c2ecf20Sopenharmony_ci * | | 6058c2ecf20Sopenharmony_ci * | If cap_info is -3: | 6068c2ecf20Sopenharmony_ci * | An authentication frame was received and the | 6078c2ecf20Sopenharmony_ci * | status_code is the IEEE Status reported in the | 6088c2ecf20Sopenharmony_ci * | response. | 6098c2ecf20Sopenharmony_ci * | | 6108c2ecf20Sopenharmony_ci * | If cap_info is -4: | 6118c2ecf20Sopenharmony_ci * | (1) Association response timeout | 6128c2ecf20Sopenharmony_ci * | (2) Authentication response timeout | 6138c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 6148c2ecf20Sopenharmony_ci * | a_id(t_u16): 0xFFFF | 6158c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 6168c2ecf20Sopenharmony_ci * 6178c2ecf20Sopenharmony_ci * 6188c2ecf20Sopenharmony_ci * For cases where an association response was received, the IEEE 6198c2ecf20Sopenharmony_ci * standard association response frame is returned: 6208c2ecf20Sopenharmony_ci * 6218c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 6228c2ecf20Sopenharmony_ci * | Header(4 * sizeof(t_u16)): Standard command response hdr | 6238c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 6248c2ecf20Sopenharmony_ci * | cap_info(t_u16): IEEE Capability | 6258c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 6268c2ecf20Sopenharmony_ci * | status_code(t_u16): IEEE Status Code | 6278c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 6288c2ecf20Sopenharmony_ci * | a_id(t_u16): IEEE Association ID | 6298c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 6308c2ecf20Sopenharmony_ci * | IEEE IEs(variable): Any received IEs comprising the | 6318c2ecf20Sopenharmony_ci * | remaining portion of a received | 6328c2ecf20Sopenharmony_ci * | association response frame. | 6338c2ecf20Sopenharmony_ci * .------------------------------------------------------------. 6348c2ecf20Sopenharmony_ci * 6358c2ecf20Sopenharmony_ci * For simplistic handling, the status_code field can be used to determine 6368c2ecf20Sopenharmony_ci * an association success (0) or failure (non-zero). 6378c2ecf20Sopenharmony_ci */ 6388c2ecf20Sopenharmony_ciint mwifiex_ret_802_11_associate(struct mwifiex_private *priv, 6398c2ecf20Sopenharmony_ci struct host_cmd_ds_command *resp) 6408c2ecf20Sopenharmony_ci{ 6418c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 6428c2ecf20Sopenharmony_ci int ret = 0; 6438c2ecf20Sopenharmony_ci struct ieee_types_assoc_rsp *assoc_rsp; 6448c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc; 6458c2ecf20Sopenharmony_ci bool enable_data = true; 6468c2ecf20Sopenharmony_ci u16 cap_info, status_code, aid; 6478c2ecf20Sopenharmony_ci const u8 *ie_ptr; 6488c2ecf20Sopenharmony_ci struct ieee80211_ht_operation *assoc_resp_ht_oper; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci if (!priv->attempted_bss_desc) { 6518c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 6528c2ecf20Sopenharmony_ci "ASSOC_RESP: failed, association terminated by host\n"); 6538c2ecf20Sopenharmony_ci goto done; 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap); 6598c2ecf20Sopenharmony_ci status_code = le16_to_cpu(assoc_rsp->status_code); 6608c2ecf20Sopenharmony_ci aid = le16_to_cpu(assoc_rsp->a_id); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) 6638c2ecf20Sopenharmony_ci dev_err(priv->adapter->dev, 6648c2ecf20Sopenharmony_ci "invalid AID value 0x%x; bits 15:14 not set\n", 6658c2ecf20Sopenharmony_ci aid); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci aid &= ~(BIT(15) | BIT(14)); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, 6708c2ecf20Sopenharmony_ci sizeof(priv->assoc_rsp_buf)); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci assoc_rsp->a_id = cpu_to_le16(aid); 6738c2ecf20Sopenharmony_ci memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci if (status_code) { 6768c2ecf20Sopenharmony_ci priv->adapter->dbg.num_cmd_assoc_failure++; 6778c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 6788c2ecf20Sopenharmony_ci "ASSOC_RESP: failed,\t" 6798c2ecf20Sopenharmony_ci "status code=%d err=%#x a_id=%#x\n", 6808c2ecf20Sopenharmony_ci status_code, cap_info, 6818c2ecf20Sopenharmony_ci le16_to_cpu(assoc_rsp->a_id)); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n", 6848c2ecf20Sopenharmony_ci assoc_failure_reason_to_str(cap_info)); 6858c2ecf20Sopenharmony_ci if (cap_info == CONNECT_ERR_ASSOC_ERR_TIMEOUT) { 6868c2ecf20Sopenharmony_ci if (status_code == MWIFIEX_ASSOC_CMD_FAILURE_AUTH) { 6878c2ecf20Sopenharmony_ci ret = WLAN_STATUS_AUTH_TIMEOUT; 6888c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 6898c2ecf20Sopenharmony_ci "ASSOC_RESP: AUTH timeout\n"); 6908c2ecf20Sopenharmony_ci } else { 6918c2ecf20Sopenharmony_ci ret = WLAN_STATUS_UNSPECIFIED_FAILURE; 6928c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 6938c2ecf20Sopenharmony_ci "ASSOC_RESP: UNSPECIFIED failure\n"); 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci } else { 6968c2ecf20Sopenharmony_ci ret = status_code; 6978c2ecf20Sopenharmony_ci } 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci goto done; 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci /* Send a Media Connected event, according to the Spec */ 7038c2ecf20Sopenharmony_ci priv->media_connected = true; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci priv->adapter->ps_state = PS_STATE_AWAKE; 7068c2ecf20Sopenharmony_ci priv->adapter->pps_uapsd_mode = false; 7078c2ecf20Sopenharmony_ci priv->adapter->tx_lock_flag = false; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci /* Set the attempted BSSID Index to current */ 7108c2ecf20Sopenharmony_ci bss_desc = priv->attempted_bss_desc; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: %s\n", 7138c2ecf20Sopenharmony_ci bss_desc->ssid.ssid); 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci /* Make a copy of current BSSID descriptor */ 7168c2ecf20Sopenharmony_ci memcpy(&priv->curr_bss_params.bss_descriptor, 7178c2ecf20Sopenharmony_ci bss_desc, sizeof(struct mwifiex_bssdescriptor)); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci /* Update curr_bss_params */ 7208c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.channel 7218c2ecf20Sopenharmony_ci = bss_desc->phy_param_set.ds_param_set.current_chan; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci priv->curr_bss_params.band = (u8) bss_desc->bss_band; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) 7268c2ecf20Sopenharmony_ci priv->curr_bss_params.wmm_enabled = true; 7278c2ecf20Sopenharmony_ci else 7288c2ecf20Sopenharmony_ci priv->curr_bss_params.wmm_enabled = false; 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci if ((priv->wmm_required || bss_desc->bcn_ht_cap) && 7318c2ecf20Sopenharmony_ci priv->curr_bss_params.wmm_enabled) 7328c2ecf20Sopenharmony_ci priv->wmm_enabled = true; 7338c2ecf20Sopenharmony_ci else 7348c2ecf20Sopenharmony_ci priv->wmm_enabled = false; 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci priv->curr_bss_params.wmm_uapsd_enabled = false; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci if (priv->wmm_enabled) 7398c2ecf20Sopenharmony_ci priv->curr_bss_params.wmm_uapsd_enabled 7408c2ecf20Sopenharmony_ci = ((bss_desc->wmm_ie.qos_info_bitmap & 7418c2ecf20Sopenharmony_ci IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci /* Store the bandwidth information from assoc response */ 7448c2ecf20Sopenharmony_ci ie_ptr = cfg80211_find_ie(WLAN_EID_HT_OPERATION, assoc_rsp->ie_buffer, 7458c2ecf20Sopenharmony_ci priv->assoc_rsp_size 7468c2ecf20Sopenharmony_ci - sizeof(struct ieee_types_assoc_rsp)); 7478c2ecf20Sopenharmony_ci if (ie_ptr) { 7488c2ecf20Sopenharmony_ci assoc_resp_ht_oper = (struct ieee80211_ht_operation *)(ie_ptr 7498c2ecf20Sopenharmony_ci + sizeof(struct ieee_types_header)); 7508c2ecf20Sopenharmony_ci priv->assoc_resp_ht_param = assoc_resp_ht_oper->ht_param; 7518c2ecf20Sopenharmony_ci priv->ht_param_present = true; 7528c2ecf20Sopenharmony_ci } else { 7538c2ecf20Sopenharmony_ci priv->ht_param_present = false; 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 7578c2ecf20Sopenharmony_ci "info: ASSOC_RESP: curr_pkt_filter is %#x\n", 7588c2ecf20Sopenharmony_ci priv->curr_pkt_filter); 7598c2ecf20Sopenharmony_ci if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) 7608c2ecf20Sopenharmony_ci priv->wpa_is_gtk_set = false; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci if (priv->wmm_enabled) { 7638c2ecf20Sopenharmony_ci /* Don't re-enable carrier until we get the WMM_GET_STATUS 7648c2ecf20Sopenharmony_ci event */ 7658c2ecf20Sopenharmony_ci enable_data = false; 7668c2ecf20Sopenharmony_ci } else { 7678c2ecf20Sopenharmony_ci /* Since WMM is not enabled, setup the queues with the 7688c2ecf20Sopenharmony_ci defaults */ 7698c2ecf20Sopenharmony_ci mwifiex_wmm_setup_queue_priorities(priv, NULL); 7708c2ecf20Sopenharmony_ci mwifiex_wmm_setup_ac_downgrade(priv); 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if (enable_data) 7748c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 7758c2ecf20Sopenharmony_ci "info: post association, re-enabling data flow\n"); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci /* Reset SNR/NF/RSSI values */ 7788c2ecf20Sopenharmony_ci priv->data_rssi_last = 0; 7798c2ecf20Sopenharmony_ci priv->data_nf_last = 0; 7808c2ecf20Sopenharmony_ci priv->data_rssi_avg = 0; 7818c2ecf20Sopenharmony_ci priv->data_nf_avg = 0; 7828c2ecf20Sopenharmony_ci priv->bcn_rssi_last = 0; 7838c2ecf20Sopenharmony_ci priv->bcn_nf_last = 0; 7848c2ecf20Sopenharmony_ci priv->bcn_rssi_avg = 0; 7858c2ecf20Sopenharmony_ci priv->bcn_nf_avg = 0; 7868c2ecf20Sopenharmony_ci priv->rxpd_rate = 0; 7878c2ecf20Sopenharmony_ci priv->rxpd_htinfo = 0; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci mwifiex_save_curr_bcn(priv); 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci priv->adapter->dbg.num_cmd_assoc_success++; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: associated\n"); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* Add the ra_list here for infra mode as there will be only 1 ra 7968c2ecf20Sopenharmony_ci always */ 7978c2ecf20Sopenharmony_ci mwifiex_ralist_add(priv, 7988c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.mac_address); 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci if (!netif_carrier_ok(priv->netdev)) 8018c2ecf20Sopenharmony_ci netif_carrier_on(priv->netdev); 8028c2ecf20Sopenharmony_ci mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) 8058c2ecf20Sopenharmony_ci priv->scan_block = true; 8068c2ecf20Sopenharmony_ci else 8078c2ecf20Sopenharmony_ci priv->port_open = true; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_cidone: 8108c2ecf20Sopenharmony_ci /* Need to indicate IOCTL complete */ 8118c2ecf20Sopenharmony_ci if (adapter->curr_cmd->wait_q_enabled) { 8128c2ecf20Sopenharmony_ci if (ret) 8138c2ecf20Sopenharmony_ci adapter->cmd_wait_q.status = -1; 8148c2ecf20Sopenharmony_ci else 8158c2ecf20Sopenharmony_ci adapter->cmd_wait_q.status = 0; 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci return ret; 8198c2ecf20Sopenharmony_ci} 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci/* 8228c2ecf20Sopenharmony_ci * This function prepares command for ad-hoc start. 8238c2ecf20Sopenharmony_ci * 8248c2ecf20Sopenharmony_ci * Driver will fill up SSID, BSS mode, IBSS parameters, physical 8258c2ecf20Sopenharmony_ci * parameters, probe delay, and capability information. Firmware 8268c2ecf20Sopenharmony_ci * will fill up beacon period, basic rates and operational rates. 8278c2ecf20Sopenharmony_ci * 8288c2ecf20Sopenharmony_ci * In addition, the following TLVs are added - 8298c2ecf20Sopenharmony_ci * - Channel TLV 8308c2ecf20Sopenharmony_ci * - Vendor specific IE 8318c2ecf20Sopenharmony_ci * - WPA/WPA2 IE 8328c2ecf20Sopenharmony_ci * - HT Capabilities IE 8338c2ecf20Sopenharmony_ci * - HT Information IE 8348c2ecf20Sopenharmony_ci * 8358c2ecf20Sopenharmony_ci * Preparation also includes - 8368c2ecf20Sopenharmony_ci * - Setting command ID and proper size 8378c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 8388c2ecf20Sopenharmony_ci */ 8398c2ecf20Sopenharmony_ciint 8408c2ecf20Sopenharmony_cimwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, 8418c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 8428c2ecf20Sopenharmony_ci struct cfg80211_ssid *req_ssid) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci int rsn_ie_len = 0; 8458c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 8468c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start = 8478c2ecf20Sopenharmony_ci &cmd->params.adhoc_start; 8488c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc; 8498c2ecf20Sopenharmony_ci u32 cmd_append_size = 0; 8508c2ecf20Sopenharmony_ci u32 i; 8518c2ecf20Sopenharmony_ci u16 tmp_cap; 8528c2ecf20Sopenharmony_ci struct mwifiex_ie_types_chan_list_param_set *chan_tlv; 8538c2ecf20Sopenharmony_ci u8 radio_type; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci struct mwifiex_ie_types_htcap *ht_cap; 8568c2ecf20Sopenharmony_ci struct mwifiex_ie_types_htinfo *ht_info; 8578c2ecf20Sopenharmony_ci u8 *pos = (u8 *) adhoc_start + 8588c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_802_11_ad_hoc_start); 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci if (!adapter) 8618c2ecf20Sopenharmony_ci return -1; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci bss_desc = &priv->curr_bss_params.bss_descriptor; 8668c2ecf20Sopenharmony_ci priv->attempted_bss_desc = bss_desc; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci /* 8698c2ecf20Sopenharmony_ci * Fill in the parameters for 2 data structures: 8708c2ecf20Sopenharmony_ci * 1. struct host_cmd_ds_802_11_ad_hoc_start command 8718c2ecf20Sopenharmony_ci * 2. bss_desc 8728c2ecf20Sopenharmony_ci * Driver will fill up SSID, bss_mode,IBSS param, Physical Param, 8738c2ecf20Sopenharmony_ci * probe delay, and Cap info. 8748c2ecf20Sopenharmony_ci * Firmware will fill up beacon period, Basic rates 8758c2ecf20Sopenharmony_ci * and operational rates. 8768c2ecf20Sopenharmony_ci */ 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci if (req_ssid->ssid_len > IEEE80211_MAX_SSID_LEN) 8818c2ecf20Sopenharmony_ci req_ssid->ssid_len = IEEE80211_MAX_SSID_LEN; 8828c2ecf20Sopenharmony_ci memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len); 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: SSID = %s\n", 8858c2ecf20Sopenharmony_ci adhoc_start->ssid); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN); 8888c2ecf20Sopenharmony_ci memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci bss_desc->ssid.ssid_len = req_ssid->ssid_len; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci /* Set the BSS mode */ 8938c2ecf20Sopenharmony_ci adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS; 8948c2ecf20Sopenharmony_ci bss_desc->bss_mode = NL80211_IFTYPE_ADHOC; 8958c2ecf20Sopenharmony_ci adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period); 8968c2ecf20Sopenharmony_ci bss_desc->beacon_period = priv->beacon_period; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci /* Set Physical param set */ 8998c2ecf20Sopenharmony_ci/* Parameter IE Id */ 9008c2ecf20Sopenharmony_ci#define DS_PARA_IE_ID 3 9018c2ecf20Sopenharmony_ci/* Parameter IE length */ 9028c2ecf20Sopenharmony_ci#define DS_PARA_IE_LEN 1 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID; 9058c2ecf20Sopenharmony_ci adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci if (!mwifiex_get_cfp(priv, adapter->adhoc_start_band, 9088c2ecf20Sopenharmony_ci (u16) priv->adhoc_channel, 0)) { 9098c2ecf20Sopenharmony_ci struct mwifiex_chan_freq_power *cfp; 9108c2ecf20Sopenharmony_ci cfp = mwifiex_get_cfp(priv, adapter->adhoc_start_band, 9118c2ecf20Sopenharmony_ci FIRST_VALID_CHANNEL, 0); 9128c2ecf20Sopenharmony_ci if (cfp) 9138c2ecf20Sopenharmony_ci priv->adhoc_channel = (u8) cfp->channel; 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci if (!priv->adhoc_channel) { 9178c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 9188c2ecf20Sopenharmony_ci "ADHOC_S_CMD: adhoc_channel cannot be 0\n"); 9198c2ecf20Sopenharmony_ci return -1; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 9238c2ecf20Sopenharmony_ci "info: ADHOC_S_CMD: creating ADHOC on channel %d\n", 9248c2ecf20Sopenharmony_ci priv->adhoc_channel); 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel; 9278c2ecf20Sopenharmony_ci priv->curr_bss_params.band = adapter->adhoc_start_band; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci bss_desc->channel = priv->adhoc_channel; 9308c2ecf20Sopenharmony_ci adhoc_start->phy_param_set.ds_param_set.current_chan = 9318c2ecf20Sopenharmony_ci priv->adhoc_channel; 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set, 9348c2ecf20Sopenharmony_ci sizeof(union ieee_types_phy_param_set)); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci /* Set IBSS param set */ 9378c2ecf20Sopenharmony_ci/* IBSS parameter IE Id */ 9388c2ecf20Sopenharmony_ci#define IBSS_PARA_IE_ID 6 9398c2ecf20Sopenharmony_ci/* IBSS parameter IE length */ 9408c2ecf20Sopenharmony_ci#define IBSS_PARA_IE_LEN 2 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID; 9438c2ecf20Sopenharmony_ci adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN; 9448c2ecf20Sopenharmony_ci adhoc_start->ss_param_set.ibss_param_set.atim_window 9458c2ecf20Sopenharmony_ci = cpu_to_le16(priv->atim_window); 9468c2ecf20Sopenharmony_ci memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set, 9478c2ecf20Sopenharmony_ci sizeof(union ieee_types_ss_param_set)); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci /* Set Capability info */ 9508c2ecf20Sopenharmony_ci bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; 9518c2ecf20Sopenharmony_ci tmp_cap = WLAN_CAPABILITY_IBSS; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* Set up privacy in bss_desc */ 9548c2ecf20Sopenharmony_ci if (priv->sec_info.encryption_mode) { 9558c2ecf20Sopenharmony_ci /* Ad-Hoc capability privacy on */ 9568c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 9578c2ecf20Sopenharmony_ci "info: ADHOC_S_CMD: wep_status set privacy to WEP\n"); 9588c2ecf20Sopenharmony_ci bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; 9598c2ecf20Sopenharmony_ci tmp_cap |= WLAN_CAPABILITY_PRIVACY; 9608c2ecf20Sopenharmony_ci } else { 9618c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 9628c2ecf20Sopenharmony_ci "info: ADHOC_S_CMD: wep_status NOT set,\t" 9638c2ecf20Sopenharmony_ci "setting privacy to ACCEPT ALL\n"); 9648c2ecf20Sopenharmony_ci bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci memset(adhoc_start->data_rate, 0, sizeof(adhoc_start->data_rate)); 9688c2ecf20Sopenharmony_ci mwifiex_get_active_data_rates(priv, adhoc_start->data_rate); 9698c2ecf20Sopenharmony_ci if ((adapter->adhoc_start_band & BAND_G) && 9708c2ecf20Sopenharmony_ci (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { 9718c2ecf20Sopenharmony_ci if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, 9728c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 9738c2ecf20Sopenharmony_ci &priv->curr_pkt_filter, false)) { 9748c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 9758c2ecf20Sopenharmony_ci "ADHOC_S_CMD: G Protection config failed\n"); 9768c2ecf20Sopenharmony_ci return -1; 9778c2ecf20Sopenharmony_ci } 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci /* Find the last non zero */ 9808c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(adhoc_start->data_rate); i++) 9818c2ecf20Sopenharmony_ci if (!adhoc_start->data_rate[i]) 9828c2ecf20Sopenharmony_ci break; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci priv->curr_bss_params.num_of_rates = i; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci /* Copy the ad-hoc creating rates into Current BSS rate structure */ 9878c2ecf20Sopenharmony_ci memcpy(&priv->curr_bss_params.data_rates, 9888c2ecf20Sopenharmony_ci &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: rates=%4ph\n", 9918c2ecf20Sopenharmony_ci adhoc_start->data_rate); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n"); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci if (IS_SUPPORT_MULTI_BANDS(adapter)) { 9968c2ecf20Sopenharmony_ci /* Append a channel TLV */ 9978c2ecf20Sopenharmony_ci chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; 9988c2ecf20Sopenharmony_ci chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 9998c2ecf20Sopenharmony_ci chan_tlv->header.len = 10008c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci memset(chan_tlv->chan_scan_param, 0x00, 10038c2ecf20Sopenharmony_ci sizeof(struct mwifiex_chan_scan_param_set)); 10048c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].chan_number = 10058c2ecf20Sopenharmony_ci (u8) priv->curr_bss_params.bss_descriptor.channel; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Chan = %d\n", 10088c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].chan_number); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].radio_type 10118c2ecf20Sopenharmony_ci = mwifiex_band_to_radio_type(priv->curr_bss_params.band); 10128c2ecf20Sopenharmony_ci if (adapter->adhoc_start_band & BAND_GN || 10138c2ecf20Sopenharmony_ci adapter->adhoc_start_band & BAND_AN) { 10148c2ecf20Sopenharmony_ci if (adapter->sec_chan_offset == 10158c2ecf20Sopenharmony_ci IEEE80211_HT_PARAM_CHA_SEC_ABOVE) 10168c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].radio_type |= 10178c2ecf20Sopenharmony_ci (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4); 10188c2ecf20Sopenharmony_ci else if (adapter->sec_chan_offset == 10198c2ecf20Sopenharmony_ci IEEE80211_HT_PARAM_CHA_SEC_BELOW) 10208c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].radio_type |= 10218c2ecf20Sopenharmony_ci (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4); 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Band = %d\n", 10248c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].radio_type); 10258c2ecf20Sopenharmony_ci pos += sizeof(chan_tlv->header) + 10268c2ecf20Sopenharmony_ci sizeof(struct mwifiex_chan_scan_param_set); 10278c2ecf20Sopenharmony_ci cmd_append_size += 10288c2ecf20Sopenharmony_ci sizeof(chan_tlv->header) + 10298c2ecf20Sopenharmony_ci sizeof(struct mwifiex_chan_scan_param_set); 10308c2ecf20Sopenharmony_ci } 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci /* Append vendor specific IE TLV */ 10338c2ecf20Sopenharmony_ci cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, 10348c2ecf20Sopenharmony_ci MWIFIEX_VSIE_MASK_ADHOC, &pos); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci if (priv->sec_info.wpa_enabled) { 10378c2ecf20Sopenharmony_ci rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); 10388c2ecf20Sopenharmony_ci if (rsn_ie_len == -1) 10398c2ecf20Sopenharmony_ci return -1; 10408c2ecf20Sopenharmony_ci cmd_append_size += rsn_ie_len; 10418c2ecf20Sopenharmony_ci } 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci if (adapter->adhoc_11n_enabled) { 10448c2ecf20Sopenharmony_ci /* Fill HT CAPABILITY */ 10458c2ecf20Sopenharmony_ci ht_cap = (struct mwifiex_ie_types_htcap *) pos; 10468c2ecf20Sopenharmony_ci memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); 10478c2ecf20Sopenharmony_ci ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); 10488c2ecf20Sopenharmony_ci ht_cap->header.len = 10498c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct ieee80211_ht_cap)); 10508c2ecf20Sopenharmony_ci radio_type = mwifiex_band_to_radio_type( 10518c2ecf20Sopenharmony_ci priv->adapter->config_bands); 10528c2ecf20Sopenharmony_ci mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci if (adapter->sec_chan_offset == 10558c2ecf20Sopenharmony_ci IEEE80211_HT_PARAM_CHA_SEC_NONE) { 10568c2ecf20Sopenharmony_ci u16 tmp_ht_cap; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci tmp_ht_cap = le16_to_cpu(ht_cap->ht_cap.cap_info); 10598c2ecf20Sopenharmony_ci tmp_ht_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; 10608c2ecf20Sopenharmony_ci tmp_ht_cap &= ~IEEE80211_HT_CAP_SGI_40; 10618c2ecf20Sopenharmony_ci ht_cap->ht_cap.cap_info = cpu_to_le16(tmp_ht_cap); 10628c2ecf20Sopenharmony_ci } 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci pos += sizeof(struct mwifiex_ie_types_htcap); 10658c2ecf20Sopenharmony_ci cmd_append_size += sizeof(struct mwifiex_ie_types_htcap); 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci /* Fill HT INFORMATION */ 10688c2ecf20Sopenharmony_ci ht_info = (struct mwifiex_ie_types_htinfo *) pos; 10698c2ecf20Sopenharmony_ci memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo)); 10708c2ecf20Sopenharmony_ci ht_info->header.type = cpu_to_le16(WLAN_EID_HT_OPERATION); 10718c2ecf20Sopenharmony_ci ht_info->header.len = 10728c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct ieee80211_ht_operation)); 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci ht_info->ht_oper.primary_chan = 10758c2ecf20Sopenharmony_ci (u8) priv->curr_bss_params.bss_descriptor.channel; 10768c2ecf20Sopenharmony_ci if (adapter->sec_chan_offset) { 10778c2ecf20Sopenharmony_ci ht_info->ht_oper.ht_param = adapter->sec_chan_offset; 10788c2ecf20Sopenharmony_ci ht_info->ht_oper.ht_param |= 10798c2ecf20Sopenharmony_ci IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; 10808c2ecf20Sopenharmony_ci } 10818c2ecf20Sopenharmony_ci ht_info->ht_oper.operation_mode = 10828c2ecf20Sopenharmony_ci cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); 10838c2ecf20Sopenharmony_ci ht_info->ht_oper.basic_set[0] = 0xff; 10848c2ecf20Sopenharmony_ci pos += sizeof(struct mwifiex_ie_types_htinfo); 10858c2ecf20Sopenharmony_ci cmd_append_size += 10868c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_types_htinfo); 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci cmd->size = 10908c2ecf20Sopenharmony_ci cpu_to_le16((u16)(sizeof(struct host_cmd_ds_802_11_ad_hoc_start) 10918c2ecf20Sopenharmony_ci + S_DS_GEN + cmd_append_size)); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci if (adapter->adhoc_start_band == BAND_B) 10948c2ecf20Sopenharmony_ci tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; 10958c2ecf20Sopenharmony_ci else 10968c2ecf20Sopenharmony_ci tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap); 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci return 0; 11018c2ecf20Sopenharmony_ci} 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci/* 11048c2ecf20Sopenharmony_ci * This function prepares command for ad-hoc join. 11058c2ecf20Sopenharmony_ci * 11068c2ecf20Sopenharmony_ci * Most of the parameters are set up by copying from the target BSS descriptor 11078c2ecf20Sopenharmony_ci * from the scan response. 11088c2ecf20Sopenharmony_ci * 11098c2ecf20Sopenharmony_ci * In addition, the following TLVs are added - 11108c2ecf20Sopenharmony_ci * - Channel TLV 11118c2ecf20Sopenharmony_ci * - Vendor specific IE 11128c2ecf20Sopenharmony_ci * - WPA/WPA2 IE 11138c2ecf20Sopenharmony_ci * - 11n IE 11148c2ecf20Sopenharmony_ci * 11158c2ecf20Sopenharmony_ci * Preparation also includes - 11168c2ecf20Sopenharmony_ci * - Setting command ID and proper size 11178c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 11188c2ecf20Sopenharmony_ci */ 11198c2ecf20Sopenharmony_ciint 11208c2ecf20Sopenharmony_cimwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, 11218c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 11228c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc) 11238c2ecf20Sopenharmony_ci{ 11248c2ecf20Sopenharmony_ci int rsn_ie_len = 0; 11258c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join = 11268c2ecf20Sopenharmony_ci &cmd->params.adhoc_join; 11278c2ecf20Sopenharmony_ci struct mwifiex_ie_types_chan_list_param_set *chan_tlv; 11288c2ecf20Sopenharmony_ci u32 cmd_append_size = 0; 11298c2ecf20Sopenharmony_ci u16 tmp_cap; 11308c2ecf20Sopenharmony_ci u32 i, rates_size = 0; 11318c2ecf20Sopenharmony_ci u16 curr_pkt_filter; 11328c2ecf20Sopenharmony_ci u8 *pos = 11338c2ecf20Sopenharmony_ci (u8 *) adhoc_join + 11348c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_802_11_ad_hoc_join); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci/* Use G protection */ 11378c2ecf20Sopenharmony_ci#define USE_G_PROTECTION 0x02 11388c2ecf20Sopenharmony_ci if (bss_desc->erp_flags & USE_G_PROTECTION) { 11398c2ecf20Sopenharmony_ci curr_pkt_filter = 11408c2ecf20Sopenharmony_ci priv-> 11418c2ecf20Sopenharmony_ci curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, 11448c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 11458c2ecf20Sopenharmony_ci &curr_pkt_filter, false)) { 11468c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 11478c2ecf20Sopenharmony_ci "ADHOC_J_CMD: G Protection config failed\n"); 11488c2ecf20Sopenharmony_ci return -1; 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci priv->attempted_bss_desc = bss_desc; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN); 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS; 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci adhoc_join->bss_descriptor.beacon_period 11598c2ecf20Sopenharmony_ci = cpu_to_le16(bss_desc->beacon_period); 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci memcpy(&adhoc_join->bss_descriptor.bssid, 11628c2ecf20Sopenharmony_ci &bss_desc->mac_address, ETH_ALEN); 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci memcpy(&adhoc_join->bss_descriptor.ssid, 11658c2ecf20Sopenharmony_ci &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci memcpy(&adhoc_join->bss_descriptor.phy_param_set, 11688c2ecf20Sopenharmony_ci &bss_desc->phy_param_set, 11698c2ecf20Sopenharmony_ci sizeof(union ieee_types_phy_param_set)); 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci memcpy(&adhoc_join->bss_descriptor.ss_param_set, 11728c2ecf20Sopenharmony_ci &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set)); 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci tmp_cap = bss_desc->cap_info_bitmap; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci tmp_cap &= CAPINFO_MASK; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 11798c2ecf20Sopenharmony_ci "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", 11808c2ecf20Sopenharmony_ci tmp_cap, CAPINFO_MASK); 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci /* Information on BSSID descriptor passed to FW */ 11838c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 11848c2ecf20Sopenharmony_ci "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n", 11858c2ecf20Sopenharmony_ci adhoc_join->bss_descriptor.bssid, 11868c2ecf20Sopenharmony_ci adhoc_join->bss_descriptor.ssid); 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci for (i = 0; i < MWIFIEX_SUPPORTED_RATES && 11898c2ecf20Sopenharmony_ci bss_desc->supported_rates[i]; i++) 11908c2ecf20Sopenharmony_ci ; 11918c2ecf20Sopenharmony_ci rates_size = i; 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci /* Copy Data Rates from the Rates recorded in scan response */ 11948c2ecf20Sopenharmony_ci memset(adhoc_join->bss_descriptor.data_rates, 0, 11958c2ecf20Sopenharmony_ci sizeof(adhoc_join->bss_descriptor.data_rates)); 11968c2ecf20Sopenharmony_ci memcpy(adhoc_join->bss_descriptor.data_rates, 11978c2ecf20Sopenharmony_ci bss_desc->supported_rates, rates_size); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci /* Copy the adhoc join rates into Current BSS state structure */ 12008c2ecf20Sopenharmony_ci priv->curr_bss_params.num_of_rates = rates_size; 12018c2ecf20Sopenharmony_ci memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates, 12028c2ecf20Sopenharmony_ci rates_size); 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci /* Copy the channel information */ 12058c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel; 12068c2ecf20Sopenharmony_ci priv->curr_bss_params.band = (u8) bss_desc->bss_band; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci if (priv->sec_info.wep_enabled || priv->sec_info.wpa_enabled) 12098c2ecf20Sopenharmony_ci tmp_cap |= WLAN_CAPABILITY_PRIVACY; 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) { 12128c2ecf20Sopenharmony_ci /* Append a channel TLV */ 12138c2ecf20Sopenharmony_ci chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; 12148c2ecf20Sopenharmony_ci chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); 12158c2ecf20Sopenharmony_ci chan_tlv->header.len = 12168c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci memset(chan_tlv->chan_scan_param, 0x00, 12198c2ecf20Sopenharmony_ci sizeof(struct mwifiex_chan_scan_param_set)); 12208c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].chan_number = 12218c2ecf20Sopenharmony_ci (bss_desc->phy_param_set.ds_param_set.current_chan); 12228c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Chan=%d\n", 12238c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].chan_number); 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].radio_type = 12268c2ecf20Sopenharmony_ci mwifiex_band_to_radio_type((u8) bss_desc->bss_band); 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Band=%d\n", 12298c2ecf20Sopenharmony_ci chan_tlv->chan_scan_param[0].radio_type); 12308c2ecf20Sopenharmony_ci pos += sizeof(chan_tlv->header) + 12318c2ecf20Sopenharmony_ci sizeof(struct mwifiex_chan_scan_param_set); 12328c2ecf20Sopenharmony_ci cmd_append_size += sizeof(chan_tlv->header) + 12338c2ecf20Sopenharmony_ci sizeof(struct mwifiex_chan_scan_param_set); 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci if (priv->sec_info.wpa_enabled) 12378c2ecf20Sopenharmony_ci rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); 12388c2ecf20Sopenharmony_ci if (rsn_ie_len == -1) 12398c2ecf20Sopenharmony_ci return -1; 12408c2ecf20Sopenharmony_ci cmd_append_size += rsn_ie_len; 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) 12438c2ecf20Sopenharmony_ci cmd_append_size += mwifiex_cmd_append_11n_tlv(priv, 12448c2ecf20Sopenharmony_ci bss_desc, &pos); 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci /* Append vendor specific IE TLV */ 12478c2ecf20Sopenharmony_ci cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, 12488c2ecf20Sopenharmony_ci MWIFIEX_VSIE_MASK_ADHOC, &pos); 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16 12518c2ecf20Sopenharmony_ci ((u16) (sizeof(struct host_cmd_ds_802_11_ad_hoc_join) 12528c2ecf20Sopenharmony_ci + S_DS_GEN + cmd_append_size)); 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci return 0; 12578c2ecf20Sopenharmony_ci} 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci/* 12608c2ecf20Sopenharmony_ci * This function handles the command response of ad-hoc start and 12618c2ecf20Sopenharmony_ci * ad-hoc join. 12628c2ecf20Sopenharmony_ci * 12638c2ecf20Sopenharmony_ci * The function generates a device-connected event to notify 12648c2ecf20Sopenharmony_ci * the applications, in case of successful ad-hoc start/join, and 12658c2ecf20Sopenharmony_ci * saves the beacon buffer. 12668c2ecf20Sopenharmony_ci */ 12678c2ecf20Sopenharmony_ciint mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, 12688c2ecf20Sopenharmony_ci struct host_cmd_ds_command *resp) 12698c2ecf20Sopenharmony_ci{ 12708c2ecf20Sopenharmony_ci int ret = 0; 12718c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 12728c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_ad_hoc_start_result *start_result = 12738c2ecf20Sopenharmony_ci &resp->params.start_result; 12748c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_ad_hoc_join_result *join_result = 12758c2ecf20Sopenharmony_ci &resp->params.join_result; 12768c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc; 12778c2ecf20Sopenharmony_ci u16 cmd = le16_to_cpu(resp->command); 12788c2ecf20Sopenharmony_ci u8 result; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci if (!priv->attempted_bss_desc) { 12818c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 12828c2ecf20Sopenharmony_ci "ADHOC_RESP: failed, association terminated by host\n"); 12838c2ecf20Sopenharmony_ci goto done; 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci if (cmd == HostCmd_CMD_802_11_AD_HOC_START) 12878c2ecf20Sopenharmony_ci result = start_result->result; 12888c2ecf20Sopenharmony_ci else 12898c2ecf20Sopenharmony_ci result = join_result->result; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci bss_desc = priv->attempted_bss_desc; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci /* Join result code 0 --> SUCCESS */ 12948c2ecf20Sopenharmony_ci if (result) { 12958c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, "ADHOC_RESP: failed\n"); 12968c2ecf20Sopenharmony_ci if (priv->media_connected) 12978c2ecf20Sopenharmony_ci mwifiex_reset_connect_state(priv, result, true); 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci memset(&priv->curr_bss_params.bss_descriptor, 13008c2ecf20Sopenharmony_ci 0x00, sizeof(struct mwifiex_bssdescriptor)); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci ret = -1; 13038c2ecf20Sopenharmony_ci goto done; 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci /* Send a Media Connected event, according to the Spec */ 13078c2ecf20Sopenharmony_ci priv->media_connected = true; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) { 13108c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_S_RESP %s\n", 13118c2ecf20Sopenharmony_ci bss_desc->ssid.ssid); 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci /* Update the created network descriptor with the new BSSID */ 13148c2ecf20Sopenharmony_ci memcpy(bss_desc->mac_address, 13158c2ecf20Sopenharmony_ci start_result->bssid, ETH_ALEN); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci priv->adhoc_state = ADHOC_STARTED; 13188c2ecf20Sopenharmony_ci } else { 13198c2ecf20Sopenharmony_ci /* 13208c2ecf20Sopenharmony_ci * Now the join cmd should be successful. 13218c2ecf20Sopenharmony_ci * If BSSID has changed use SSID to compare instead of BSSID 13228c2ecf20Sopenharmony_ci */ 13238c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 13248c2ecf20Sopenharmony_ci "info: ADHOC_J_RESP %s\n", 13258c2ecf20Sopenharmony_ci bss_desc->ssid.ssid); 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci /* 13288c2ecf20Sopenharmony_ci * Make a copy of current BSSID descriptor, only needed for 13298c2ecf20Sopenharmony_ci * join since the current descriptor is already being used 13308c2ecf20Sopenharmony_ci * for adhoc start 13318c2ecf20Sopenharmony_ci */ 13328c2ecf20Sopenharmony_ci memcpy(&priv->curr_bss_params.bss_descriptor, 13338c2ecf20Sopenharmony_ci bss_desc, sizeof(struct mwifiex_bssdescriptor)); 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci priv->adhoc_state = ADHOC_JOINED; 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: channel = %d\n", 13398c2ecf20Sopenharmony_ci priv->adhoc_channel); 13408c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: BSSID = %pM\n", 13418c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.mac_address); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci if (!netif_carrier_ok(priv->netdev)) 13448c2ecf20Sopenharmony_ci netif_carrier_on(priv->netdev); 13458c2ecf20Sopenharmony_ci mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci mwifiex_save_curr_bcn(priv); 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_cidone: 13508c2ecf20Sopenharmony_ci /* Need to indicate IOCTL complete */ 13518c2ecf20Sopenharmony_ci if (adapter->curr_cmd->wait_q_enabled) { 13528c2ecf20Sopenharmony_ci if (ret) 13538c2ecf20Sopenharmony_ci adapter->cmd_wait_q.status = -1; 13548c2ecf20Sopenharmony_ci else 13558c2ecf20Sopenharmony_ci adapter->cmd_wait_q.status = 0; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci return ret; 13608c2ecf20Sopenharmony_ci} 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci/* 13638c2ecf20Sopenharmony_ci * This function associates to a specific BSS discovered in a scan. 13648c2ecf20Sopenharmony_ci * 13658c2ecf20Sopenharmony_ci * It clears any past association response stored for application 13668c2ecf20Sopenharmony_ci * retrieval and calls the command preparation routine to send the 13678c2ecf20Sopenharmony_ci * command to firmware. 13688c2ecf20Sopenharmony_ci */ 13698c2ecf20Sopenharmony_ciint mwifiex_associate(struct mwifiex_private *priv, 13708c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc) 13718c2ecf20Sopenharmony_ci{ 13728c2ecf20Sopenharmony_ci /* Return error if the adapter is not STA role or table entry 13738c2ecf20Sopenharmony_ci * is not marked as infra. 13748c2ecf20Sopenharmony_ci */ 13758c2ecf20Sopenharmony_ci if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) || 13768c2ecf20Sopenharmony_ci (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) 13778c2ecf20Sopenharmony_ci return -1; 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 13808c2ecf20Sopenharmony_ci !bss_desc->disable_11n && !bss_desc->disable_11ac && 13818c2ecf20Sopenharmony_ci priv->adapter->config_bands & BAND_AAC) 13828c2ecf20Sopenharmony_ci mwifiex_set_11ac_ba_params(priv); 13838c2ecf20Sopenharmony_ci else 13848c2ecf20Sopenharmony_ci mwifiex_set_ba_params(priv); 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci /* Clear any past association response stored for application 13878c2ecf20Sopenharmony_ci retrieval */ 13888c2ecf20Sopenharmony_ci priv->assoc_rsp_size = 0; 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE, 13918c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, bss_desc, true); 13928c2ecf20Sopenharmony_ci} 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci/* 13958c2ecf20Sopenharmony_ci * This function starts an ad-hoc network. 13968c2ecf20Sopenharmony_ci * 13978c2ecf20Sopenharmony_ci * It calls the command preparation routine to send the command to firmware. 13988c2ecf20Sopenharmony_ci */ 13998c2ecf20Sopenharmony_ciint 14008c2ecf20Sopenharmony_cimwifiex_adhoc_start(struct mwifiex_private *priv, 14018c2ecf20Sopenharmony_ci struct cfg80211_ssid *adhoc_ssid) 14028c2ecf20Sopenharmony_ci{ 14038c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: Adhoc Channel = %d\n", 14048c2ecf20Sopenharmony_ci priv->adhoc_channel); 14058c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.channel = %d\n", 14068c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.channel); 14078c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.band = %d\n", 14088c2ecf20Sopenharmony_ci priv->curr_bss_params.band); 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 14118c2ecf20Sopenharmony_ci priv->adapter->config_bands & BAND_AAC) 14128c2ecf20Sopenharmony_ci mwifiex_set_11ac_ba_params(priv); 14138c2ecf20Sopenharmony_ci else 14148c2ecf20Sopenharmony_ci mwifiex_set_ba_params(priv); 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START, 14178c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, adhoc_ssid, true); 14188c2ecf20Sopenharmony_ci} 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci/* 14218c2ecf20Sopenharmony_ci * This function joins an ad-hoc network found in a previous scan. 14228c2ecf20Sopenharmony_ci * 14238c2ecf20Sopenharmony_ci * It calls the command preparation routine to send the command to firmware, 14248c2ecf20Sopenharmony_ci * if already not connected to the requested SSID. 14258c2ecf20Sopenharmony_ci */ 14268c2ecf20Sopenharmony_ciint mwifiex_adhoc_join(struct mwifiex_private *priv, 14278c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc) 14288c2ecf20Sopenharmony_ci{ 14298c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 14308c2ecf20Sopenharmony_ci "info: adhoc join: curr_bss ssid =%s\n", 14318c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.ssid.ssid); 14328c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 14338c2ecf20Sopenharmony_ci "info: adhoc join: curr_bss ssid_len =%u\n", 14348c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.ssid.ssid_len); 14358c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid =%s\n", 14368c2ecf20Sopenharmony_ci bss_desc->ssid.ssid); 14378c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid_len =%u\n", 14388c2ecf20Sopenharmony_ci bss_desc->ssid.ssid_len); 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci /* Check if the requested SSID is already joined */ 14418c2ecf20Sopenharmony_ci if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len && 14428c2ecf20Sopenharmony_ci !mwifiex_ssid_cmp(&bss_desc->ssid, 14438c2ecf20Sopenharmony_ci &priv->curr_bss_params.bss_descriptor.ssid) && 14448c2ecf20Sopenharmony_ci (priv->curr_bss_params.bss_descriptor.bss_mode == 14458c2ecf20Sopenharmony_ci NL80211_IFTYPE_ADHOC)) { 14468c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 14478c2ecf20Sopenharmony_ci "info: ADHOC_J_CMD: new ad-hoc SSID\t" 14488c2ecf20Sopenharmony_ci "is the same as current; not attempting to re-join\n"); 14498c2ecf20Sopenharmony_ci return -1; 14508c2ecf20Sopenharmony_ci } 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && 14538c2ecf20Sopenharmony_ci !bss_desc->disable_11n && !bss_desc->disable_11ac && 14548c2ecf20Sopenharmony_ci priv->adapter->config_bands & BAND_AAC) 14558c2ecf20Sopenharmony_ci mwifiex_set_11ac_ba_params(priv); 14568c2ecf20Sopenharmony_ci else 14578c2ecf20Sopenharmony_ci mwifiex_set_ba_params(priv); 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 14608c2ecf20Sopenharmony_ci "info: curr_bss_params.channel = %d\n", 14618c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.channel); 14628c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 14638c2ecf20Sopenharmony_ci "info: curr_bss_params.band = %c\n", 14648c2ecf20Sopenharmony_ci priv->curr_bss_params.band); 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, 14678c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, bss_desc, true); 14688c2ecf20Sopenharmony_ci} 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci/* 14718c2ecf20Sopenharmony_ci * This function deauthenticates/disconnects from infra network by sending 14728c2ecf20Sopenharmony_ci * deauthentication request. 14738c2ecf20Sopenharmony_ci */ 14748c2ecf20Sopenharmony_cistatic int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) 14758c2ecf20Sopenharmony_ci{ 14768c2ecf20Sopenharmony_ci u8 mac_address[ETH_ALEN]; 14778c2ecf20Sopenharmony_ci int ret; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci if (!mac || is_zero_ether_addr(mac)) 14808c2ecf20Sopenharmony_ci memcpy(mac_address, 14818c2ecf20Sopenharmony_ci priv->curr_bss_params.bss_descriptor.mac_address, 14828c2ecf20Sopenharmony_ci ETH_ALEN); 14838c2ecf20Sopenharmony_ci else 14848c2ecf20Sopenharmony_ci memcpy(mac_address, mac, ETH_ALEN); 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, 14878c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, mac_address, true); 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci return ret; 14908c2ecf20Sopenharmony_ci} 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci/* 14938c2ecf20Sopenharmony_ci * This function deauthenticates/disconnects from a BSS. 14948c2ecf20Sopenharmony_ci * 14958c2ecf20Sopenharmony_ci * In case of infra made, it sends deauthentication request, and 14968c2ecf20Sopenharmony_ci * in case of ad-hoc mode, a stop network request is sent to the firmware. 14978c2ecf20Sopenharmony_ci * In AP mode, a command to stop bss is sent to firmware. 14988c2ecf20Sopenharmony_ci */ 14998c2ecf20Sopenharmony_ciint mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) 15008c2ecf20Sopenharmony_ci{ 15018c2ecf20Sopenharmony_ci int ret = 0; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci if (!priv->media_connected) 15048c2ecf20Sopenharmony_ci return 0; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci switch (priv->bss_mode) { 15078c2ecf20Sopenharmony_ci case NL80211_IFTYPE_STATION: 15088c2ecf20Sopenharmony_ci case NL80211_IFTYPE_P2P_CLIENT: 15098c2ecf20Sopenharmony_ci ret = mwifiex_deauthenticate_infra(priv, mac); 15108c2ecf20Sopenharmony_ci if (ret) 15118c2ecf20Sopenharmony_ci cfg80211_disconnected(priv->netdev, 0, NULL, 0, 15128c2ecf20Sopenharmony_ci true, GFP_KERNEL); 15138c2ecf20Sopenharmony_ci break; 15148c2ecf20Sopenharmony_ci case NL80211_IFTYPE_ADHOC: 15158c2ecf20Sopenharmony_ci return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP, 15168c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, NULL, true); 15178c2ecf20Sopenharmony_ci case NL80211_IFTYPE_AP: 15188c2ecf20Sopenharmony_ci return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, 15198c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, NULL, true); 15208c2ecf20Sopenharmony_ci default: 15218c2ecf20Sopenharmony_ci break; 15228c2ecf20Sopenharmony_ci } 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci return ret; 15258c2ecf20Sopenharmony_ci} 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci/* This function deauthenticates/disconnects from all BSS. */ 15288c2ecf20Sopenharmony_civoid mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter) 15298c2ecf20Sopenharmony_ci{ 15308c2ecf20Sopenharmony_ci struct mwifiex_private *priv; 15318c2ecf20Sopenharmony_ci int i; 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci for (i = 0; i < adapter->priv_num; i++) { 15348c2ecf20Sopenharmony_ci priv = adapter->priv[i]; 15358c2ecf20Sopenharmony_ci if (priv) 15368c2ecf20Sopenharmony_ci mwifiex_deauthenticate(priv, NULL); 15378c2ecf20Sopenharmony_ci } 15388c2ecf20Sopenharmony_ci} 15398c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mwifiex_deauthenticate_all); 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci/* 15428c2ecf20Sopenharmony_ci * This function converts band to radio type used in channel TLV. 15438c2ecf20Sopenharmony_ci */ 15448c2ecf20Sopenharmony_ciu8 15458c2ecf20Sopenharmony_cimwifiex_band_to_radio_type(u8 band) 15468c2ecf20Sopenharmony_ci{ 15478c2ecf20Sopenharmony_ci switch (band) { 15488c2ecf20Sopenharmony_ci case BAND_A: 15498c2ecf20Sopenharmony_ci case BAND_AN: 15508c2ecf20Sopenharmony_ci case BAND_A | BAND_AN: 15518c2ecf20Sopenharmony_ci case BAND_A | BAND_AN | BAND_AAC: 15528c2ecf20Sopenharmony_ci return HostCmd_SCAN_RADIO_TYPE_A; 15538c2ecf20Sopenharmony_ci case BAND_B: 15548c2ecf20Sopenharmony_ci case BAND_G: 15558c2ecf20Sopenharmony_ci case BAND_B | BAND_G: 15568c2ecf20Sopenharmony_ci default: 15578c2ecf20Sopenharmony_ci return HostCmd_SCAN_RADIO_TYPE_BG; 15588c2ecf20Sopenharmony_ci } 15598c2ecf20Sopenharmony_ci} 1560