blob: 852cd8ecda77bf4712b14f7e3c163a4e5ab2f565 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Wilson Yangef657d32014-01-15 19:19:23 -08002 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20*/
Jeff Johnson295189b2012-06-20 16:38:30 -070021
22/**========================================================================
23
24 \file wlan_hdd_cfg80211.c
25
26 \brief WLAN Host Device Driver implementation
27
Gopichand Nakkala747461f2013-04-24 19:24:45 +053028 Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070029
Gopichand Nakkala747461f2013-04-24 19:24:45 +053030 Qualcomm Technologies Confidential and Proprietary.
Jeff Johnson295189b2012-06-20 16:38:30 -070031
32 ========================================================================*/
33
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070034/**=========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -070035
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070036 EDIT HISTORY FOR FILE
Jeff Johnson295189b2012-06-20 16:38:30 -070037
38
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070039 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
Jeff Johnson295189b2012-06-20 16:38:30 -070041
42
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070043 $Header:$ $DateTime: $ $Author: $
Jeff Johnson295189b2012-06-20 16:38:30 -070044
45
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070046 when who what, where, why
Jeff Johnson295189b2012-06-20 16:38:30 -070047 -------- --- --------------------------------------------------------
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070048 21/12/09 Ashwani Created module.
Jeff Johnson295189b2012-06-20 16:38:30 -070049
50 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070051 Ganesh K
Jeff Johnson295189b2012-06-20 16:38:30 -070052 ==========================================================================*/
53
Jeff Johnson295189b2012-06-20 16:38:30 -070054
55#include <linux/version.h>
56#include <linux/module.h>
57#include <linux/kernel.h>
58#include <linux/init.h>
59#include <linux/wireless.h>
60#include <wlan_hdd_includes.h>
61#include <net/arp.h>
62#include <net/cfg80211.h>
63#include <linux/wireless.h>
64#include <wlan_hdd_wowl.h>
65#include <aniGlobal.h>
66#include "ccmApi.h"
67#include "sirParams.h"
68#include "dot11f.h"
69#include "wlan_hdd_assoc.h"
70#include "wlan_hdd_wext.h"
71#include "sme_Api.h"
72#include "wlan_hdd_p2p.h"
73#include "wlan_hdd_cfg80211.h"
74#include "wlan_hdd_hostapd.h"
75#include "sapInternal.h"
76#include "wlan_hdd_softap_tx_rx.h"
77#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053078#include "wlan_hdd_assoc.h"
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053079#include "wlan_hdd_power.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070080#ifdef WLAN_BTAMP_FEATURE
81#include "bap_hdd_misc.h"
82#endif
83#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -080084#ifdef FEATURE_WLAN_TDLS
85#include "wlan_hdd_tdls.h"
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053086#include "wlan_hdd_wmm.h"
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +053087#include "wlan_qct_wda.h"
Mohit Khanna698ba2a2012-12-04 15:08:18 -080088#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +053089#include "wlan_nv.h"
Leo Chang6fe1f922013-06-07 19:21:24 -070090#include "wlan_hdd_dev_pwr.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070091
92#define g_mode_rates_size (12)
93#define a_mode_rates_size (8)
94#define FREQ_BASE_80211G (2407)
95#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070096#define MAX_SCAN_SSID 9
Kiet Lamac06e2c2013-10-23 16:25:07 +053097#define MAX_PENDING_LOG 5
Jeff Johnson295189b2012-06-20 16:38:30 -070098#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
99 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
100
101#define HDD2GHZCHAN(freq, chan, flag) { \
102 .band = IEEE80211_BAND_2GHZ, \
103 .center_freq = (freq), \
104 .hw_value = (chan),\
105 .flags = (flag), \
106 .max_antenna_gain = 0 ,\
107 .max_power = 30, \
108}
109
110#define HDD5GHZCHAN(freq, chan, flag) { \
111 .band = IEEE80211_BAND_5GHZ, \
112 .center_freq = (freq), \
113 .hw_value = (chan),\
114 .flags = (flag), \
115 .max_antenna_gain = 0 ,\
116 .max_power = 30, \
117}
118
119#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
120{\
121 .bitrate = rate, \
122 .hw_value = rate_id, \
123 .flags = flag, \
124}
125
Lee Hoonkic1262f22013-01-24 21:59:00 -0800126#ifndef WLAN_FEATURE_TDLS_DEBUG
127#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
128#else
129#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
130#endif
131
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530132#ifdef WLAN_FEATURE_VOWIFI_11R
133#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
134#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
135#endif
136
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530137static const u32 hdd_cipher_suites[] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700138{
139 WLAN_CIPHER_SUITE_WEP40,
140 WLAN_CIPHER_SUITE_WEP104,
141 WLAN_CIPHER_SUITE_TKIP,
142#ifdef FEATURE_WLAN_CCX
143#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
144 WLAN_CIPHER_SUITE_KRK,
145 WLAN_CIPHER_SUITE_CCMP,
146#else
147 WLAN_CIPHER_SUITE_CCMP,
148#endif
149#ifdef FEATURE_WLAN_WAPI
150 WLAN_CIPHER_SUITE_SMS4,
151#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700152#ifdef WLAN_FEATURE_11W
153 WLAN_CIPHER_SUITE_AES_CMAC,
154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155};
156
157static inline int is_broadcast_ether_addr(const u8 *addr)
158{
159 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
160 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
161}
162
163static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530164{
Jeff Johnson295189b2012-06-20 16:38:30 -0700165 HDD2GHZCHAN(2412, 1, 0) ,
166 HDD2GHZCHAN(2417, 2, 0) ,
167 HDD2GHZCHAN(2422, 3, 0) ,
168 HDD2GHZCHAN(2427, 4, 0) ,
169 HDD2GHZCHAN(2432, 5, 0) ,
170 HDD2GHZCHAN(2437, 6, 0) ,
171 HDD2GHZCHAN(2442, 7, 0) ,
172 HDD2GHZCHAN(2447, 8, 0) ,
173 HDD2GHZCHAN(2452, 9, 0) ,
174 HDD2GHZCHAN(2457, 10, 0) ,
175 HDD2GHZCHAN(2462, 11, 0) ,
176 HDD2GHZCHAN(2467, 12, 0) ,
177 HDD2GHZCHAN(2472, 13, 0) ,
178 HDD2GHZCHAN(2484, 14, 0) ,
179};
180
Jeff Johnson295189b2012-06-20 16:38:30 -0700181static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
182{
183 HDD2GHZCHAN(2412, 1, 0) ,
184 HDD2GHZCHAN(2437, 6, 0) ,
185 HDD2GHZCHAN(2462, 11, 0) ,
186};
Jeff Johnson295189b2012-06-20 16:38:30 -0700187
188static struct ieee80211_channel hdd_channels_5_GHZ[] =
189{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700190 HDD5GHZCHAN(4920, 240, 0) ,
191 HDD5GHZCHAN(4940, 244, 0) ,
192 HDD5GHZCHAN(4960, 248, 0) ,
193 HDD5GHZCHAN(4980, 252, 0) ,
194 HDD5GHZCHAN(5040, 208, 0) ,
195 HDD5GHZCHAN(5060, 212, 0) ,
196 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700197 HDD5GHZCHAN(5180, 36, 0) ,
198 HDD5GHZCHAN(5200, 40, 0) ,
199 HDD5GHZCHAN(5220, 44, 0) ,
200 HDD5GHZCHAN(5240, 48, 0) ,
201 HDD5GHZCHAN(5260, 52, 0) ,
202 HDD5GHZCHAN(5280, 56, 0) ,
203 HDD5GHZCHAN(5300, 60, 0) ,
204 HDD5GHZCHAN(5320, 64, 0) ,
205 HDD5GHZCHAN(5500,100, 0) ,
206 HDD5GHZCHAN(5520,104, 0) ,
207 HDD5GHZCHAN(5540,108, 0) ,
208 HDD5GHZCHAN(5560,112, 0) ,
209 HDD5GHZCHAN(5580,116, 0) ,
210 HDD5GHZCHAN(5600,120, 0) ,
211 HDD5GHZCHAN(5620,124, 0) ,
212 HDD5GHZCHAN(5640,128, 0) ,
213 HDD5GHZCHAN(5660,132, 0) ,
214 HDD5GHZCHAN(5680,136, 0) ,
215 HDD5GHZCHAN(5700,140, 0) ,
Leo Chang80de3c22013-11-26 10:52:12 -0800216#ifdef FEATURE_WLAN_CH144
217 HDD5GHZCHAN(5720,144, 0) ,
218#endif /* FEATURE_WLAN_CH144 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700219 HDD5GHZCHAN(5745,149, 0) ,
220 HDD5GHZCHAN(5765,153, 0) ,
221 HDD5GHZCHAN(5785,157, 0) ,
222 HDD5GHZCHAN(5805,161, 0) ,
223 HDD5GHZCHAN(5825,165, 0) ,
224};
225
226static struct ieee80211_rate g_mode_rates[] =
227{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530228 HDD_G_MODE_RATETAB(10, 0x1, 0),
229 HDD_G_MODE_RATETAB(20, 0x2, 0),
230 HDD_G_MODE_RATETAB(55, 0x4, 0),
231 HDD_G_MODE_RATETAB(110, 0x8, 0),
232 HDD_G_MODE_RATETAB(60, 0x10, 0),
233 HDD_G_MODE_RATETAB(90, 0x20, 0),
234 HDD_G_MODE_RATETAB(120, 0x40, 0),
235 HDD_G_MODE_RATETAB(180, 0x80, 0),
236 HDD_G_MODE_RATETAB(240, 0x100, 0),
237 HDD_G_MODE_RATETAB(360, 0x200, 0),
238 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700239 HDD_G_MODE_RATETAB(540, 0x800, 0),
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530240};
Jeff Johnson295189b2012-06-20 16:38:30 -0700241
242static struct ieee80211_rate a_mode_rates[] =
243{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
255{
256 .channels = hdd_channels_2_4_GHZ,
257 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
258 .band = IEEE80211_BAND_2GHZ,
259 .bitrates = g_mode_rates,
260 .n_bitrates = g_mode_rates_size,
261 .ht_cap.ht_supported = 1,
262 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
263 | IEEE80211_HT_CAP_GRN_FLD
264 | IEEE80211_HT_CAP_DSSSCCK40
265 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
266 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
267 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
268 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
269 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
270 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
271};
272
Jeff Johnson295189b2012-06-20 16:38:30 -0700273static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
274{
275 .channels = hdd_social_channels_2_4_GHZ,
276 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
277 .band = IEEE80211_BAND_2GHZ,
278 .bitrates = g_mode_rates,
279 .n_bitrates = g_mode_rates_size,
280 .ht_cap.ht_supported = 1,
281 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
282 | IEEE80211_HT_CAP_GRN_FLD
283 | IEEE80211_HT_CAP_DSSSCCK40
284 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
285 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
286 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
287 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
288 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
289 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
290};
Jeff Johnson295189b2012-06-20 16:38:30 -0700291
292static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
293{
294 .channels = hdd_channels_5_GHZ,
295 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
296 .band = IEEE80211_BAND_5GHZ,
297 .bitrates = a_mode_rates,
298 .n_bitrates = a_mode_rates_size,
299 .ht_cap.ht_supported = 1,
300 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
301 | IEEE80211_HT_CAP_GRN_FLD
302 | IEEE80211_HT_CAP_DSSSCCK40
303 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
304 | IEEE80211_HT_CAP_SGI_40
305 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
306 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
307 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
308 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
309 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
310 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
311};
312
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530313/* This structure contain information what kind of frame are expected in
Jeff Johnson295189b2012-06-20 16:38:30 -0700314 TX/RX direction for each kind of interface */
315static const struct ieee80211_txrx_stypes
316wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
317 [NL80211_IFTYPE_STATION] = {
318 .tx = 0xffff,
319 .rx = BIT(SIR_MAC_MGMT_ACTION) |
320 BIT(SIR_MAC_MGMT_PROBE_REQ),
321 },
322 [NL80211_IFTYPE_AP] = {
323 .tx = 0xffff,
324 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
325 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_PROBE_REQ) |
327 BIT(SIR_MAC_MGMT_DISASSOC) |
328 BIT(SIR_MAC_MGMT_AUTH) |
329 BIT(SIR_MAC_MGMT_DEAUTH) |
330 BIT(SIR_MAC_MGMT_ACTION),
331 },
Jeff Johnsonbc006202013-04-29 14:05:30 -0700332 [NL80211_IFTYPE_ADHOC] = {
333 .tx = 0xffff,
334 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
335 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
336 BIT(SIR_MAC_MGMT_PROBE_REQ) |
337 BIT(SIR_MAC_MGMT_DISASSOC) |
338 BIT(SIR_MAC_MGMT_AUTH) |
339 BIT(SIR_MAC_MGMT_DEAUTH) |
340 BIT(SIR_MAC_MGMT_ACTION),
341 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700342 [NL80211_IFTYPE_P2P_CLIENT] = {
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ACTION) |
345 BIT(SIR_MAC_MGMT_PROBE_REQ),
346 },
347 [NL80211_IFTYPE_P2P_GO] = {
348 /* This is also same as for SoftAP */
349 .tx = 0xffff,
350 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
351 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
352 BIT(SIR_MAC_MGMT_PROBE_REQ) |
353 BIT(SIR_MAC_MGMT_DISASSOC) |
354 BIT(SIR_MAC_MGMT_AUTH) |
355 BIT(SIR_MAC_MGMT_DEAUTH) |
356 BIT(SIR_MAC_MGMT_ACTION),
357 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700358};
359
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800360#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800361static const struct ieee80211_iface_limit
362wlan_hdd_iface_limit[] = {
363 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800364 /* max = 3 ; Our driver create two interfaces during driver init
365 * wlan0 and p2p0 interfaces. p2p0 is considered as station
366 * interface until a group is formed. In JB architecture, once the
367 * group is formed, interface type of p2p0 is changed to P2P GO or
368 * Client.
369 * When supplicant remove the group, it first issue a set interface
370 * cmd to change the mode back to Station. In JB this works fine as
371 * we advertize two station type interface during driver init.
372 * Some vendors create separate interface for P2P GO/Client,
373 * after group formation(Third one). But while group remove
374 * supplicant first tries to change the mode(3rd interface) to STATION
375 * But as we advertized only two sta type interfaces nl80211 was
376 * returning error for the third one which was leading to failure in
377 * delete interface. Ideally while removing the group, supplicant
378 * should not try to change the 3rd interface mode to Station type.
379 * Till we get a fix in wpa_supplicant, we advertize max STA
380 * interface type to 3
381 */
382 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800383 .types = BIT(NL80211_IFTYPE_STATION),
384 },
385 {
386 .max = 1,
Jeff Johnsonbc006202013-04-29 14:05:30 -0700387 .types = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP),
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800388 },
389 {
390 .max = 1,
391 .types = BIT(NL80211_IFTYPE_P2P_GO) |
392 BIT(NL80211_IFTYPE_P2P_CLIENT),
393 },
394};
395
396/* By default, only single channel concurrency is allowed */
397static struct ieee80211_iface_combination
398wlan_hdd_iface_combination = {
399 .limits = wlan_hdd_iface_limit,
400 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800401 /*
402 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
403 * and p2p0 interfaces during driver init
404 * Some vendors create separate interface for P2P operations.
405 * wlan0: STA interface
406 * p2p0: P2P Device interface, action frames goes
407 * through this interface.
408 * p2p-xx: P2P interface, After GO negotiation this interface is
409 * created for p2p operations(GO/CLIENT interface).
410 */
411 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800412 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
413 .beacon_int_infra_match = false,
414};
415#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800416
Jeff Johnson295189b2012-06-20 16:38:30 -0700417static struct cfg80211_ops wlan_hdd_cfg80211_ops;
418
419/* Data rate 100KBPS based on IE Index */
420struct index_data_rate_type
421{
422 v_U8_t beacon_rate_index;
423 v_U16_t supported_rate[4];
424};
425
426/* 11B, 11G Rate table include Basic rate and Extended rate
427 The IDX field is the rate index
428 The HI field is the rate when RSSI is strong or being ignored
429 (in this case we report actual rate)
430 The MID field is the rate when RSSI is moderate
431 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
432 The LO field is the rate when RSSI is low
433 (in this case we don't report rates, actual current rate used)
434 */
435static const struct
436{
437 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700438 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700439} supported_data_rate[] =
440{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700441/* IDX HI HM LM LO (RSSI-based index */
442 {2, { 10, 10, 10, 0}},
443 {4, { 20, 20, 10, 0}},
444 {11, { 55, 20, 10, 0}},
445 {12, { 60, 55, 20, 0}},
446 {18, { 90, 55, 20, 0}},
447 {22, {110, 55, 20, 0}},
448 {24, {120, 90, 60, 0}},
449 {36, {180, 120, 60, 0}},
450 {44, {220, 180, 60, 0}},
451 {48, {240, 180, 90, 0}},
452 {66, {330, 180, 90, 0}},
453 {72, {360, 240, 90, 0}},
454 {96, {480, 240, 120, 0}},
455 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700456};
457
458/* MCS Based rate table */
459static struct index_data_rate_type supported_mcs_rate[] =
460{
461/* MCS L20 L40 S20 S40 */
462 {0, {65, 135, 72, 150}},
463 {1, {130, 270, 144, 300}},
464 {2, {195, 405, 217, 450}},
465 {3, {260, 540, 289, 600}},
466 {4, {390, 810, 433, 900}},
467 {5, {520, 1080, 578, 1200}},
468 {6, {585, 1215, 650, 1350}},
469 {7, {650, 1350, 722, 1500}}
470};
471
Leo Chang6f8870f2013-03-26 18:11:36 -0700472#ifdef WLAN_FEATURE_11AC
473
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530474#define DATA_RATE_11AC_MCS_MASK 0x03
Leo Chang6f8870f2013-03-26 18:11:36 -0700475
476struct index_vht_data_rate_type
477{
478 v_U8_t beacon_rate_index;
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530479 v_U16_t supported_VHT80_rate[2];
480 v_U16_t supported_VHT40_rate[2];
481 v_U16_t supported_VHT20_rate[2];
Leo Chang6f8870f2013-03-26 18:11:36 -0700482};
483
484typedef enum
485{
486 DATA_RATE_11AC_MAX_MCS_7,
487 DATA_RATE_11AC_MAX_MCS_8,
488 DATA_RATE_11AC_MAX_MCS_9,
489 DATA_RATE_11AC_MAX_MCS_NA
490} eDataRate11ACMaxMcs;
491
492/* MCS Based VHT rate table */
493static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
494{
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530495/* MCS L80 S80 L40 S40 L20 S40*/
496 {0, {293, 325}, {135, 150}, {65, 72}},
497 {1, {585, 650}, {270, 300}, {130, 144}},
498 {2, {878, 975}, {405, 450}, {195, 217}},
499 {3, {1170, 1300}, {540, 600}, {260, 289}},
500 {4, {1755, 1950}, {810, 900}, {390, 433}},
501 {5, {2340, 2600}, {1080, 1200}, {520, 578}},
502 {6, {2633, 2925}, {1215, 1350}, {585, 650}},
503 {7, {2925, 3250}, {1350, 1500}, {650, 722}},
504 {8, {3510, 3900}, {1620, 1800}, {780, 867}},
505 {9, {3900, 4333}, {1800, 2000}, {780, 867}}
Leo Chang6f8870f2013-03-26 18:11:36 -0700506};
507#endif /* WLAN_FEATURE_11AC */
508
Jeff Johnson295189b2012-06-20 16:38:30 -0700509extern struct net_device_ops net_ops_struct;
510
Leo Chang9056f462013-08-01 19:21:11 -0700511#ifdef WLAN_NL80211_TESTMODE
512enum wlan_hdd_tm_attr
513{
514 WLAN_HDD_TM_ATTR_INVALID = 0,
515 WLAN_HDD_TM_ATTR_CMD = 1,
516 WLAN_HDD_TM_ATTR_DATA = 2,
517 WLAN_HDD_TM_ATTR_TYPE = 3,
518 /* keep last */
519 WLAN_HDD_TM_ATTR_AFTER_LAST,
520 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
521};
522
523enum wlan_hdd_tm_cmd
524{
525 WLAN_HDD_TM_CMD_WLAN_HB = 1,
526};
527
528#define WLAN_HDD_TM_DATA_MAX_LEN 5000
529
530static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] =
531{
532 [WLAN_HDD_TM_ATTR_CMD] = { .type = NLA_U32 },
533 [WLAN_HDD_TM_ATTR_DATA] = { .type = NLA_BINARY,
534 .len = WLAN_HDD_TM_DATA_MAX_LEN },
535};
536#endif /* WLAN_NL80211_TESTMODE */
537
Rajesh Chauhan98a31f82014-01-06 20:15:25 -0800538#ifdef FEATURE_WLAN_CH_AVOID
539/*
540 * FUNCTION: wlan_hdd_send_avoid_freq_event
541 * This is called when wlan driver needs to send vendor specific
542 * avoid frequency range event to userspace
543 */
544int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
545 tHddAvoidFreqList *pAvoidFreqList)
546{
547 struct sk_buff *vendor_event;
548
549 ENTER();
550
551 if (!pHddCtx)
552 {
553 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
554 "%s: HDD context is null", __func__);
555 return -1;
556 }
557
558 if (!pAvoidFreqList)
559 {
560 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
561 "%s: pAvoidFreqList is null", __func__);
562 return -1;
563 }
564
565 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
566 sizeof(tHddAvoidFreqList),
567 QCOM_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
568 GFP_KERNEL);
569 if (!vendor_event)
570 {
571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
572 "%s: cfg80211_vendor_event_alloc failed", __func__);
573 return -1;
574 }
575
576 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
577 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
578
579 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
580
581 EXIT();
582 return 0;
583}
584#endif /* FEATURE_WLAN_CH_AVOID */
585
586/* vendor specific events */
587static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
588{
589#ifdef FEATURE_WLAN_CH_AVOID
590 {
591 .vendor_id = QCOM_NL80211_VENDOR_ID,
592 .subcmd = QCOM_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
593 },
594#endif /* FEATURE_WLAN_CH_AVOID */
595};
596
Jeff Johnson295189b2012-06-20 16:38:30 -0700597/*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530598 * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530599 * This function is called by hdd_wlan_startup()
600 * during initialization.
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530601 * This function is used to allocate wiphy structure.
Jeff Johnson295189b2012-06-20 16:38:30 -0700602 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530603struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size)
Jeff Johnson295189b2012-06-20 16:38:30 -0700604{
605 struct wiphy *wiphy;
606 ENTER();
607
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530608 /*
609 * Create wiphy device
Jeff Johnson295189b2012-06-20 16:38:30 -0700610 */
611 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
612
613 if (!wiphy)
614 {
615 /* Print error and jump into err label and free the memory */
616 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
617 return NULL;
618 }
619
620 return wiphy;
621}
622
623/*
624 * FUNCTION: wlan_hdd_cfg80211_update_band
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530625 * This function is called from the supplicant through a
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 * private ioctl to change the band value
627 */
628int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
629{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530630 int i, j;
631 eNVChannelEnabledType channelEnabledState;
632
Jeff Johnsone7245742012-09-05 17:12:55 -0700633 ENTER();
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530634 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
Jeff Johnson295189b2012-06-20 16:38:30 -0700635 {
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530636
637 if (NULL == wiphy->bands[i])
638 {
639 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
640 __func__, i);
641 continue;
642 }
643
644 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
645 {
646 struct ieee80211_supported_band *band = wiphy->bands[i];
647
648 channelEnabledState = vos_nv_getChannelEnabledState(
649 band->channels[j].hw_value);
650
651 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only
652 {
653 // Enable Social channels for P2P
654 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) &&
655 NV_CHANNEL_ENABLE == channelEnabledState)
656 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
657 else
658 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
659 continue;
660 }
661 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only
662 {
663 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
664 continue;
665 }
666
667 if (NV_CHANNEL_DISABLE == channelEnabledState ||
668 NV_CHANNEL_INVALID == channelEnabledState)
669 {
670 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
671 }
672 else if (NV_CHANNEL_DFS == channelEnabledState)
673 {
674 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
675 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
676 }
677 else
678 {
679 band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
680 |IEEE80211_CHAN_RADAR);
681 }
682 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700683 }
684 return 0;
685}
686/*
687 * FUNCTION: wlan_hdd_cfg80211_init
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530688 * This function is called by hdd_wlan_startup()
689 * during initialization.
Jeff Johnson295189b2012-06-20 16:38:30 -0700690 * This function is used to initialize and register wiphy structure.
691 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530692int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700693 struct wiphy *wiphy,
694 hdd_config_t *pCfg
695 )
696{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530697 int i, j;
Jeff Johnsone7245742012-09-05 17:12:55 -0700698 ENTER();
699
Jeff Johnson295189b2012-06-20 16:38:30 -0700700 /* Now bind the underlying wlan device with wiphy */
701 set_wiphy_dev(wiphy, dev);
702
703 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700704
Kiet Lam6c583332013-10-14 05:37:09 +0530705#ifndef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -0700706 /* the flag for the other case would be initialzed in
707 vos_init_wiphy_from_nv_bin */
Amar Singhal0a402232013-10-11 20:57:16 -0700708 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
Kiet Lam6c583332013-10-14 05:37:09 +0530709#endif
Amar Singhala49cbc52013-10-08 18:37:44 -0700710
Amar Singhalfddc28c2013-09-05 13:03:40 -0700711 /* This will disable updating of NL channels from passive to
712 * active if a beacon is received on passive channel. */
713 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhalf0073192013-09-20 12:34:56 -0700714
Amar Singhalfddc28c2013-09-05 13:03:40 -0700715
Amar Singhala49cbc52013-10-08 18:37:44 -0700716
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700717#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700718 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
719 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
720 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700721 | WIPHY_FLAG_OFFCHAN_TX;
Kiet Lam6c583332013-10-14 05:37:09 +0530722 wiphy->country_ie_pref = NL80211_COUNTRY_IE_IGNORE_CORE;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700723#endif
Amar Singhala49cbc52013-10-08 18:37:44 -0700724
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700725#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
726 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800727#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700728 || pCfg->isFastRoamIniFeatureEnabled
729#endif
730#ifdef FEATURE_WLAN_CCX
731 || pCfg->isCcxIniFeatureEnabled
732#endif
733 )
734 {
735 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
736 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800737#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800738#ifdef FEATURE_WLAN_TDLS
739 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
740 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
741#endif
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530742#ifdef FEATURE_WLAN_SCAN_PNO
Hardik Kantilal Patel3dfd8792013-11-13 20:34:57 +0530743 if (pCfg->configPNOScanSupport)
744 {
745 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
746 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
747 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
748 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
749 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530750#endif/*FEATURE_WLAN_SCAN_PNO*/
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800751
Amar Singhalfddc28c2013-09-05 13:03:40 -0700752#ifdef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700753 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
754 driver can still register regulatory callback and
Amar Singhalfddc28c2013-09-05 13:03:40 -0700755 it will get regulatory settings in wiphy->band[], but
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700756 driver need to determine what to do with both
757 regulatory settings */
Amar Singhalfddc28c2013-09-05 13:03:40 -0700758
759 wiphy->reg_notifier = wlan_hdd_linux_reg_notifier;
Amar Singhala49cbc52013-10-08 18:37:44 -0700760#else
761 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700762#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700763
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530764 wiphy->max_scan_ssids = MAX_SCAN_SSID;
765
Madan Mohan Koyyalamudi6815b162013-07-19 17:17:46 +0530766 wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Jeff Johnson295189b2012-06-20 16:38:30 -0700767
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +0530768 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
769
Jeff Johnson295189b2012-06-20 16:38:30 -0700770 /* Supports STATION & AD-HOC modes right now */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530771 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -0700772 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700773 | BIT(NL80211_IFTYPE_P2P_CLIENT)
774 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700775 | BIT(NL80211_IFTYPE_AP);
776
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800777#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800778 if( pCfg->enableMCC )
779 {
780 /* Currently, supports up to two channels */
781 wlan_hdd_iface_combination.num_different_channels = 2;
782
783 if( !pCfg->allowMCCGODiffBI )
784 wlan_hdd_iface_combination.beacon_int_infra_match = true;
785
786 }
787 wiphy->iface_combinations = &wlan_hdd_iface_combination;
788 wiphy->n_iface_combinations = 1;
789#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800790
Jeff Johnson295189b2012-06-20 16:38:30 -0700791 /* Before registering we need to update the ht capabilitied based
792 * on ini values*/
793 if( !pCfg->ShortGI20MhzEnable )
794 {
795 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
796 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
797 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
798 }
799
800 if( !pCfg->ShortGI40MhzEnable )
801 {
802 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
803 }
804
805 if( !pCfg->nChannelBondingMode5GHz )
806 {
807 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
808 }
809
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530810 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
811 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
812
813 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
814 {
815
816 if (NULL == wiphy->bands[i])
817 {
818 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
819 __func__, i);
820 continue;
821 }
822
823 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
824 {
825 struct ieee80211_supported_band *band = wiphy->bands[i];
826
827 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
828 {
829 // Enable social channels for P2P
830 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
831 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
832 else
833 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
834 continue;
835 }
836 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
837 {
838 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
839 continue;
840 }
841 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700842 }
843 /*Initialise the supported cipher suite details*/
844 wiphy->cipher_suites = hdd_cipher_suites;
845 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
846
847 /*signal strength in mBm (100*dBm) */
848 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
849
850#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700851 wiphy->max_remain_on_channel_duration = 1000;
852#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700853
Rajesh Chauhan98a31f82014-01-06 20:15:25 -0800854 wiphy->n_vendor_commands = 0;
855 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
856 wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
857
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530858 EXIT();
859 return 0;
860}
861
862/* In this function we are registering wiphy. */
863int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
864{
865 ENTER();
866 /* Register our wiphy dev with cfg80211 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700867 if (0 > wiphy_register(wiphy))
868 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530869 /* print error */
Jeff Johnson295189b2012-06-20 16:38:30 -0700870 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
871 return -EIO;
872 }
873
874 EXIT();
875 return 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530876}
Jeff Johnson295189b2012-06-20 16:38:30 -0700877
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530878/* In this function we are updating channel list when,
879 regulatory domain is FCC and country code is US.
880 Here In FCC standard 5GHz UNII-1 Bands are indoor only.
881 As per FCC smart phone is not a indoor device.
882 GO should not opeate on indoor channels */
883void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy)
884{
885 int j;
886 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
887 tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE;
888 //Default counrtycode from NV at the time of wiphy initialization.
889 if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal,
890 &defaultCountryCode[0]))
891 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700892 hddLog(LOGE, FL("Failed to get default country code from NV"));
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530893 }
894 if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S'))
895 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530896 if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ])
897 {
898 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ );
899 return;
900 }
901 for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
902 {
903 struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ];
904 // Mark UNII -1 band channel as passive
905 if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq))
906 band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
907 }
908 }
909}
910
Jeff Johnson295189b2012-06-20 16:38:30 -0700911/* In this function we will do all post VOS start initialization.
912 In this function we will register for all frame in which supplicant
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530913 is interested.
Jeff Johnson295189b2012-06-20 16:38:30 -0700914*/
915void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
916{
Jeff Johnson295189b2012-06-20 16:38:30 -0700917 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
918 /* Register for all P2P action, public action etc frames */
919 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
920
Jeff Johnsone7245742012-09-05 17:12:55 -0700921 ENTER();
922
Jeff Johnson295189b2012-06-20 16:38:30 -0700923 /* Right now we are registering these frame when driver is getting
924 initialized. Once we will move to 2.6.37 kernel, in which we have
925 frame register ops, we will move this code as a part of that */
926 /* GAS Initial Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530927 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Jeff Johnson295189b2012-06-20 16:38:30 -0700928 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
929
930 /* GAS Initial Response */
931 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
932 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530933
Jeff Johnson295189b2012-06-20 16:38:30 -0700934 /* GAS Comeback Request */
935 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
936 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
937
938 /* GAS Comeback Response */
939 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
940 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
941
942 /* P2P Public Action */
943 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530944 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700945 P2P_PUBLIC_ACTION_FRAME_SIZE );
946
947 /* P2P Action */
948 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
949 (v_U8_t*)P2P_ACTION_FRAME,
950 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700951
Gopichand Nakkalae3d56e72013-04-21 23:33:32 +0530952 /* WNM BSS Transition Request frame */
953 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
954 (v_U8_t*)WNM_BSS_ACTION_FRAME,
955 WNM_BSS_ACTION_FRAME_SIZE );
956
Chet Lanctot186b5732013-03-18 10:26:30 -0700957#ifdef WLAN_FEATURE_11W
958 /* SA Query Response Action Frame */
959 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
960 (v_U8_t*)SA_QUERY_FRAME_RSP,
961 SA_QUERY_FRAME_RSP_SIZE );
962#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700963}
964
965void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
966{
Jeff Johnson295189b2012-06-20 16:38:30 -0700967 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
968 /* Register for all P2P action, public action etc frames */
969 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
970
Jeff Johnsone7245742012-09-05 17:12:55 -0700971 ENTER();
972
Jeff Johnson295189b2012-06-20 16:38:30 -0700973 /* Right now we are registering these frame when driver is getting
974 initialized. Once we will move to 2.6.37 kernel, in which we have
975 frame register ops, we will move this code as a part of that */
976 /* GAS Initial Request */
977
978 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
979 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
980
981 /* GAS Initial Response */
982 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
983 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530984
Jeff Johnson295189b2012-06-20 16:38:30 -0700985 /* GAS Comeback Request */
986 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
987 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
988
989 /* GAS Comeback Response */
990 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
991 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
992
993 /* P2P Public Action */
994 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530995 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700996 P2P_PUBLIC_ACTION_FRAME_SIZE );
997
998 /* P2P Action */
999 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
1000 (v_U8_t*)P2P_ACTION_FRAME,
1001 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -07001002
1003#ifdef WLAN_FEATURE_11W
1004 /* SA Query Response Action Frame */
1005 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
1006 (v_U8_t*)SA_QUERY_FRAME_RSP,
1007 SA_QUERY_FRAME_RSP_SIZE );
1008#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -07001009}
1010
1011#ifdef FEATURE_WLAN_WAPI
1012void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
1013 const u8 *mac_addr, u8 *key , int key_Len)
1014{
1015 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1016 tCsrRoamSetKey setKey;
1017 v_BOOL_t isConnected = TRUE;
1018 int status = 0;
1019 v_U32_t roamId= 0xFF;
1020 tANI_U8 *pKeyPtr = NULL;
1021 int n = 0;
1022
Arif Hussain6d2a3322013-11-17 19:50:10 -08001023 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001024 __func__,pAdapter->device_mode);
1025
Gopichand Nakkalae7480202013-02-11 15:24:22 +05301026 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -07001027 setKey.keyId = key_index; // Store Key ID
1028 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
1029 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
1030 setKey.paeRole = 0 ; // the PAE role
1031 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
1032 {
1033 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
1034 }
1035 else
1036 {
1037 isConnected = hdd_connIsConnected(pHddStaCtx);
1038 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
1039 }
1040 setKey.keyLength = key_Len;
1041 pKeyPtr = setKey.Key;
1042 memcpy( pKeyPtr, key, key_Len);
1043
Arif Hussain6d2a3322013-11-17 19:50:10 -08001044 hddLog(VOS_TRACE_LEVEL_INFO,"%s: WAPI KEY LENGTH:0x%04x",
Jeff Johnson295189b2012-06-20 16:38:30 -07001045 __func__, key_Len);
1046 for (n = 0 ; n < key_Len; n++)
1047 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
1048 __func__,n,setKey.Key[n]);
1049
1050 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
1051 if ( isConnected )
1052 {
1053 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
1054 pAdapter->sessionId, &setKey, &roamId );
1055 }
1056 if ( status != 0 )
1057 {
1058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1059 "[%4d] sme_RoamSetKey returned ERROR status= %d",
1060 __LINE__, status );
1061 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
1062 }
1063}
1064#endif /* FEATURE_WLAN_WAPI*/
1065
1066#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301067int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07001068 beacon_data_t **ppBeacon,
1069 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001070#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301071int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001072 beacon_data_t **ppBeacon,
1073 struct cfg80211_beacon_data *params,
1074 int dtim_period)
1075#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301076{
Jeff Johnson295189b2012-06-20 16:38:30 -07001077 int size;
1078 beacon_data_t *beacon = NULL;
1079 beacon_data_t *old = NULL;
1080 int head_len,tail_len;
1081
Jeff Johnsone7245742012-09-05 17:12:55 -07001082 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001083 if (params->head && !params->head_len)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301084 {
1085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1086 FL("head_len is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001087 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301088 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001089
1090 old = pAdapter->sessionCtx.ap.beacon;
1091
1092 if (!params->head && !old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301093 {
1094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1095 FL("session(%d) old and new heads points to NULL"),
1096 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001097 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301098 }
1099
1100 if (params->tail && !params->tail_len)
1101 {
1102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1103 FL("tail_len is zero but tail is not NULL"));
1104 return -EINVAL;
1105 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001106
Jeff Johnson295189b2012-06-20 16:38:30 -07001107#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
1108 /* Kernel 3.0 is not updating dtim_period for set beacon */
1109 if (!params->dtim_period)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301110 {
1111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1112 FL("dtim period is 0"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001113 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301114 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001115#endif
1116
1117 if(params->head)
1118 head_len = params->head_len;
1119 else
1120 head_len = old->head_len;
1121
1122 if(params->tail || !old)
1123 tail_len = params->tail_len;
1124 else
1125 tail_len = old->tail_len;
1126
1127 size = sizeof(beacon_data_t) + head_len + tail_len;
1128
1129 beacon = kzalloc(size, GFP_KERNEL);
1130
1131 if( beacon == NULL )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301132 {
1133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1134 FL("Mem allocation for beacon failed"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001135 return -ENOMEM;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301136 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001137
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001138#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001139 if(params->dtim_period || !old )
1140 beacon->dtim_period = params->dtim_period;
1141 else
1142 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001143#else
1144 if(dtim_period || !old )
1145 beacon->dtim_period = dtim_period;
1146 else
1147 beacon->dtim_period = old->dtim_period;
1148#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301149
Jeff Johnson295189b2012-06-20 16:38:30 -07001150 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
1151 beacon->tail = beacon->head + head_len;
1152 beacon->head_len = head_len;
1153 beacon->tail_len = tail_len;
1154
1155 if(params->head) {
1156 memcpy (beacon->head,params->head,beacon->head_len);
1157 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301158 else {
Jeff Johnson295189b2012-06-20 16:38:30 -07001159 if(old)
1160 memcpy (beacon->head,old->head,beacon->head_len);
1161 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301162
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 if(params->tail) {
1164 memcpy (beacon->tail,params->tail,beacon->tail_len);
1165 }
1166 else {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301167 if(old)
Jeff Johnson295189b2012-06-20 16:38:30 -07001168 memcpy (beacon->tail,old->tail,beacon->tail_len);
1169 }
1170
1171 *ppBeacon = beacon;
1172
1173 kfree(old);
1174
1175 return 0;
1176
1177}
Jeff Johnson295189b2012-06-20 16:38:30 -07001178
1179v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
1180{
1181 int left = length;
1182 v_U8_t *ptr = pIes;
1183 v_U8_t elem_id,elem_len;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301184
Jeff Johnson295189b2012-06-20 16:38:30 -07001185 while(left >= 2)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301186 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001187 elem_id = ptr[0];
1188 elem_len = ptr[1];
1189 left -= 2;
1190 if(elem_len > left)
1191 {
1192 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001193 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -07001194 eid,elem_len,left);
1195 return NULL;
1196 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301197 if (elem_id == eid)
Jeff Johnson295189b2012-06-20 16:38:30 -07001198 {
1199 return ptr;
1200 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301201
Jeff Johnson295189b2012-06-20 16:38:30 -07001202 left -= elem_len;
1203 ptr += (elem_len + 2);
1204 }
1205 return NULL;
1206}
1207
Jeff Johnson295189b2012-06-20 16:38:30 -07001208/* Check if rate is 11g rate or not */
1209static int wlan_hdd_rate_is_11g(u8 rate)
1210{
Sanjay Devnani28322e22013-06-21 16:13:40 -07001211 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001212 u8 i;
1213 for (i = 0; i < 8; i++)
1214 {
1215 if(rate == gRateArray[i])
1216 return TRUE;
1217 }
1218 return FALSE;
1219}
1220
1221/* Check for 11g rate and set proper 11g only mode */
1222static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1223 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1224{
1225 u8 i, num_rates = pIe[0];
1226
1227 pIe += 1;
1228 for ( i = 0; i < num_rates; i++)
1229 {
1230 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1231 {
1232 /* If rate set have 11g rate than change the mode to 11G */
1233 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1234 if (pIe[i] & BASIC_RATE_MASK)
1235 {
1236 /* If we have 11g rate as basic rate, it means mode
1237 is 11g only mode.
1238 */
1239 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1240 *pCheckRatesfor11g = FALSE;
1241 }
1242 }
1243 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1244 {
1245 *require_ht = TRUE;
1246 }
1247 }
1248 return;
1249}
1250
1251static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1252{
1253 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1254 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1255 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1256 u8 checkRatesfor11g = TRUE;
1257 u8 require_ht = FALSE;
1258 u8 *pIe=NULL;
1259
1260 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1261
1262 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1263 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1264 if (pIe != NULL)
1265 {
1266 pIe += 1;
1267 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1268 &pConfig->SapHw_mode);
1269 }
1270
1271 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1272 WLAN_EID_EXT_SUPP_RATES);
1273 if (pIe != NULL)
1274 {
1275
1276 pIe += 1;
1277 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1278 &pConfig->SapHw_mode);
1279 }
1280
1281 if( pConfig->channel > 14 )
1282 {
1283 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1284 }
1285
1286 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1287 WLAN_EID_HT_CAPABILITY);
1288
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301289 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001290 {
1291 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1292 if(require_ht)
1293 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1294 }
1295}
1296
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301297static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1298 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1299{
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001300 v_U16_t ielen = 0;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301301 v_U8_t *pIe = NULL;
1302 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1303
1304 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1305 pBeacon->tail, pBeacon->tail_len);
1306
1307 if (pIe)
1308 {
1309 ielen = pIe[1] + 2;
1310 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1311 {
1312 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1313 }
1314 else
1315 {
1316 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1317 return -EINVAL;
1318 }
1319 *total_ielen += ielen;
1320 }
1321 return 0;
1322}
1323
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001324static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter,
1325 v_U8_t *genie, v_U8_t *total_ielen)
1326{
1327 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1328 int left = pBeacon->tail_len;
1329 v_U8_t *ptr = pBeacon->tail;
1330 v_U8_t elem_id, elem_len;
1331 v_U16_t ielen = 0;
1332
1333 if ( NULL == ptr || 0 == left )
1334 return;
1335
1336 while (left >= 2)
1337 {
1338 elem_id = ptr[0];
1339 elem_len = ptr[1];
1340 left -= 2;
1341 if (elem_len > left)
1342 {
1343 hddLog( VOS_TRACE_LEVEL_ERROR,
1344 "****Invalid IEs eid = %d elem_len=%d left=%d*****",
1345 elem_id, elem_len, left);
1346 return;
1347 }
1348 if (IE_EID_VENDOR == elem_id)
1349 {
1350 /* skipping the VSIE's which we don't want to include or
1351 * it will be included by existing code
1352 */
1353 if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) &&
1354#ifdef WLAN_FEATURE_WFD
1355 (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) &&
1356#endif
1357 (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1358 (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1359 (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) &&
1360 (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1361 (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0))
1362 {
1363 ielen = ptr[1] + 2;
1364 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1365 {
1366 vos_mem_copy(&genie[*total_ielen], ptr, ielen);
1367 *total_ielen += ielen;
1368 }
1369 else
1370 {
1371 hddLog( VOS_TRACE_LEVEL_ERROR,
1372 "IE Length is too big "
1373 "IEs eid=%d elem_len=%d total_ie_lent=%d",
1374 elem_id, elem_len, *total_ielen);
1375 }
1376 }
1377 }
1378
1379 left -= elem_len;
1380 ptr += (elem_len + 2);
1381 }
1382 return;
1383}
1384
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001385#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001386static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1387 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001388#else
1389static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1390 struct cfg80211_beacon_data *params)
1391#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001392{
1393 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301394 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001395 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001396 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001397
1398 genie = vos_mem_malloc(MAX_GENIE_LEN);
1399
1400 if(genie == NULL) {
1401
1402 return -ENOMEM;
1403 }
1404
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301405 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1406 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001407 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301408 hddLog(LOGE,
1409 FL("Adding WPS IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301410 ret = -EINVAL;
1411 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001412 }
1413
1414#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301415 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1416 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1417 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301418 hddLog(LOGE,
1419 FL("Adding WFD IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301420 ret = -EINVAL;
1421 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001422 }
1423#endif
1424
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301425 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1426 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001427 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301428 hddLog(LOGE,
1429 FL("Adding P2P IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301430 ret = -EINVAL;
1431 goto done;
1432 }
1433
1434 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1435 {
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001436 wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen);
Jeff Johnson295189b2012-06-20 16:38:30 -07001437 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001438
1439 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1440 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1441 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1442 {
1443 hddLog(LOGE,
1444 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001445 ret = -EINVAL;
1446 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001447 }
1448
1449 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1450 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1451 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1452 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1453 ==eHAL_STATUS_FAILURE)
1454 {
1455 hddLog(LOGE,
1456 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001457 ret = -EINVAL;
1458 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001459 }
1460
1461 // Added for ProResp IE
1462 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1463 {
1464 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1465 u8 probe_rsp_ie_len[3] = {0};
1466 u8 counter = 0;
1467 /* Check Probe Resp Length if it is greater then 255 then Store
1468 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1469 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1470 Store More then 255 bytes into One Variable.
1471 */
1472 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1473 {
1474 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1475 {
1476 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1477 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1478 }
1479 else
1480 {
1481 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1482 rem_probe_resp_ie_len = 0;
1483 }
1484 }
1485
1486 rem_probe_resp_ie_len = 0;
1487
1488 if (probe_rsp_ie_len[0] > 0)
1489 {
1490 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1491 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1492 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1493 probe_rsp_ie_len[0], NULL,
1494 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1495 {
1496 hddLog(LOGE,
1497 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001498 ret = -EINVAL;
1499 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001500 }
1501 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1502 }
1503
1504 if (probe_rsp_ie_len[1] > 0)
1505 {
1506 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1507 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1508 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1509 probe_rsp_ie_len[1], NULL,
1510 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1511 {
1512 hddLog(LOGE,
1513 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001514 ret = -EINVAL;
1515 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001516 }
1517 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1518 }
1519
1520 if (probe_rsp_ie_len[2] > 0)
1521 {
1522 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1523 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1524 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1525 probe_rsp_ie_len[2], NULL,
1526 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1527 {
1528 hddLog(LOGE,
1529 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001530 ret = -EINVAL;
1531 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001532 }
1533 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1534 }
1535
1536 if (probe_rsp_ie_len[1] == 0 )
1537 {
1538 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1539 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1540 eANI_BOOLEAN_FALSE) )
1541 {
1542 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001543 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001544 }
1545 }
1546
1547 if (probe_rsp_ie_len[2] == 0 )
1548 {
1549 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1550 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1551 eANI_BOOLEAN_FALSE) )
1552 {
1553 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001554 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001555 }
1556 }
1557
1558 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1559 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1560 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1561 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1562 == eHAL_STATUS_FAILURE)
1563 {
1564 hddLog(LOGE,
1565 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001566 ret = -EINVAL;
1567 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001568 }
1569 }
1570 else
1571 {
1572 // Reset WNI_CFG_PROBE_RSP Flags
1573 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1574
1575 hddLog(VOS_TRACE_LEVEL_INFO,
1576 "%s: No Probe Response IE received in set beacon",
1577 __func__);
1578 }
1579
1580 // Added for AssocResp IE
1581 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1582 {
1583 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1584 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1585 params->assocresp_ies_len, NULL,
1586 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1587 {
1588 hddLog(LOGE,
1589 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001590 ret = -EINVAL;
1591 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 }
1593
1594 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1595 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1596 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1597 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1598 == eHAL_STATUS_FAILURE)
1599 {
1600 hddLog(LOGE,
1601 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001602 ret = -EINVAL;
1603 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001604 }
1605 }
1606 else
1607 {
1608 hddLog(VOS_TRACE_LEVEL_INFO,
1609 "%s: No Assoc Response IE received in set beacon",
1610 __func__);
1611
1612 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1613 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1614 eANI_BOOLEAN_FALSE) )
1615 {
1616 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001617 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001618 }
1619 }
1620
Jeff Johnsone7245742012-09-05 17:12:55 -07001621done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001622 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301623 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001624}
Jeff Johnson295189b2012-06-20 16:38:30 -07001625
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301626/*
Jeff Johnson295189b2012-06-20 16:38:30 -07001627 * FUNCTION: wlan_hdd_validate_operation_channel
1628 * called by wlan_hdd_cfg80211_start_bss() and
1629 * wlan_hdd_cfg80211_set_channel()
1630 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301631 * channel list.
1632 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001633VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001634{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301635
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 v_U32_t num_ch = 0;
1637 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1638 u32 indx = 0;
1639 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301640 v_U8_t fValidChannel = FALSE, count = 0;
1641 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301642
Jeff Johnson295189b2012-06-20 16:38:30 -07001643 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1644
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301645 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001646 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301647 /* Validate the channel */
1648 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001649 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301650 if ( channel == rfChannels[count].channelNum )
1651 {
1652 fValidChannel = TRUE;
1653 break;
1654 }
1655 }
1656 if (fValidChannel != TRUE)
1657 {
1658 hddLog(VOS_TRACE_LEVEL_ERROR,
1659 "%s: Invalid Channel [%d]", __func__, channel);
1660 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 }
1662 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301663 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001664 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301665 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1666 valid_ch, &num_ch))
1667 {
1668 hddLog(VOS_TRACE_LEVEL_ERROR,
1669 "%s: failed to get valid channel list", __func__);
1670 return VOS_STATUS_E_FAILURE;
1671 }
1672 for (indx = 0; indx < num_ch; indx++)
1673 {
1674 if (channel == valid_ch[indx])
1675 {
1676 break;
1677 }
1678 }
1679
1680 if (indx >= num_ch)
1681 {
1682 hddLog(VOS_TRACE_LEVEL_ERROR,
1683 "%s: Invalid Channel [%d]", __func__, channel);
1684 return VOS_STATUS_E_FAILURE;
1685 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001686 }
1687 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301688
Jeff Johnson295189b2012-06-20 16:38:30 -07001689}
1690
Viral Modi3a32cc52013-02-08 11:14:52 -08001691/**
1692 * FUNCTION: wlan_hdd_cfg80211_set_channel
1693 * This function is used to set the channel number
1694 */
1695static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1696 struct ieee80211_channel *chan,
1697 enum nl80211_channel_type channel_type
1698 )
1699{
1700 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001701 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001702 hdd_adapter_t *pAdapter = NULL;
1703 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301704 hdd_context_t *pHddCtx;
1705 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001706
1707 ENTER();
1708
1709 if( NULL == dev )
1710 {
1711 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001712 "%s: Called with dev = NULL.", __func__);
Viral Modi3a32cc52013-02-08 11:14:52 -08001713 return -ENODEV;
1714 }
1715 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1716
1717 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001718 "%s: device_mode = %d freq = %d", __func__,
Viral Modi3a32cc52013-02-08 11:14:52 -08001719 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301720
1721 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1722 status = wlan_hdd_validate_context(pHddCtx);
1723
1724 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08001725 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301726 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1727 "%s: HDD context is not valid", __func__);
1728 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001729 }
1730
1731 /*
1732 * Do freq to chan conversion
1733 * TODO: for 11a
1734 */
1735
1736 channel = ieee80211_frequency_to_channel(freq);
1737
1738 /* Check freq range */
1739 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1740 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1741 {
1742 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001743 "%s: Channel [%d] is outside valid range from %d to %d",
Viral Modi3a32cc52013-02-08 11:14:52 -08001744 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1745 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1746 return -EINVAL;
1747 }
1748
1749 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1750
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301751 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1752 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001753 {
1754 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1755 {
1756 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001757 "%s: Invalid Channel [%d]", __func__, channel);
Viral Modi3a32cc52013-02-08 11:14:52 -08001758 return -EINVAL;
1759 }
1760 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1761 "%s: set channel to [%d] for device mode =%d",
1762 __func__, channel,pAdapter->device_mode);
1763 }
1764 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001765 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001766 )
1767 {
1768 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1769 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1770 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1771
1772 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1773 {
1774 /* Link is up then return cant set channel*/
1775 hddLog( VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001776 "%s: IBSS Associated, can't set the channel", __func__);
Viral Modi3a32cc52013-02-08 11:14:52 -08001777 return -EINVAL;
1778 }
1779
1780 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1781 pHddStaCtx->conn_info.operationChannel = channel;
1782 pRoamProfile->ChannelInfo.ChannelList =
1783 &pHddStaCtx->conn_info.operationChannel;
1784 }
1785 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001786 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001787 )
1788 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301789 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1790 {
1791 if(VOS_STATUS_SUCCESS !=
1792 wlan_hdd_validate_operation_channel(pAdapter,channel))
1793 {
1794 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001795 "%s: Invalid Channel [%d]", __func__, channel);
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301796 return -EINVAL;
1797 }
1798 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1799 }
1800 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001801 {
1802 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1803
1804 /* If auto channel selection is configured as enable/ 1 then ignore
1805 channel set by supplicant
1806 */
1807 if ( cfg_param->apAutoChannelSelection )
1808 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301809 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1810 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001811 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1812 "%s: set channel to auto channel (0) for device mode =%d",
1813 __func__, pAdapter->device_mode);
1814 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301815 else
1816 {
1817 if(VOS_STATUS_SUCCESS !=
1818 wlan_hdd_validate_operation_channel(pAdapter,channel))
1819 {
1820 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001821 "%s: Invalid Channel [%d]", __func__, channel);
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301822 return -EINVAL;
1823 }
1824 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1825 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001826 }
1827 }
1828 else
1829 {
1830 hddLog(VOS_TRACE_LEVEL_FATAL,
1831 "%s: Invalid device mode failed to set valid channel", __func__);
1832 return -EINVAL;
1833 }
1834 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301835 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001836}
1837
Jeff Johnson295189b2012-06-20 16:38:30 -07001838#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1839static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1840 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001841#else
1842static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1843 struct cfg80211_beacon_data *params,
1844 const u8 *ssid, size_t ssid_len,
1845 enum nl80211_hidden_ssid hidden_ssid)
1846#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001847{
1848 tsap_Config_t *pConfig;
1849 beacon_data_t *pBeacon = NULL;
1850 struct ieee80211_mgmt *pMgmt_frame;
1851 v_U8_t *pIe=NULL;
1852 v_U16_t capab_info;
1853 eCsrAuthType RSNAuthType;
1854 eCsrEncryptionType RSNEncryptType;
1855 eCsrEncryptionType mcRSNEncryptType;
1856 int status = VOS_STATUS_SUCCESS;
1857 tpWLAN_SAPEventCB pSapEventCallback;
1858 hdd_hostapd_state_t *pHostapdState;
1859 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1860 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301861 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001862 struct qc_mac_acl_entry *acl_entry = NULL;
1863 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001864 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001865
1866 ENTER();
1867
1868 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1869
1870 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1871
1872 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1873
1874 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1875
1876 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1877
1878 //channel is already set in the set_channel Call back
1879 //pConfig->channel = pCommitConfig->channel;
1880
1881 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301882 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07001883 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1884
1885 pConfig->dtim_period = pBeacon->dtim_period;
1886
Arif Hussain6d2a3322013-11-17 19:50:10 -08001887 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***",
Jeff Johnson295189b2012-06-20 16:38:30 -07001888 pConfig->dtim_period);
1889
1890
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001891 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001892 {
1893 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001894 WLAN_EID_COUNTRY);
Kiet Lam083504c2013-11-25 14:17:45 +05301895 if(memcmp(pHddCtx->cfg_ini->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0)
1896 {
1897 tANI_BOOLEAN restartNeeded;
1898 pConfig->ieee80211d = 1;
1899 vos_mem_copy(pConfig->countryCode, pHddCtx->cfg_ini->apCntryCode, 3);
1900 sme_setRegInfo(hHal, pConfig->countryCode);
1901 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1902 }
1903 else if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001904 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001905 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001906 pConfig->ieee80211d = 1;
1907 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1908 sme_setRegInfo(hHal, pConfig->countryCode);
1909 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001910 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001911 else
1912 {
1913 pConfig->ieee80211d = 0;
1914 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301915 /*
1916 * If auto channel is configured i.e. channel is 0,
1917 * so skip channel validation.
1918 */
1919 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1920 {
1921 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1922 {
1923 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001924 "%s: Invalid Channel [%d]", __func__, pConfig->channel);
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301925 return -EINVAL;
1926 }
1927 }
1928 else
1929 {
1930 if(1 != pHddCtx->is_dynamic_channel_range_set)
1931 {
1932 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1933 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1934 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1935 }
1936 pHddCtx->is_dynamic_channel_range_set = 0;
1937 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001938 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001939 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001940 {
1941 pConfig->ieee80211d = 0;
1942 }
1943 pConfig->authType = eSAP_AUTO_SWITCH;
1944
1945 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301946
1947 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07001948 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1949
1950 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1951
1952 /*Set wps station to configured*/
1953 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1954
1955 if(pIe)
1956 {
1957 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1958 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08001959 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***");
Jeff Johnson295189b2012-06-20 16:38:30 -07001960 return -EINVAL;
1961 }
1962 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1963 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001964 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001965 /* Check 15 bit of WPS IE as it contain information for wps state
1966 * WPS state
1967 */
1968 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1969 {
1970 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1971 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1972 {
1973 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1974 }
1975 }
1976 }
1977 else
1978 {
1979 pConfig->wps_state = SAP_WPS_DISABLED;
1980 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301981 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07001982
1983 pConfig->RSNWPAReqIELength = 0;
1984 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301985 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001986 WLAN_EID_RSN);
1987 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301988 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001989 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1990 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1991 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301992 /* The actual processing may eventually be more extensive than
1993 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07001994 * by the app.
1995 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301996 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001997 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1998 &RSNEncryptType,
1999 &mcRSNEncryptType,
2000 &RSNAuthType,
2001 pConfig->pRSNWPAReqIE[1]+2,
2002 pConfig->pRSNWPAReqIE );
2003
2004 if( VOS_STATUS_SUCCESS == status )
2005 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302006 /* Now copy over all the security attributes you have
2007 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07002008 * */
2009 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
2010 pConfig->mcRSNEncryptType = mcRSNEncryptType;
2011 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
2012 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302013 hddLog( LOG1, FL("CSR AuthType = %d, "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002014 "EncryptionType = %d mcEncryptionType = %d"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002015 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
2016 }
2017 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302018
Jeff Johnson295189b2012-06-20 16:38:30 -07002019 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2020 pBeacon->tail, pBeacon->tail_len);
2021
2022 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
2023 {
2024 if (pConfig->pRSNWPAReqIE)
2025 {
2026 /*Mixed mode WPA/WPA2*/
2027 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
2028 pConfig->RSNWPAReqIELength += pIe[1] + 2;
2029 }
2030 else
2031 {
2032 pConfig->RSNWPAReqIELength = pIe[1] + 2;
2033 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
2034 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302035 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07002036 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
2037 &RSNEncryptType,
2038 &mcRSNEncryptType,
2039 &RSNAuthType,
2040 pConfig->pRSNWPAReqIE[1]+2,
2041 pConfig->pRSNWPAReqIE );
2042
2043 if( VOS_STATUS_SUCCESS == status )
2044 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302045 /* Now copy over all the security attributes you have
2046 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07002047 * */
2048 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
2049 pConfig->mcRSNEncryptType = mcRSNEncryptType;
2050 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
2051 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302052 hddLog( LOG1, FL("CSR AuthType = %d, "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002053 "EncryptionType = %d mcEncryptionType = %d"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002054 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
2055 }
2056 }
2057 }
2058
Jeff Johnson4416a782013-03-25 14:17:50 -07002059 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
2060 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
2061 return -EINVAL;
2062 }
2063
Jeff Johnson295189b2012-06-20 16:38:30 -07002064 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
2065
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002066#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002067 if (params->ssid != NULL)
2068 {
2069 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
2070 pConfig->SSIDinfo.ssid.length = params->ssid_len;
2071 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2072 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
2073 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002074#else
2075 if (ssid != NULL)
2076 {
2077 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
2078 pConfig->SSIDinfo.ssid.length = ssid_len;
2079 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2080 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
2081 }
2082#endif
2083
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302084 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07002085 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302086
Jeff Johnson295189b2012-06-20 16:38:30 -07002087 /* default value */
2088 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
2089 pConfig->num_accept_mac = 0;
2090 pConfig->num_deny_mac = 0;
2091
2092 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2093 pBeacon->tail, pBeacon->tail_len);
2094
2095 /* pIe for black list is following form:
2096 type : 1 byte
2097 length : 1 byte
2098 OUI : 4 bytes
2099 acl type : 1 byte
2100 no of mac addr in black list: 1 byte
2101 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302102 */
2103 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002104 {
2105 pConfig->SapMacaddr_acl = pIe[6];
2106 pConfig->num_deny_mac = pIe[7];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002107 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002108 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302109 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
2110 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002111 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2112 for (i = 0; i < pConfig->num_deny_mac; i++)
2113 {
2114 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2115 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302116 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002117 }
2118 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2119 pBeacon->tail, pBeacon->tail_len);
2120
2121 /* pIe for white list is following form:
2122 type : 1 byte
2123 length : 1 byte
2124 OUI : 4 bytes
2125 acl type : 1 byte
2126 no of mac addr in white list: 1 byte
2127 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302128 */
2129 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002130 {
2131 pConfig->SapMacaddr_acl = pIe[6];
2132 pConfig->num_accept_mac = pIe[7];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002133 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002134 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302135 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
2136 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002137 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2138 for (i = 0; i < pConfig->num_accept_mac; i++)
2139 {
2140 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2141 acl_entry++;
2142 }
2143 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302144
Jeff Johnson295189b2012-06-20 16:38:30 -07002145 wlan_hdd_set_sapHwmode(pHostapdAdapter);
2146
Jeff Johnsone7245742012-09-05 17:12:55 -07002147#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002148 /* Overwrite the hostapd setting for HW mode only for 11ac.
Kiet Lam0f320422013-11-21 19:29:17 +05302149 * This is valid only if mode is set to 11n in hostapd, either AUTO or
2150 * 11ac in .ini and 11ac is supported by both host and firmware.
2151 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode)
2152 */
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002153 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
2154 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302155 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002156 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
Kiet Lam0f320422013-11-21 19:29:17 +05302157 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) &&
2158 (sme_IsFeatureSupportedByDriver(DOT11AC)) && (sme_IsFeatureSupportedByFW(DOT11AC)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07002159 {
2160 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Ravi Joshi83bfaa12013-05-28 22:12:08 -07002161
2162 /* Disable VHT support in 2.4 GHz band */
2163 if (pConfig->channel <= 14 &&
2164 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->enableVhtFor24GHzBand == FALSE)
2165 {
2166 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
2167 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002168 }
2169#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302170
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07002171 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
2172 {
2173 sme_SelectCBMode(hHal,
2174 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
2175 pConfig->channel);
2176 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002177 // ht_capab is not what the name conveys,this is used for protection bitmap
2178 pConfig->ht_capab =
2179 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
2180
2181 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
2182 {
2183 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
2184 return -EINVAL;
2185 }
2186
2187 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302188 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07002189 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
2190 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302191 pConfig->obssProtEnabled =
2192 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07002193
Arif Hussain6d2a3322013-11-17 19:50:10 -08002194 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR),
Jeff Johnson295189b2012-06-20 16:38:30 -07002195 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Arif Hussain6d2a3322013-11-17 19:50:10 -08002196 hddLog(LOGW,FL("ssid =%s, beaconint=%d, channel=%d"),
2197 pConfig->SSIDinfo.ssid.ssId, (int)pConfig->beacon_int,
2198 (int)pConfig->channel);
2199 hddLog(LOGW,FL("hw_mode=%x, privacy=%d, authType=%d"),
2200 pConfig->SapHw_mode, pConfig->privacy,
2201 pConfig->authType);
2202 hddLog(LOGW,FL("RSN/WPALen=%d, Uapsd = %d"),
2203 (int)pConfig->RSNWPAReqIELength, pConfig->UapsdEnable);
2204 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d"),
2205 pConfig->protEnabled, pConfig->obssProtEnabled);
Jeff Johnson295189b2012-06-20 16:38:30 -07002206
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302207 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002208 {
2209 //Bss already started. just return.
2210 //TODO Probably it should update some beacon params.
2211 hddLog( LOGE, "Bss Already started...Ignore the request");
2212 EXIT();
2213 return 0;
2214 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302215
Jeff Johnson295189b2012-06-20 16:38:30 -07002216 pConfig->persona = pHostapdAdapter->device_mode;
2217
2218 pSapEventCallback = hdd_hostapd_SAPEventCB;
2219 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2220 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2221 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08002222 hddLog(LOGE,FL("SAP Start Bss fail"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002223 return -EINVAL;
2224 }
2225
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302226 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002227 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2228
2229 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302230
Jeff Johnson295189b2012-06-20 16:38:30 -07002231 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302232 {
2233 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002234 ("ERROR: HDD vos wait for single_event failed!!"));
Tushnim Bhattacharyyaad37df12013-10-02 12:01:33 -07002235 smeGetCommandQStatus(hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07002236 VOS_ASSERT(0);
2237 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302238
Jeff Johnson295189b2012-06-20 16:38:30 -07002239 //Succesfully started Bss update the state bit.
2240 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2241
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002242#ifdef WLAN_FEATURE_P2P_DEBUG
2243 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2244 {
2245 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2246 {
2247 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2248 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002249 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002250 }
2251 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2252 {
2253 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2254 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002255 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002256 }
2257 }
2258#endif
2259
Jeff Johnson295189b2012-06-20 16:38:30 -07002260 pHostapdState->bCommit = TRUE;
2261 EXIT();
2262
2263 return 0;
2264}
2265
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002266#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302267static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2268 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07002269 struct beacon_parameters *params)
2270{
2271 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302272 hdd_context_t *pHddCtx;
2273 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002274
2275 ENTER();
2276
Arif Hussain6d2a3322013-11-17 19:50:10 -08002277 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d",pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002278
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302279 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2280 status = wlan_hdd_validate_context(pHddCtx);
2281
2282 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002283 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2285 "%s: HDD context is not valid", __func__);
2286 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002287 }
2288
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302289 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002290 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002291 )
2292 {
2293 beacon_data_t *old,*new;
2294
2295 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302296
Jeff Johnson295189b2012-06-20 16:38:30 -07002297 if (old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302298 {
2299 hddLog(VOS_TRACE_LEVEL_WARN,
2300 FL("already beacon info added to session(%d)"),
2301 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002302 return -EALREADY;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302303 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002304
2305 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2306
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302307 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07002308 {
2309 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002310 "%s:Error!!! Allocating the new beacon",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002311 return -EINVAL;
2312 }
2313
2314 pAdapter->sessionCtx.ap.beacon = new;
2315
2316 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2317 }
2318
2319 EXIT();
2320 return status;
2321}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302322
2323static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07002324 struct net_device *dev,
2325 struct beacon_parameters *params)
2326{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302327 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302328 hdd_context_t *pHddCtx;
2329 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002330
2331 ENTER();
2332
Arif Hussain6d2a3322013-11-17 19:50:10 -08002333 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002334 __func__,pAdapter->device_mode);
2335
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302336 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2337 status = wlan_hdd_validate_context(pHddCtx);
2338
2339 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002340 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2342 "%s: HDD context is not valid", __func__);
2343 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002344 }
2345
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302346 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002347 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302348 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002349 {
2350 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302351
Jeff Johnson295189b2012-06-20 16:38:30 -07002352 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302353
Jeff Johnson295189b2012-06-20 16:38:30 -07002354 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302355 {
2356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2357 FL("session(%d) old and new heads points to NULL"),
2358 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002359 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302360 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002361
2362 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2363
2364 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302365 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002366 "%s: Error!!! Allocating the new beacon",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002367 return -EINVAL;
2368 }
2369
2370 pAdapter->sessionCtx.ap.beacon = new;
2371
2372 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2373 }
2374
2375 EXIT();
2376 return status;
2377}
2378
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002379#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2380
2381#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002382static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2383 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002384#else
2385static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2386 struct net_device *dev)
2387#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002388{
2389 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002390 hdd_context_t *pHddCtx = NULL;
2391 hdd_scaninfo_t *pScanInfo = NULL;
2392 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302393 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002394
2395 ENTER();
2396
2397 if (NULL == pAdapter)
2398 {
2399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002400 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002401 return -ENODEV;
2402 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002403
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302404 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2405 status = wlan_hdd_validate_context(pHddCtx);
2406
2407 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002408 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2410 "%s: HDD context is not valid", __func__);
2411 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07002412 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002413
2414 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2415 if (NULL == staAdapter)
2416 {
2417 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2418 if (NULL == staAdapter)
2419 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2421 "%s: HDD adapter context for STA/P2P-CLI is Null",
2422 __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002423 }
2424 }
2425
2426 pScanInfo = &pHddCtx->scan_info;
2427
Arif Hussain6d2a3322013-11-17 19:50:10 -08002428 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002429 __func__,pAdapter->device_mode);
2430
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002431 if ((pScanInfo != NULL) && pScanInfo->mScanPending && staAdapter)
Jeff Johnsone7245742012-09-05 17:12:55 -07002432 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302433 long ret;
2434
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002435 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05302436 hdd_abort_mac_scan(staAdapter->pHddCtx, pAdapter->sessionId);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302437 ret = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002438 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002439 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302440 if (ret <= 0)
Jeff Johnsone7245742012-09-05 17:12:55 -07002441 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302443 FL("Timeout occurred while waiting for abortscan %ld"),
2444 ret);
Yue Ma4f55ef32014-01-23 16:45:33 -08002445
2446 if (pHddCtx->isLogpInProgress)
2447 {
2448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2449 "%s: LOGP in Progress. Ignore!!!", __func__);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302450
2451 VOS_ASSERT(pScanInfo->mScanPending);
Yue Ma4f55ef32014-01-23 16:45:33 -08002452 return -EAGAIN;
2453 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002454 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07002455 }
2456 }
2457
Arun Kumar Khandavallia3bd8002014-01-17 16:21:19 +05302458 hdd_hostapd_stop(dev);
2459
Jeff Johnson295189b2012-06-20 16:38:30 -07002460 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002461 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002462 )
2463 {
2464 beacon_data_t *old;
2465
2466 old = pAdapter->sessionCtx.ap.beacon;
2467
2468 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302469 {
2470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2471 FL("session(%d) beacon data points to NULL"),
2472 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002473 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302474 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002475
Jeff Johnson295189b2012-06-20 16:38:30 -07002476 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002477
2478 mutex_lock(&pHddCtx->sap_lock);
2479 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2480 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002481 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002482 {
2483 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2484
2485 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2486
2487 if (!VOS_IS_STATUS_SUCCESS(status))
2488 {
2489 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002490 ("ERROR: HDD vos wait for single_event failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002491 VOS_ASSERT(0);
2492 }
2493 }
2494 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2495 }
2496 mutex_unlock(&pHddCtx->sap_lock);
2497
2498 if(status != VOS_STATUS_SUCCESS)
2499 {
2500 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002501 "%s:Error!!! Stopping the BSS",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002502 return -EINVAL;
2503 }
2504
Jeff Johnson4416a782013-03-25 14:17:50 -07002505 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002506 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2507 ==eHAL_STATUS_FAILURE)
2508 {
2509 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002510 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07002511 }
2512
Jeff Johnson4416a782013-03-25 14:17:50 -07002513 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002514 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2515 eANI_BOOLEAN_FALSE) )
2516 {
2517 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002518 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07002519 }
2520
2521 // Reset WNI_CFG_PROBE_RSP Flags
2522 wlan_hdd_reset_prob_rspies(pAdapter);
2523
2524 pAdapter->sessionCtx.ap.beacon = NULL;
2525 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002526#ifdef WLAN_FEATURE_P2P_DEBUG
2527 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2528 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2529 {
2530 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2531 "GO got removed");
2532 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2533 }
2534#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002535 }
2536 EXIT();
2537 return status;
2538}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002539
2540#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2541
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302542static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2543 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002544 struct cfg80211_ap_settings *params)
2545{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302546 hdd_adapter_t *pAdapter;
2547 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302548 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002549
2550 ENTER();
2551
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302552 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002553 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302555 "%s: Device is Null", __func__);
2556 return -ENODEV;
2557 }
2558
2559 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2560 if (NULL == pAdapter)
2561 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302563 "%s: HDD adapter is Null", __func__);
2564 return -ENODEV;
2565 }
2566
2567 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2568 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302570 "%s: HDD adapter magic is invalid", __func__);
2571 return -ENODEV;
2572 }
2573
2574 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302575 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302576
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302577 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302578 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2580 "%s: HDD context is not valid", __func__);
2581 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302582 }
2583
2584 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2585 __func__, pAdapter->device_mode);
2586
2587 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002588 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002589 )
2590 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302591 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002592
2593 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302594
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002595 if (old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302596 {
2597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2598 FL("already beacon info added to session(%d)"),
2599 pAdapter->sessionId);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002600 return -EALREADY;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302601 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002602
2603 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2604
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302605 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002606 {
2607 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302608 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002609 return -EINVAL;
2610 }
2611 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002612#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07002613 wlan_hdd_cfg80211_set_channel(wiphy, dev,
2614#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2615 params->channel, params->channel_type);
2616#else
2617 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
2618#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08002619#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002620 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2621 params->ssid_len, params->hidden_ssid);
2622 }
2623
2624 EXIT();
2625 return status;
2626}
2627
2628
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302629static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002630 struct net_device *dev,
2631 struct cfg80211_beacon_data *params)
2632{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302633 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302634 hdd_context_t *pHddCtx;
2635 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002636
2637 ENTER();
2638
Arif Hussain6d2a3322013-11-17 19:50:10 -08002639 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002640 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302641
2642 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2643 status = wlan_hdd_validate_context(pHddCtx);
2644
2645 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002646 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2648 "%s: HDD context is not valid", __func__);
2649 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002650 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002651
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302652 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002653 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302654 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002655 {
2656 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302657
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002658 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302659
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002660 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302661 {
2662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2663 FL("session(%d) beacon data points to NULL"),
2664 pAdapter->sessionId);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002665 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302666 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002667
2668 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2669
2670 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302671 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002672 "%s: Error!!! Allocating the new beacon",__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002673 return -EINVAL;
2674 }
2675
2676 pAdapter->sessionCtx.ap.beacon = new;
2677
2678 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2679 }
2680
2681 EXIT();
2682 return status;
2683}
2684
2685#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2686
Jeff Johnson295189b2012-06-20 16:38:30 -07002687
2688static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2689 struct net_device *dev,
2690 struct bss_parameters *params)
2691{
2692 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2693
2694 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302695
Arif Hussain6d2a3322013-11-17 19:50:10 -08002696 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002697 __func__,pAdapter->device_mode);
2698
2699 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002700 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302701 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002702 {
2703 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2704 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302705 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07002706 {
2707 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302708 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002709 }
2710
2711 EXIT();
2712 return 0;
2713}
2714
Kiet Lam10841362013-11-01 11:36:50 +05302715/* FUNCTION: wlan_hdd_change_country_code_cd
2716* to wait for contry code completion
2717*/
2718void* wlan_hdd_change_country_code_cb(void *pAdapter)
2719{
2720 hdd_adapter_t *call_back_pAdapter = pAdapter;
2721 complete(&call_back_pAdapter->change_country_code);
2722 return NULL;
2723}
2724
Jeff Johnson295189b2012-06-20 16:38:30 -07002725/*
2726 * FUNCTION: wlan_hdd_cfg80211_change_iface
2727 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2728 */
2729int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2730 struct net_device *ndev,
2731 enum nl80211_iftype type,
2732 u32 *flags,
2733 struct vif_params *params
2734 )
2735{
2736 struct wireless_dev *wdev;
2737 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2738 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002739 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002740 tCsrRoamProfile *pRoamProfile = NULL;
2741 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302742 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002743 eMib_dot11DesiredBssType connectedBssType;
2744 VOS_STATUS status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302745 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07002746
2747 ENTER();
2748
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302749 status = wlan_hdd_validate_context(pHddCtx);
2750
2751 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07002752 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2754 "%s: HDD context is not valid", __func__);
2755 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002756 }
2757
2758 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2759 __func__, pAdapter->device_mode);
2760
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302761 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07002762 wdev = ndev->ieee80211_ptr;
2763
2764#ifdef WLAN_BTAMP_FEATURE
2765 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2766 (NL80211_IFTYPE_ADHOC == type)||
2767 (NL80211_IFTYPE_AP == type)||
2768 (NL80211_IFTYPE_P2P_GO == type))
2769 {
2770 pHddCtx->isAmpAllowed = VOS_FALSE;
2771 // stop AMP traffic
2772 status = WLANBAP_StopAmp();
2773 if(VOS_STATUS_SUCCESS != status )
2774 {
2775 pHddCtx->isAmpAllowed = VOS_TRUE;
2776 hddLog(VOS_TRACE_LEVEL_FATAL,
2777 "%s: Failed to stop AMP", __func__);
2778 return -EINVAL;
2779 }
2780 }
2781#endif //WLAN_BTAMP_FEATURE
2782 /* Reset the current device mode bit mask*/
2783 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2784
2785 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002786 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002787 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002788 )
2789 {
2790 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2791 pRoamProfile = &pWextState->roamProfile;
2792 LastBSSType = pRoamProfile->BSSType;
2793
2794 switch (type)
2795 {
2796 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002797 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002798 hddLog(VOS_TRACE_LEVEL_INFO,
2799 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2800 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002801#ifdef WLAN_FEATURE_11AC
2802 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2803 {
2804 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2805 }
2806#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302807 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07002808 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002809 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002810 //Check for sub-string p2p to confirm its a p2p interface
2811 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302812 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002813 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2814 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2815 }
2816 else
2817 {
2818 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002819 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002820 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302821#ifdef FEATURE_WLAN_TDLS
2822 /* The open adapter for the p2p shall skip initializations in
2823 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
2824 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
2825 * tdls_init when the change_iface sets the device mode to
2826 * WLAN_HDD_P2P_CLIENT.
2827 */
2828
2829 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2830 {
2831 if (0 != wlan_hdd_tdls_init (pAdapter))
2832 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302833 hddLog(VOS_TRACE_LEVEL_ERROR,
2834 "%s: tdls initialization failed", __func__);
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302835 return -EINVAL;
2836 }
2837 }
2838#endif
2839
Jeff Johnson295189b2012-06-20 16:38:30 -07002840 break;
2841 case NL80211_IFTYPE_ADHOC:
2842 hddLog(VOS_TRACE_LEVEL_INFO,
2843 "%s: setting interface Type to ADHOC", __func__);
2844 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2845 pRoamProfile->phyMode =
2846 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07002847 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002848 wdev->iftype = type;
2849 break;
2850
2851 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002852 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002853 {
2854 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2855 "%s: setting interface Type to %s", __func__,
2856 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2857
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002858 //Cancel any remain on channel for GO mode
2859 if (NL80211_IFTYPE_P2P_GO == type)
2860 {
2861 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2862 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002863 if (NL80211_IFTYPE_AP == type)
2864 {
2865 /* As Loading WLAN Driver one interface being created for p2p device
2866 * address. This will take one HW STA and the max number of clients
2867 * that can connect to softAP will be reduced by one. so while changing
2868 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2869 * interface as it is not required in SoftAP mode.
2870 */
2871
2872 // Get P2P Adapter
2873 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2874
2875 if (pP2pAdapter)
2876 {
2877 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2878 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2879 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2880 }
2881 }
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302882#ifdef FEATURE_WLAN_TDLS
Mohit Khanna0f232092012-09-11 14:46:08 -07002883
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302884 /* A Mutex Lock is introduced while changing the mode to
2885 * protect the concurrent access for the Adapters by TDLS
2886 * module.
2887 */
2888 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
2889 {
2890 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2891 "%s: unable to lock list", __func__);
2892 return -EINVAL;
2893 }
2894#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002895 //De-init the adapter.
2896 hdd_stop_adapter( pHddCtx, pAdapter );
2897 hdd_deinit_adapter( pHddCtx, pAdapter );
2898 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002899 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2900 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302901#ifdef FEATURE_WLAN_TDLS
2902 mutex_unlock(&pHddCtx->tdls_lock);
2903#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002904
2905 //Disable BMPS and IMPS if enabled
2906 //before starting Go
2907 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2908 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302909 if(VOS_STATUS_E_FAILURE ==
Jeff Johnson32d95a32012-09-10 13:15:23 -07002910 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2911 {
2912 //Fail to Exit BMPS
2913 VOS_ASSERT(0);
2914 }
2915 }
2916
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002917 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2918 (pConfig->apRandomBssidEnabled))
2919 {
2920 /* To meet Android requirements create a randomized
2921 MAC address of the form 02:1A:11:Fx:xx:xx */
2922 get_random_bytes(&ndev->dev_addr[3], 3);
2923 ndev->dev_addr[0] = 0x02;
2924 ndev->dev_addr[1] = 0x1A;
2925 ndev->dev_addr[2] = 0x11;
2926 ndev->dev_addr[3] |= 0xF0;
2927 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2928 VOS_MAC_ADDR_SIZE);
Arif Hussain24bafea2013-11-15 15:10:03 -08002929 pr_info("wlan: Generated HotSpot BSSID " MAC_ADDRESS_STR"\n",
2930 MAC_ADDR_ARRAY(ndev->dev_addr));
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002931 }
2932
Jeff Johnson295189b2012-06-20 16:38:30 -07002933 hdd_set_ap_ops( pAdapter->dev );
2934
Kiet Lam10841362013-11-01 11:36:50 +05302935 /* This is for only SAP mode where users can
2936 * control country through ini.
2937 * P2P GO follows station country code
2938 * acquired during the STA scanning. */
2939 if((NL80211_IFTYPE_AP == type) &&
2940 (memcmp(pConfig->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0))
2941 {
2942 int status = 0;
2943 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
2944 "%s: setting country code from INI ", __func__);
2945 init_completion(&pAdapter->change_country_code);
2946 status = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2947 (void *)(tSmeChangeCountryCallback)
2948 wlan_hdd_change_country_code_cb,
2949 pConfig->apCntryCode, pAdapter,
2950 pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05302951 eSIR_FALSE,
2952 eSIR_TRUE);
Kiet Lam10841362013-11-01 11:36:50 +05302953 if (eHAL_STATUS_SUCCESS == status)
2954 {
2955 /* Wait for completion */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302956 ret = wait_for_completion_interruptible_timeout(
Kiet Lam10841362013-11-01 11:36:50 +05302957 &pAdapter->change_country_code,
2958 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302959 if (ret <= 0)
Kiet Lam10841362013-11-01 11:36:50 +05302960 {
2961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302962 FL("SME Timed out while setting country code %ld"),
2963 ret);
Yue Ma4f55ef32014-01-23 16:45:33 -08002964
2965 if (pHddCtx->isLogpInProgress)
2966 {
2967 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2968 "%s: LOGP in Progress. Ignore!!!", __func__);
2969 return -EAGAIN;
2970 }
Kiet Lam10841362013-11-01 11:36:50 +05302971 }
2972 }
2973 else
2974 {
2975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002976 "%s: SME Change Country code failed",__func__);
Kiet Lam10841362013-11-01 11:36:50 +05302977 return -EINVAL;
2978 }
2979 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002980 status = hdd_init_ap_mode(pAdapter);
2981 if(status != VOS_STATUS_SUCCESS)
2982 {
2983 hddLog(VOS_TRACE_LEVEL_FATAL,
2984 "%s: Error initializing the ap mode", __func__);
2985 return -EINVAL;
2986 }
2987 hdd_set_conparam(1);
2988
Jeff Johnson295189b2012-06-20 16:38:30 -07002989 /*interface type changed update in wiphy structure*/
2990 if(wdev)
2991 {
2992 wdev->iftype = type;
2993 pHddCtx->change_iface = type;
2994 }
2995 else
2996 {
2997 hddLog(VOS_TRACE_LEVEL_ERROR,
2998 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2999 return -EINVAL;
3000 }
3001 goto done;
3002 }
3003
3004 default:
3005 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
3006 __func__);
3007 return -EOPNOTSUPP;
3008 }
3009 }
3010 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003011 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003012 )
3013 {
3014 switch(type)
3015 {
3016 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003017 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07003018 case NL80211_IFTYPE_ADHOC:
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303019#ifdef FEATURE_WLAN_TDLS
3020
3021 /* A Mutex Lock is introduced while changing the mode to
3022 * protect the concurrent access for the Adapters by TDLS
3023 * module.
3024 */
3025 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
3026 {
3027 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3028 "%s: unable to lock list", __func__);
3029 return -EINVAL;
3030 }
3031#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07003032 hdd_stop_adapter( pHddCtx, pAdapter );
3033 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07003034 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08003035 //Check for sub-string p2p to confirm its a p2p interface
3036 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08003037 {
3038 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
3039 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
3040 }
3041 else
3042 {
3043 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07003044 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08003045 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003046 hdd_set_conparam(0);
3047 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07003048 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
3049 hdd_set_station_ops( pAdapter->dev );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303050#ifdef FEATURE_WLAN_TDLS
3051 mutex_unlock(&pHddCtx->tdls_lock);
3052#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05303053 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07003054 if( VOS_STATUS_SUCCESS != status )
3055 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07003056 /* In case of JB, for P2P-GO, only change interface will be called,
3057 * This is the right place to enable back bmps_imps()
3058 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303059 if (pHddCtx->hdd_wlan_suspended)
3060 {
3061 hdd_set_pwrparams(pHddCtx);
3062 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003063 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003064 goto done;
3065 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003066 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003067 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
3069 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003070 goto done;
3071 default:
3072 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
3073 __func__);
3074 return -EOPNOTSUPP;
3075
3076 }
3077
3078 }
3079 else
3080 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303081 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: unsupported device mode(%d)",
3082 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003083 return -EOPNOTSUPP;
3084 }
3085
3086
3087 if(pRoamProfile)
3088 {
3089 if ( LastBSSType != pRoamProfile->BSSType )
3090 {
3091 /*interface type changed update in wiphy structure*/
3092 wdev->iftype = type;
3093
3094 /*the BSS mode changed, We need to issue disconnect
3095 if connected or in IBSS disconnect state*/
3096 if ( hdd_connGetConnectedBssType(
3097 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
3098 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
3099 {
3100 /*need to issue a disconnect to CSR.*/
3101 INIT_COMPLETION(pAdapter->disconnect_comp_var);
3102 if( eHAL_STATUS_SUCCESS ==
3103 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
3104 pAdapter->sessionId,
3105 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
3106 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303107 ret = wait_for_completion_interruptible_timeout(
3108 &pAdapter->disconnect_comp_var,
3109 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3110 if (ret <= 0)
3111 {
3112 hddLog(VOS_TRACE_LEVEL_ERROR,
3113 FL("wait on disconnect_comp_var failed %ld"), ret);
3114 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003115 }
3116 }
3117 }
3118 }
3119
3120done:
3121 /*set bitmask based on updated value*/
3122 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07003123
3124 /* Only STA mode support TM now
3125 * all other mode, TM feature should be disabled */
3126 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
3127 (~VOS_STA & pHddCtx->concurrency_mode) )
3128 {
3129 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
3130 }
3131
Jeff Johnson295189b2012-06-20 16:38:30 -07003132#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303133 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07003134 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
3135 {
3136 //we are ok to do AMP
3137 pHddCtx->isAmpAllowed = VOS_TRUE;
3138 }
3139#endif //WLAN_BTAMP_FEATURE
3140 EXIT();
3141 return 0;
3142}
3143
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003144#ifdef FEATURE_WLAN_TDLS
3145static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
3146 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
3147{
3148 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3149 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3150 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003151 hddTdlsPeer_t *pTdlsPeer;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303152 long ret;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003153
3154 ENTER();
3155
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303156 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003157 {
3158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3159 "Invalid arguments");
3160 return -EINVAL;
3161 }
Hoonki Lee27511902013-03-14 18:19:06 -07003162
3163 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
3164 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
3165 {
3166 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3167 "%s: TDLS mode is disabled OR not enabled in FW."
3168 MAC_ADDRESS_STR " Request declined.",
3169 __func__, MAC_ADDR_ARRAY(mac));
3170 return -ENOTSUPP;
3171 }
3172
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003173 if (pHddCtx->isLogpInProgress)
3174 {
3175 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3176 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07003177 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003178 return -EBUSY;
3179 }
3180
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303181 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003182
3183 if ( NULL == pTdlsPeer ) {
3184 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3185 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
3186 __func__, MAC_ADDR_ARRAY(mac), update);
3187 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003188 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003189
3190 /* in add station, we accept existing valid staId if there is */
3191 if ((0 == update) &&
3192 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
3193 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003194 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003195 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003196 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003197 " link_status %d. staId %d. add station ignored.",
3198 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
3199 return 0;
3200 }
3201 /* in change station, we accept only when staId is valid */
3202 if ((1 == update) &&
3203 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
3204 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
3205 {
3206 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3207 "%s: " MAC_ADDRESS_STR
3208 " link status %d. staId %d. change station %s.",
3209 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
3210 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
3211 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003212 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003213
3214 /* when others are on-going, we want to change link_status to idle */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303215 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003216 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3218 "%s: " MAC_ADDRESS_STR
3219 " TDLS setup is ongoing. Request declined.",
3220 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07003221 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003222 }
3223
3224 /* first to check if we reached to maximum supported TDLS peer.
3225 TODO: for now, return -EPERM looks working fine,
3226 but need to check if any other errno fit into this category.*/
3227 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
3228 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003229 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3230 "%s: " MAC_ADDRESS_STR
3231 " TDLS Max peer already connected. Request declined.",
3232 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07003233 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003234 }
3235 else
3236 {
3237 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303238 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003239 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003240 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003241 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3242 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
3243 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003244 return -EPERM;
3245 }
3246 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003247 if (0 == update)
3248 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003249
Jeff Johnsond75fe012013-04-06 10:53:06 -07003250 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303251 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003252 {
3253 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3254 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003255 if(StaParams->htcap_present)
3256 {
3257 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3258 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
3259 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3260 "ht_capa->extended_capabilities: %0x",
3261 StaParams->HTCap.extendedHtCapInfo);
3262 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003263 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3264 "params->capability: %0x",StaParams->capability);
3265 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003266 "params->ext_capab_len: %0x",StaParams->extn_capability[0]);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003267 if(StaParams->vhtcap_present)
3268 {
3269 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3270 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
3271 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
3272 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
3273 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003274 {
3275 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003277 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
3278 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3279 "[%d]: %x ", i, StaParams->supported_rates[i]);
3280 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07003281 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303282 else if ((1 == update) && (NULL == StaParams))
3283 {
3284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3285 "%s : update is true, but staParams is NULL. Error!", __func__);
3286 return -EPERM;
3287 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003288
3289 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
3290
3291 if (!update)
3292 {
3293 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3294 pAdapter->sessionId, mac);
3295 }
3296 else
3297 {
3298 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3299 pAdapter->sessionId, mac, StaParams);
3300 }
3301
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303302 ret = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003303 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
3304
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303305 if (ret <= 0)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003306 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003307 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303308 "%s: timeout waiting for tdls add station indication %ld",
3309 __func__, ret);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003310 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003311 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303312
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003313 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
3314 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003315 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003316 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003317 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003318 }
3319
3320 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07003321
3322error:
3323 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
3324 return -EPERM;
3325
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003326}
3327#endif
3328
Jeff Johnson295189b2012-06-20 16:38:30 -07003329static int wlan_hdd_change_station(struct wiphy *wiphy,
3330 struct net_device *dev,
3331 u8 *mac,
3332 struct station_parameters *params)
3333{
3334 VOS_STATUS status = VOS_STATUS_SUCCESS;
3335 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05303336 hdd_context_t *pHddCtx;
3337 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003338 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003339#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003340 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003341 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003342#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003343 ENTER();
3344
Gopichand Nakkala29149562013-05-10 21:43:41 +05303345 if ((NULL == pAdapter))
3346 {
3347 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3348 "invalid adapter ");
3349 return -EINVAL;
3350 }
3351
3352 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3353 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3354
3355 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
3356 {
3357 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3358 "invalid HDD state or HDD station context");
3359 return -EINVAL;
3360 }
3361
3362 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003363 {
3364 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3365 "%s:LOGP in Progress. Ignore!!!", __func__);
3366 return -EAGAIN;
3367 }
3368
Jeff Johnson295189b2012-06-20 16:38:30 -07003369 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
3370
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003371 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3372 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07003373 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003374 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07003375 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303376 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07003377 WLANTL_STA_AUTHENTICATED);
3378
Gopichand Nakkala29149562013-05-10 21:43:41 +05303379 if (status != VOS_STATUS_SUCCESS)
3380 {
3381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3382 "%s: Not able to change TL state to AUTHENTICATED", __func__);
3383 return -EINVAL;
3384 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003385 }
3386 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07003387 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3388 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303389#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003390 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
3391 StaParams.capability = params->capability;
3392 StaParams.uapsd_queues = params->uapsd_queues;
3393 StaParams.max_sp = params->max_sp;
3394
3395 if (0 != params->ext_capab_len)
3396 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
3397 sizeof(StaParams.extn_capability));
3398
3399 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003400 {
3401 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003402 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003403 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003404
3405 StaParams.supported_rates_len = params->supported_rates_len;
3406
3407 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
3408 * The supported_rates array , for all the structures propogating till Add Sta
3409 * to the firmware has to be modified , if the supplicant (ieee80211) is
3410 * modified to send more rates.
3411 */
3412
3413 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3414 */
3415 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3416 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3417
3418 if (0 != StaParams.supported_rates_len) {
3419 int i = 0;
3420 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3421 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003423 "Supported Rates with Length %d", StaParams.supported_rates_len);
3424 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003425 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003426 "[%d]: %0x", i, StaParams.supported_rates[i]);
3427 }
3428
3429 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003430 {
3431 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003432 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003433 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003434
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003435 if (0 != params->ext_capab_len ) {
3436 /*Define A Macro : TODO Sunil*/
3437 if ((1<<4) & StaParams.extn_capability[3]) {
3438 isBufSta = 1;
3439 }
3440 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303441 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac, params->uapsd_queues,
3442 params->max_sp, isBufSta);
3443 if (VOS_STATUS_SUCCESS != status) {
3444 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3445 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3446 return -EINVAL;
3447 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003448 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3449
3450 if (VOS_STATUS_SUCCESS != status) {
3451 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3452 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3453 return -EINVAL;
3454 }
3455 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003456#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05303457 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003458 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003459 return status;
3460}
3461
3462/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003463 * FUNCTION: wlan_hdd_cfg80211_add_key
3464 * This function is used to initialize the key information
3465 */
3466#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003467static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003468 struct net_device *ndev,
3469 u8 key_index, bool pairwise,
3470 const u8 *mac_addr,
3471 struct key_params *params
3472 )
3473#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003474static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003475 struct net_device *ndev,
3476 u8 key_index, const u8 *mac_addr,
3477 struct key_params *params
3478 )
3479#endif
3480{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003481 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003482 tCsrRoamSetKey setKey;
3483 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303484 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003485 v_U32_t roamId= 0xFF;
3486 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003487 hdd_hostapd_state_t *pHostapdState;
3488 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003489 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303490 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003491
3492 ENTER();
3493
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303494 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3495 status = wlan_hdd_validate_context(pHddCtx);
3496
3497 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003498 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3500 "%s: HDD context is not valid", __func__);
3501 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003502 }
3503
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003504 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3505 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003506
3507 if (CSR_MAX_NUM_KEY <= key_index)
3508 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003509 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003510 key_index);
3511
3512 return -EINVAL;
3513 }
3514
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003515 if (CSR_MAX_KEY_LEN < params->key_len)
3516 {
3517 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3518 params->key_len);
3519
3520 return -EINVAL;
3521 }
3522
3523 hddLog(VOS_TRACE_LEVEL_INFO,
3524 "%s: called with key index = %d & key length %d",
3525 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003526
3527 /*extract key idx, key len and key*/
3528 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3529 setKey.keyId = key_index;
3530 setKey.keyLength = params->key_len;
3531 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3532
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003533 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003534 {
3535 case WLAN_CIPHER_SUITE_WEP40:
3536 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3537 break;
3538
3539 case WLAN_CIPHER_SUITE_WEP104:
3540 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3541 break;
3542
3543 case WLAN_CIPHER_SUITE_TKIP:
3544 {
3545 u8 *pKey = &setKey.Key[0];
3546 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3547
3548 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3549
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003550 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003551
3552 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003553 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003554 |--------------|----------|----------|
3555 <---16bytes---><--8bytes--><--8bytes-->
3556
3557 */
3558 /*Sme expects the 32 bytes key to be in the below order
3559
3560 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003561 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003562 |--------------|----------|----------|
3563 <---16bytes---><--8bytes--><--8bytes-->
3564 */
3565 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003566 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003567
3568 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003569 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003570
3571 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003572 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003573
3574
3575 break;
3576 }
3577
3578 case WLAN_CIPHER_SUITE_CCMP:
3579 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3580 break;
3581
3582#ifdef FEATURE_WLAN_WAPI
3583 case WLAN_CIPHER_SUITE_SMS4:
3584 {
3585 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3586 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3587 params->key, params->key_len);
3588 return 0;
3589 }
3590#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003591
Jeff Johnson295189b2012-06-20 16:38:30 -07003592#ifdef FEATURE_WLAN_CCX
3593 case WLAN_CIPHER_SUITE_KRK:
3594 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3595 break;
3596#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003597
3598#ifdef WLAN_FEATURE_11W
3599 case WLAN_CIPHER_SUITE_AES_CMAC:
3600 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003601 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003602#endif
3603
Jeff Johnson295189b2012-06-20 16:38:30 -07003604 default:
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003605 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
Jeff Johnson295189b2012-06-20 16:38:30 -07003606 __func__, params->cipher);
3607 return -EOPNOTSUPP;
3608 }
3609
3610 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3611 __func__, setKey.encType);
3612
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003613 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3615 (!pairwise)
3616#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003617 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003618#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003619 )
3620 {
3621 /* set group key*/
3622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3623 "%s- %d: setting Broadcast key",
3624 __func__, __LINE__);
3625 setKey.keyDirection = eSIR_RX_ONLY;
3626 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3627 }
3628 else
3629 {
3630 /* set pairwise key*/
3631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3632 "%s- %d: setting pairwise key",
3633 __func__, __LINE__);
3634 setKey.keyDirection = eSIR_TX_RX;
3635 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3636 }
3637 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
3638 {
3639 setKey.keyDirection = eSIR_TX_RX;
3640 /*Set the group key*/
3641 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3642 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07003643
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003644 if ( 0 != status )
3645 {
3646 hddLog(VOS_TRACE_LEVEL_ERROR,
3647 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3648 return -EINVAL;
3649 }
3650 /*Save the keys here and call sme_RoamSetKey for setting
3651 the PTK after peer joins the IBSS network*/
3652 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
3653 &setKey, sizeof(tCsrRoamSetKey));
3654 return status;
3655 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05303656 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
3657 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
3658 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003659 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003660 if( pHostapdState->bssState == BSS_START )
3661 {
c_hpothu7c55da62014-01-23 18:34:02 +05303662 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3663 vos_status = wlan_hdd_check_ula_done(pAdapter);
3664
3665 if ( vos_status != VOS_STATUS_SUCCESS )
3666 {
3667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3668 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3669 __LINE__, vos_status );
3670
3671 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3672
3673 return -EINVAL;
3674 }
3675
Jeff Johnson295189b2012-06-20 16:38:30 -07003676 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3677
3678 if ( status != eHAL_STATUS_SUCCESS )
3679 {
3680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3681 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3682 __LINE__, status );
3683 }
3684 }
3685
3686 /* Saving WEP keys */
3687 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3688 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3689 {
3690 //Save the wep key in ap context. Issue setkey after the BSS is started.
3691 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3692 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3693 }
3694 else
3695 {
3696 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003697 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003698 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3699 }
3700 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003701 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3702 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003703 {
3704 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3705 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3706
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303707#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3708 if (!pairwise)
3709#else
3710 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
3711#endif
3712 {
3713 /* set group key*/
3714 if (pHddStaCtx->roam_info.deferKeyComplete)
3715 {
3716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3717 "%s- %d: Perform Set key Complete",
3718 __func__, __LINE__);
3719 hdd_PerformRoamSetKeyComplete(pAdapter);
3720 }
3721 }
3722
Jeff Johnson295189b2012-06-20 16:38:30 -07003723 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3724
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003725 pWextState->roamProfile.Keys.defaultIndex = key_index;
3726
3727
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003728 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003729 params->key, params->key_len);
3730
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303731
Jeff Johnson295189b2012-06-20 16:38:30 -07003732 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3733
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303734 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003735 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303736 __func__, setKey.peerMac[0], setKey.peerMac[1],
3737 setKey.peerMac[2], setKey.peerMac[3],
3738 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003739 setKey.keyDirection);
3740
3741 vos_status = wlan_hdd_check_ula_done(pAdapter);
3742
3743 if ( vos_status != VOS_STATUS_SUCCESS )
3744 {
3745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3746 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3747 __LINE__, vos_status );
3748
3749 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3750
3751 return -EINVAL;
3752
3753 }
3754
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003755#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303756 /* The supplicant may attempt to set the PTK once pre-authentication
3757 is done. Save the key in the UMAC and include it in the ADD BSS
3758 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003759 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303760 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003761 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303762 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3763 "%s: Update PreAuth Key success", __func__);
3764 return 0;
3765 }
3766 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
3767 {
3768 hddLog(VOS_TRACE_LEVEL_ERROR,
3769 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303770 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003771 }
3772#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003773
3774 /* issue set key request to SME*/
3775 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3776 pAdapter->sessionId, &setKey, &roamId );
3777
3778 if ( 0 != status )
3779 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303780 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003781 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3782 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3783 return -EINVAL;
3784 }
3785
3786
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303787 /* in case of IBSS as there was no information available about WEP keys during
3788 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07003789 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303790 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3791 !( ( IW_AUTH_KEY_MGMT_802_1X
3792 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07003793 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3794 )
3795 &&
3796 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3797 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3798 )
3799 )
3800 {
3801 setKey.keyDirection = eSIR_RX_ONLY;
3802 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3803
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303804 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003805 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303806 __func__, setKey.peerMac[0], setKey.peerMac[1],
3807 setKey.peerMac[2], setKey.peerMac[3],
3808 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003809 setKey.keyDirection);
3810
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303811 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003812 pAdapter->sessionId, &setKey, &roamId );
3813
3814 if ( 0 != status )
3815 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303816 hddLog(VOS_TRACE_LEVEL_ERROR,
3817 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003818 __func__, status);
3819 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3820 return -EINVAL;
3821 }
3822 }
3823 }
3824
3825 return 0;
3826}
3827
3828/*
3829 * FUNCTION: wlan_hdd_cfg80211_get_key
3830 * This function is used to get the key information
3831 */
3832#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303833static int wlan_hdd_cfg80211_get_key(
3834 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003835 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303836 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 const u8 *mac_addr, void *cookie,
3838 void (*callback)(void *cookie, struct key_params*)
3839 )
3840#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303841static int wlan_hdd_cfg80211_get_key(
3842 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003843 struct net_device *ndev,
3844 u8 key_index, const u8 *mac_addr, void *cookie,
3845 void (*callback)(void *cookie, struct key_params*)
3846 )
3847#endif
3848{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303849 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003850 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3851 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3852 struct key_params params;
3853
3854 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303855
Arif Hussain6d2a3322013-11-17 19:50:10 -08003856 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003857 __func__,pAdapter->device_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303858
Jeff Johnson295189b2012-06-20 16:38:30 -07003859 memset(&params, 0, sizeof(params));
3860
3861 if (CSR_MAX_NUM_KEY <= key_index)
3862 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303863 hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid key index %d"), key_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003866
3867 switch(pRoamProfile->EncryptionType.encryptionType[0])
3868 {
3869 case eCSR_ENCRYPT_TYPE_NONE:
3870 params.cipher = IW_AUTH_CIPHER_NONE;
3871 break;
3872
3873 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3874 case eCSR_ENCRYPT_TYPE_WEP40:
3875 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3876 break;
3877
3878 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3879 case eCSR_ENCRYPT_TYPE_WEP104:
3880 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3881 break;
3882
3883 case eCSR_ENCRYPT_TYPE_TKIP:
3884 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3885 break;
3886
3887 case eCSR_ENCRYPT_TYPE_AES:
3888 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3889 break;
3890
3891 default:
3892 params.cipher = IW_AUTH_CIPHER_NONE;
3893 break;
3894 }
3895
3896 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3897 params.seq_len = 0;
3898 params.seq = NULL;
3899 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3900 callback(cookie, &params);
3901 return 0;
3902}
3903
3904/*
3905 * FUNCTION: wlan_hdd_cfg80211_del_key
3906 * This function is used to delete the key information
3907 */
3908#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303909static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003910 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303911 u8 key_index,
3912 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003913 const u8 *mac_addr
3914 )
3915#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303916static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003917 struct net_device *ndev,
3918 u8 key_index,
3919 const u8 *mac_addr
3920 )
3921#endif
3922{
3923 int status = 0;
3924
3925 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303926 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07003927 //it is observed that this is invalidating peer
3928 //key index whenever re-key is done. This is affecting data link.
3929 //It should be ok to ignore del_key.
3930#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303931 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3932 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003933 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3934 tCsrRoamSetKey setKey;
3935 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303936
Jeff Johnson295189b2012-06-20 16:38:30 -07003937 ENTER();
3938
3939 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3940 __func__,pAdapter->device_mode);
3941
3942 if (CSR_MAX_NUM_KEY <= key_index)
3943 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303944 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003945 key_index);
3946
3947 return -EINVAL;
3948 }
3949
3950 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3951 setKey.keyId = key_index;
3952
3953 if (mac_addr)
3954 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3955 else
3956 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3957
3958 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3959
3960 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003961 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303962 )
3963 {
3964
3965 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07003966 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3967 if( pHostapdState->bssState == BSS_START)
3968 {
3969 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303970
Jeff Johnson295189b2012-06-20 16:38:30 -07003971 if ( status != eHAL_STATUS_SUCCESS )
3972 {
3973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3974 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3975 __LINE__, status );
3976 }
3977 }
3978 }
3979 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303980 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003981 )
3982 {
3983 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3984
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303985 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3986
3987 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003988 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303989 __func__, setKey.peerMac[0], setKey.peerMac[1],
3990 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07003991 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303992 if(pAdapter->sessionCtx.station.conn_info.connState ==
3993 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07003994 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303995 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003996 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303997
Jeff Johnson295189b2012-06-20 16:38:30 -07003998 if ( 0 != status )
3999 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304000 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004001 "%s: sme_RoamSetKey failure, returned %d",
4002 __func__, status);
4003 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
4004 return -EINVAL;
4005 }
4006 }
4007 }
4008#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004009 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004010 return status;
4011}
4012
4013/*
4014 * FUNCTION: wlan_hdd_cfg80211_set_default_key
4015 * This function is used to set the default tx key index
4016 */
4017#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4018static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
4019 struct net_device *ndev,
4020 u8 key_index,
4021 bool unicast, bool multicast)
4022#else
4023static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
4024 struct net_device *ndev,
4025 u8 key_index)
4026#endif
4027{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304028 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304029 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05304030 hdd_wext_state_t *pWextState;
4031 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304032 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004033
4034 ENTER();
4035
Gopichand Nakkala29149562013-05-10 21:43:41 +05304036 if ((NULL == pAdapter))
4037 {
4038 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4039 "invalid adapter");
4040 return -EINVAL;
4041 }
4042
4043 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4044 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4045
4046 if ((NULL == pWextState) || (NULL == pHddStaCtx))
4047 {
4048 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4049 "invalid Wext state or HDD context");
4050 return -EINVAL;
4051 }
4052
Arif Hussain6d2a3322013-11-17 19:50:10 -08004053 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004054 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304055
Jeff Johnson295189b2012-06-20 16:38:30 -07004056 if (CSR_MAX_NUM_KEY <= key_index)
4057 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304058 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004059 key_index);
4060
4061 return -EINVAL;
4062 }
4063
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304064 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4065 status = wlan_hdd_validate_context(pHddCtx);
4066
4067 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004068 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4070 "%s: HDD context is not valid", __func__);
4071 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004072 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304073
Jeff Johnson295189b2012-06-20 16:38:30 -07004074 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07004075 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304076 )
Jeff Johnson295189b2012-06-20 16:38:30 -07004077 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05304078 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Arif Hussain6943f522013-11-04 20:10:10 -08004079 pHddStaCtx->conn_info.ucEncryptionType) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304080 (eCSR_ENCRYPT_TYPE_AES !=
Arif Hussain6943f522013-11-04 20:10:10 -08004081 pHddStaCtx->conn_info.ucEncryptionType)
Jeff Johnson295189b2012-06-20 16:38:30 -07004082 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304083 {
4084 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07004085 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304086
Jeff Johnson295189b2012-06-20 16:38:30 -07004087 tCsrRoamSetKey setKey;
4088 v_U32_t roamId= 0xFF;
4089 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304090
4091 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004092 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304093
Jeff Johnson295189b2012-06-20 16:38:30 -07004094 Keys->defaultIndex = (u8)key_index;
4095 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
4096 setKey.keyId = key_index;
4097 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304098
4099 vos_mem_copy(&setKey.Key[0],
4100 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07004101 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304102
Gopichand Nakkala29149562013-05-10 21:43:41 +05304103 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304104
4105 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07004106 &pHddStaCtx->conn_info.bssId[0],
4107 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304108
Gopichand Nakkala29149562013-05-10 21:43:41 +05304109 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
4110 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4111 eCSR_ENCRYPT_TYPE_WEP104)
4112 {
4113 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
4114 even though ap is configured for WEP-40 encryption. In this canse the key length
4115 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
4116 type(104) and switching encryption type to 40*/
4117 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4118 eCSR_ENCRYPT_TYPE_WEP40;
4119 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
4120 eCSR_ENCRYPT_TYPE_WEP40;
4121 }
4122
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304123 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07004124 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304125
Jeff Johnson295189b2012-06-20 16:38:30 -07004126 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304127 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004128 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304129
Jeff Johnson295189b2012-06-20 16:38:30 -07004130 if ( 0 != status )
4131 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304132 hddLog(VOS_TRACE_LEVEL_ERROR,
4133 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004134 status);
4135 return -EINVAL;
4136 }
4137 }
4138 }
4139
4140 /* In SoftAp mode setting key direction for default mode */
4141 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
4142 {
4143 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
4144 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
4145 (eCSR_ENCRYPT_TYPE_AES !=
4146 pWextState->roamProfile.EncryptionType.encryptionType[0])
4147 )
4148 {
4149 /* Saving key direction for default key index to TX default */
4150 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4151 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
4152 }
4153 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304154
Jeff Johnson295189b2012-06-20 16:38:30 -07004155 return status;
4156}
4157
Jeff Johnson295189b2012-06-20 16:38:30 -07004158/*
4159 * FUNCTION: wlan_hdd_cfg80211_inform_bss
4160 * This function is used to inform the BSS details to nl80211 interface.
4161 */
4162static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
4163 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
4164{
4165 struct net_device *dev = pAdapter->dev;
4166 struct wireless_dev *wdev = dev->ieee80211_ptr;
4167 struct wiphy *wiphy = wdev->wiphy;
4168 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
4169 int chan_no;
4170 int ie_length;
4171 const char *ie;
4172 unsigned int freq;
4173 struct ieee80211_channel *chan;
4174 int rssi = 0;
4175 struct cfg80211_bss *bss = NULL;
4176
4177 ENTER();
4178
4179 if( NULL == pBssDesc )
4180 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004181 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004182 return bss;
4183 }
4184
4185 chan_no = pBssDesc->channelId;
4186 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
4187 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
4188
4189 if( NULL == ie )
4190 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004191 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004192 return bss;
4193 }
4194
4195#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
4196 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
4197 {
4198 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4199 }
4200 else
4201 {
4202 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4203 }
4204#else
4205 freq = ieee80211_channel_to_frequency(chan_no);
4206#endif
4207
4208 chan = __ieee80211_get_channel(wiphy, freq);
4209
4210 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
4211 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
4212 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
4213 if (bss == NULL)
4214 {
4215 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
4216
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304217 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
4218 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07004219 pBssDesc->capabilityInfo,
4220 pBssDesc->beaconInterval, ie, ie_length,
4221 rssi, GFP_KERNEL ));
4222}
4223 else
4224 {
4225 return bss;
4226 }
4227}
4228
4229
4230
4231/*
4232 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
4233 * This function is used to inform the BSS details to nl80211 interface.
4234 */
4235struct cfg80211_bss*
4236wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
4237 tSirBssDescription *bss_desc
4238 )
4239{
4240 /*
4241 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
4242 already exists in bss data base of cfg80211 for that particular BSS ID.
4243 Using cfg80211_inform_bss_frame to update the bss entry instead of
4244 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
4245 now there is no possibility to get the mgmt(probe response) frame from PE,
4246 converting bss_desc to ieee80211_mgmt(probe response) and passing to
4247 cfg80211_inform_bss_frame.
4248 */
4249 struct net_device *dev = pAdapter->dev;
4250 struct wireless_dev *wdev = dev->ieee80211_ptr;
4251 struct wiphy *wiphy = wdev->wiphy;
4252 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004253#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4254 qcom_ie_age *qie_age = NULL;
4255 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
4256#else
Jeff Johnson295189b2012-06-20 16:38:30 -07004257 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004258#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004259 const char *ie =
4260 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
4261 unsigned int freq;
4262 struct ieee80211_channel *chan;
Abhishek Singh1e2bfa32014-01-02 15:44:15 +05304263 struct ieee80211_mgmt *mgmt = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004264 struct cfg80211_bss *bss_status = NULL;
4265 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
4266 int rssi = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07004267 hdd_context_t *pHddCtx;
4268 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07004269#ifdef WLAN_OPEN_SOURCE
4270 struct timespec ts;
4271#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004272
Wilson Yangf80a0542013-10-07 13:02:37 -07004273 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4274 status = wlan_hdd_validate_context(pHddCtx);
4275
4276 /*bss_update is not allowed during wlan driver loading or unloading*/
4277 if (pHddCtx->isLoadUnloadInProgress)
4278 {
4279 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4280 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
4281 return NULL;
4282 }
4283
4284
4285 if (0 != status)
4286 {
4287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4288 "%s: HDD context is not valid", __func__);
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004289 return NULL;
Wilson Yangf80a0542013-10-07 13:02:37 -07004290 }
4291
Abhishek Singh1e2bfa32014-01-02 15:44:15 +05304292 mgmt = kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
Wilson Yangf80a0542013-10-07 13:02:37 -07004293 if (!mgmt)
4294 {
4295 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4296 "%s: memory allocation failed ", __func__);
4297 return NULL;
4298 }
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004299
Jeff Johnson295189b2012-06-20 16:38:30 -07004300 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07004301
4302#ifdef WLAN_OPEN_SOURCE
4303 /* Android does not want the timestamp from the frame.
4304 Instead it wants a monotonic increasing value */
4305 get_monotonic_boottime(&ts);
4306 mgmt->u.probe_resp.timestamp =
4307 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
4308#else
4309 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07004310 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
4311 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07004312
4313#endif
4314
Jeff Johnson295189b2012-06-20 16:38:30 -07004315 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
4316 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004317
4318#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4319 /* GPS Requirement: need age ie per entry. Using vendor specific. */
4320 /* Assuming this is the last IE, copy at the end */
4321 ie_length -=sizeof(qcom_ie_age);
4322 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
4323 qie_age->element_id = QCOM_VENDOR_IE_ID;
4324 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
4325 qie_age->oui_1 = QCOM_OUI1;
4326 qie_age->oui_2 = QCOM_OUI2;
4327 qie_age->oui_3 = QCOM_OUI3;
4328 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
4329 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
4330#endif
4331
Jeff Johnson295189b2012-06-20 16:38:30 -07004332 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05304333 if (bss_desc->fProbeRsp)
4334 {
4335 mgmt->frame_control |=
4336 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
4337 }
4338 else
4339 {
4340 mgmt->frame_control |=
4341 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
4342 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004343
4344#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304345 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004346 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
4347 {
4348 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4349 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304350 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
4352
4353 {
4354 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4355 }
4356 else
4357 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304358 hddLog(VOS_TRACE_LEVEL_ERROR, "%s Invalid chan_no:%d",
4359 __func__, chan_no);
Jeff Johnson295189b2012-06-20 16:38:30 -07004360 kfree(mgmt);
4361 return NULL;
4362 }
4363#else
4364 freq = ieee80211_channel_to_frequency(chan_no);
4365#endif
4366 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004367 /*when the band is changed on the fly using the GUI, three things are done
4368 * 1. scan abort 2.flush scan results from cache 3.update the band with the new band user specified(refer to the hdd_setBand_helper function)
4369 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
4370 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
4371 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
4372 * and discards the channels correponding to previous band and calls back with zero bss results.
4373 * but if the time between band update and scan done callback is very small then band change will not reflect in SME and SME reports to HDD
4374 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
4375 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
4376 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
4377 * So drop the bss and continue to next bss.
4378 */
4379 if(chan == NULL)
4380 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304381 hddLog(VOS_TRACE_LEVEL_ERROR, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07004382 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004383 return NULL;
4384 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004385 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304386 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07004387 * */
4388 if (( eConnectionState_Associated ==
4389 pAdapter->sessionCtx.station.conn_info.connState ) &&
4390 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
4391 pAdapter->sessionCtx.station.conn_info.bssId,
4392 WNI_CFG_BSSID_LEN)))
4393 {
4394 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
4395 rssi = (pAdapter->rssi * 100);
4396 }
4397 else
4398 {
4399 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
4400 }
4401
Nirav Shah20ac06f2013-12-12 18:14:06 +05304402 hddLog(VOS_TRACE_LEVEL_INFO, "%s: BSSID:" MAC_ADDRESS_STR " Channel:%d"
4403 "RSSI:%d", __func__, MAC_ADDR_ARRAY(mgmt->bssid),
4404 chan->center_freq, (int)(rssi/100));
4405
Jeff Johnson295189b2012-06-20 16:38:30 -07004406 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4407 frame_len, rssi, GFP_KERNEL);
4408 kfree(mgmt);
4409 return bss_status;
4410}
4411
4412/*
4413 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4414 * This function is used to update the BSS data base of CFG8011
4415 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304416struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004417 tCsrRoamInfo *pRoamInfo
4418 )
4419{
4420 tCsrRoamConnectedProfile roamProfile;
4421 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4422 struct cfg80211_bss *bss = NULL;
4423
4424 ENTER();
4425
4426 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4427 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4428
4429 if (NULL != roamProfile.pBssDesc)
4430 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304431 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004432 &roamProfile);
4433
4434 if (NULL == bss)
4435 {
4436 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4437 __func__);
4438 }
4439
4440 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4441 }
4442 else
4443 {
4444 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4445 __func__);
4446 }
4447 return bss;
4448}
4449
4450/*
4451 * FUNCTION: wlan_hdd_cfg80211_update_bss
4452 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304453static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4454 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07004455 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304456{
Jeff Johnson295189b2012-06-20 16:38:30 -07004457 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4458 tCsrScanResultInfo *pScanResult;
4459 eHalStatus status = 0;
4460 tScanResultHandle pResult;
4461 struct cfg80211_bss *bss_status = NULL;
Wilson Yangf80a0542013-10-07 13:02:37 -07004462 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004463
4464 ENTER();
4465
Wilson Yangf80a0542013-10-07 13:02:37 -07004466 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4467
4468 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004469 {
Wilson Yangf80a0542013-10-07 13:02:37 -07004470 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4471 "%s:LOGP in Progress. Ignore!!!",__func__);
4472 return -EAGAIN;
Jeff Johnson295189b2012-06-20 16:38:30 -07004473 }
4474
Wilson Yangf80a0542013-10-07 13:02:37 -07004475
4476 /*bss_update is not allowed during wlan driver loading or unloading*/
4477 if (pHddCtx->isLoadUnloadInProgress)
4478 {
4479 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4480 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
4481 return VOS_STATUS_E_PERM;
4482 }
4483
4484
Jeff Johnson295189b2012-06-20 16:38:30 -07004485 /*
4486 * start getting scan results and populate cgf80211 BSS database
4487 */
4488 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4489
4490 /* no scan results */
4491 if (NULL == pResult)
4492 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304493 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result Status %d",
4494 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004495 return status;
4496 }
4497
4498 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4499
4500 while (pScanResult)
4501 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304502 /*
4503 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4504 * entry already exists in bss data base of cfg80211 for that
4505 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4506 * bss entry instead of cfg80211_inform_bss, But this call expects
4507 * mgmt packet as input. As of now there is no possibility to get
4508 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07004509 * ieee80211_mgmt(probe response) and passing to c
4510 * fg80211_inform_bss_frame.
4511 * */
4512
4513 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4514 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304515
Jeff Johnson295189b2012-06-20 16:38:30 -07004516
4517 if (NULL == bss_status)
4518 {
4519 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08004520 "%s: NULL returned by cfg80211_inform_bss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 }
4522 else
4523 {
Yue Maf49ba872013-08-19 12:04:25 -07004524 cfg80211_put_bss(
4525#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
4526 wiphy,
4527#endif
4528 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004529 }
4530
4531 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4532 }
4533
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304534 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07004535
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304536 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004537}
4538
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004539void
4540hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4541{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304542 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Arif Hussaina7c8e412013-11-20 11:06:42 -08004543 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(macAddr));
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004544} /****** end hddPrintMacAddr() ******/
4545
4546void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004547hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004548{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304549 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Arif Hussain6d2a3322013-11-17 19:50:10 -08004550 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004551 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4552 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4553 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004554} /****** end hddPrintPmkId() ******/
4555
4556//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4557//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4558
4559//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4560//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4561
4562#define dump_bssid(bssid) \
4563 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004564 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4565 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004566 }
4567
4568#define dump_pmkid(pMac, pmkid) \
4569 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004570 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4571 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004572 }
4573
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004574#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004575/*
4576 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4577 * This function is used to notify the supplicant of a new PMKSA candidate.
4578 */
4579int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304580 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004581 int index, bool preauth )
4582{
Jeff Johnsone7245742012-09-05 17:12:55 -07004583#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004584 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004585 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004586
4587 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004588 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004589
4590 if( NULL == pRoamInfo )
4591 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004592 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004593 return -EINVAL;
4594 }
4595
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004596 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4597 {
4598 dump_bssid(pRoamInfo->bssid);
4599 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004600 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004601 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004602#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304603 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004604}
4605#endif //FEATURE_WLAN_LFR
4606
Yue Maef608272013-04-08 23:09:17 -07004607#ifdef FEATURE_WLAN_LFR_METRICS
4608/*
4609 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth
4610 * 802.11r/LFR metrics reporting function to report preauth initiation
4611 *
4612 */
4613#define MAX_LFR_METRICS_EVENT_LENGTH 100
4614VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
4615 tCsrRoamInfo *pRoamInfo)
4616{
4617 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4618 union iwreq_data wrqu;
4619
4620 ENTER();
4621
4622 if (NULL == pAdapter)
4623 {
4624 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4625 return VOS_STATUS_E_FAILURE;
4626 }
4627
4628 /* create the event */
4629 memset(&wrqu, 0, sizeof(wrqu));
4630 memset(metrics_notification, 0, sizeof(metrics_notification));
4631
4632 wrqu.data.pointer = metrics_notification;
4633 wrqu.data.length = scnprintf(metrics_notification,
4634 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_INIT "
4635 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
4636
4637 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4638
4639 EXIT();
4640
4641 return VOS_STATUS_SUCCESS;
4642}
4643
4644/*
4645 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth_status
4646 * 802.11r/LFR metrics reporting function to report preauth completion
4647 * or failure
4648 */
4649VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status(
4650 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, bool preauth_status)
4651{
4652 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4653 union iwreq_data wrqu;
4654
4655 ENTER();
4656
4657 if (NULL == pAdapter)
4658 {
4659 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4660 return VOS_STATUS_E_FAILURE;
4661 }
4662
4663 /* create the event */
4664 memset(&wrqu, 0, sizeof(wrqu));
4665 memset(metrics_notification, 0, sizeof(metrics_notification));
4666
4667 scnprintf(metrics_notification, sizeof(metrics_notification),
4668 "QCOM: LFR_PREAUTH_STATUS "MAC_ADDRESS_STR,
4669 MAC_ADDR_ARRAY(pRoamInfo->bssid));
4670
4671 if (1 == preauth_status)
4672 strncat(metrics_notification, " TRUE", 5);
4673 else
4674 strncat(metrics_notification, " FALSE", 6);
4675
4676 wrqu.data.pointer = metrics_notification;
4677 wrqu.data.length = strlen(metrics_notification);
4678
4679 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4680
4681 EXIT();
4682
4683 return VOS_STATUS_SUCCESS;
4684}
4685
4686/*
4687 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_handover
4688 * 802.11r/LFR metrics reporting function to report handover initiation
4689 *
4690 */
4691VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t * pAdapter,
4692 tCsrRoamInfo *pRoamInfo)
4693{
4694 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4695 union iwreq_data wrqu;
4696
4697 ENTER();
4698
4699 if (NULL == pAdapter)
4700 {
4701 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4702 return VOS_STATUS_E_FAILURE;
4703 }
4704
4705 /* create the event */
4706 memset(&wrqu, 0, sizeof(wrqu));
4707 memset(metrics_notification, 0, sizeof(metrics_notification));
4708
4709 wrqu.data.pointer = metrics_notification;
4710 wrqu.data.length = scnprintf(metrics_notification,
4711 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_HANDOVER "
4712 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
4713
4714 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4715
4716 EXIT();
4717
4718 return VOS_STATUS_SUCCESS;
4719}
4720#endif
4721
Jeff Johnson295189b2012-06-20 16:38:30 -07004722/*
4723 * FUNCTION: hdd_cfg80211_scan_done_callback
4724 * scanning callback function, called after finishing scan
4725 *
4726 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304727static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07004728 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4729{
4730 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304731 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07004732 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004733 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4734 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 struct cfg80211_scan_request *req = NULL;
4736 int ret = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304737 long waitRet = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004738
4739 ENTER();
4740
4741 hddLog(VOS_TRACE_LEVEL_INFO,
4742 "%s called with halHandle = %p, pContext = %p,"
Arif Hussain6d2a3322013-11-17 19:50:10 -08004743 "scanID = %d, returned status = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004744 __func__, halHandle, pContext, (int) scanId, (int) status);
4745
Kiet Lamac06e2c2013-10-23 16:25:07 +05304746 pScanInfo->mScanPendingCounter = 0;
4747
Jeff Johnson295189b2012-06-20 16:38:30 -07004748 //Block on scan req completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304749 waitRet = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004750 &pScanInfo->scan_req_completion_event,
4751 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304752 if (waitRet <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304754 hddLog(VOS_TRACE_LEVEL_ERROR,
4755 "%s wait on scan_req_completion_event failed %ld",__func__, waitRet);
Jeff Johnson295189b2012-06-20 16:38:30 -07004756 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004757 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004758 }
4759
Yue Maef608272013-04-08 23:09:17 -07004760 if (pScanInfo->mScanPending != VOS_TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -07004761 {
4762 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004763 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004764 }
4765
4766 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304767 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07004768 {
4769 hddLog(VOS_TRACE_LEVEL_INFO,
4770 "%s called with mismatched scanId pScanInfo->scanId = %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08004771 "scanId = %d", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07004772 (int) scanId);
4773 }
4774
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304775 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07004776 pAdapter);
4777
4778 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304779 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004780
4781
4782 /* If any client wait scan result through WEXT
4783 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004784 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004785 {
4786 /* The other scan request waiting for current scan finish
4787 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004788 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004789 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004790 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004791 }
4792 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004793 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004794 {
4795 struct net_device *dev = pAdapter->dev;
4796 union iwreq_data wrqu;
4797 int we_event;
4798 char *msg;
4799
4800 memset(&wrqu, '\0', sizeof(wrqu));
4801 we_event = SIOCGIWSCAN;
4802 msg = NULL;
4803 wireless_send_event(dev, we_event, &wrqu, msg);
4804 }
4805 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004806 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004807
4808 /* Get the Scan Req */
4809 req = pAdapter->request;
4810
4811 if (!req)
4812 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004813 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004814 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004815 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004816 }
4817
4818 /*
4819 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304820 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 req->n_ssids = 0;
4822 req->n_channels = 0;
4823 req->ie = 0;
4824
Jeff Johnson295189b2012-06-20 16:38:30 -07004825 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004826 /* Scan is no longer pending */
4827 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004828
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004829 /*
4830 * cfg80211_scan_done informing NL80211 about completion
4831 * of scanning
4832 */
4833 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004834 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004835
Jeff Johnsone7245742012-09-05 17:12:55 -07004836allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004837 /* release the wake lock at the end of the scan*/
4838 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004839
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004840 /* Acquire wakelock to handle the case where APP's tries to suspend
4841 * immediatly after the driver gets connect request(i.e after scan)
4842 * from supplicant, this result in app's is suspending and not able
4843 * to process the connect request to AP */
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05304844 hdd_prevent_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004845
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004846#ifdef FEATURE_WLAN_TDLS
4847 wlan_hdd_tdls_scan_done_callback(pAdapter);
4848#endif
4849
Jeff Johnson295189b2012-06-20 16:38:30 -07004850 EXIT();
4851 return 0;
4852}
4853
4854/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004855 * FUNCTION: hdd_isScanAllowed
4856 * Go through each adapter and check if scan allowed
4857 *
4858 */
4859v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4860{
4861 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4862 hdd_station_ctx_t *pHddStaCtx = NULL;
4863 hdd_adapter_t *pAdapter = NULL;
4864 VOS_STATUS status = 0;
4865 v_U8_t staId = 0;
4866 v_U8_t *staMac = NULL;
4867
c_hpothu9b781ba2013-12-30 20:57:45 +05304868 if (TRUE == pHddCtx->btCoexModeSet)
4869 {
4870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4871 FL("BTCoex Mode operation in progress, Do not allow scan"));
4872 return VOS_FALSE;
4873 }
4874
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004875 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4876
4877 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4878 {
4879 pAdapter = pAdapterNode->pAdapter;
4880
4881 if( pAdapter )
4882 {
4883 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304884 "%s: Adapter with device mode %d exists",
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004885 __func__, pAdapter->device_mode);
4886 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4887 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4888 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4889 {
4890 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4891 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4892 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4893 {
4894 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4895 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain24bafea2013-11-15 15:10:03 -08004896 "%s: client " MAC_ADDRESS_STR
4897 " is in the middle of WPS/EAPOL exchange.", __func__,
4898 MAC_ADDR_ARRAY(staMac));
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004899 return VOS_FALSE;
4900 }
4901 }
4902 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4903 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4904 {
4905 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4906 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304907 if ((pAdapter->aStaInfo[staId].isUsed) &&
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004908 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4909 {
4910 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4911
4912 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain24bafea2013-11-15 15:10:03 -08004913 "%s: client " MAC_ADDRESS_STR " of SoftAP/P2P-GO is in the "
4914 "middle of WPS/EAPOL exchange.", __func__,
4915 MAC_ADDR_ARRAY(staMac));
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004916 return VOS_FALSE;
4917 }
4918 }
4919 }
4920 }
4921 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4922 pAdapterNode = pNext;
4923 }
4924 hddLog(VOS_TRACE_LEVEL_INFO,
4925 "%s: Scan allowed", __func__);
4926 return VOS_TRUE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304927}
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004928
4929/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004930 * FUNCTION: wlan_hdd_cfg80211_scan
4931 * this scan respond to scan trigger and update cfg80211 scan database
4932 * later, scan dump command can be used to recieve scan results
4933 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004934int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4935#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4936 struct net_device *dev,
4937#endif
4938 struct cfg80211_scan_request *request)
4939{
4940#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4941 struct net_device *dev = request->wdev->netdev;
4942#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304943 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07004944 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4945 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304946 hdd_config_t *cfg_param = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004947 tCsrScanRequest scanRequest;
4948 tANI_U8 *channelList = NULL, i;
4949 v_U32_t scanId = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304950 int status;
4951 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004952 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004953
4954 ENTER();
4955
Arif Hussain6d2a3322013-11-17 19:50:10 -08004956 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004957 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004958
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304959 status = wlan_hdd_validate_context(pHddCtx);
4960
4961 if (0 != status)
4962 {
4963 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4964 "%s: HDD context is not valid", __func__);
4965 return status;
4966 }
4967
4968 cfg_param = pHddCtx->cfg_ini;
4969 pScanInfo = &pHddCtx->scan_info;
4970
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004971 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004972 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004973 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004974 {
4975 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004976 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4977 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004978 return -EBUSY;
4979 }
4980
Jeff Johnson295189b2012-06-20 16:38:30 -07004981#ifdef WLAN_BTAMP_FEATURE
4982 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004983 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004985 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004986 "%s: No scanning when AMP is on", __func__);
4987 return -EOPNOTSUPP;
4988 }
4989#endif
4990 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004991 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004992 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004993 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004994 "%s: Not scanning on device_mode = %d",
4995 __func__, pAdapter->device_mode);
4996 return -EOPNOTSUPP;
4997 }
4998
4999 if (TRUE == pScanInfo->mScanPending)
5000 {
Kiet Lamac06e2c2013-10-23 16:25:07 +05305001 if ( MAX_PENDING_LOG > pScanInfo->mScanPendingCounter++ )
5002 {
5003 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: mScanPending is TRUE", __func__);
5004 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005005 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07005006 }
5007
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305008 //Don't Allow Scan and return busy if Remain On
Jeff Johnson32d95a32012-09-10 13:15:23 -07005009 //Channel and action frame is pending
5010 //Otherwise Cancel Remain On Channel and allow Scan
5011 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005012 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07005013 {
Kiet Lamac06e2c2013-10-23 16:25:07 +05305014 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Remain On Channel Pending", __func__);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005015 return -EBUSY;
5016 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005017#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005018 /* if tdls disagree scan right now, return immediately.
5019 tdls will schedule the scan when scan is allowed. (return SUCCESS)
5020 or will reject the scan if any TDLS is in progress. (return -EBUSY)
5021 */
5022 status = wlan_hdd_tdls_scan_callback (pAdapter,
5023 wiphy,
5024#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
5025 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07005026#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005027 request);
5028 if(status <= 0)
5029 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305030 if(!status)
5031 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS in progress."
5032 "scan rejected %d", __func__, status);
5033 else
5034 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS teardown is ongoing %d",
5035 __func__, status);
5036
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005037 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005038 }
5039#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07005040
Jeff Johnson295189b2012-06-20 16:38:30 -07005041 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
5042 {
5043 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08005044 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005045 return -EAGAIN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305046 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005047 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
5048 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305049 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005050 "%s: MAX TM Level Scan not allowed", __func__);
5051 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305052 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07005053 }
5054 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
5055
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08005056 /* Check if scan is allowed at this point of time.
5057 */
5058 if (!hdd_isScanAllowed(pHddCtx))
5059 {
5060 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
5061 return -EBUSY;
5062 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305063
Jeff Johnson295189b2012-06-20 16:38:30 -07005064 vos_mem_zero( &scanRequest, sizeof(scanRequest));
5065
5066 if (NULL != request)
5067 {
5068 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305069 (int)request->n_ssids);
Jeff Johnson295189b2012-06-20 16:38:30 -07005070
5071 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
5072 * Becasue of this, driver is assuming that this is not wildcard scan and so
5073 * is not aging out the scan results.
5074 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07005075 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07005076 {
5077 request->n_ssids = 0;
5078 }
5079
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005080 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07005081 {
5082 tCsrSSIDInfo *SsidInfo;
5083 int j;
5084 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
5085 /* Allocate num_ssid tCsrSSIDInfo structure */
5086 SsidInfo = scanRequest.SSIDs.SSIDList =
5087 ( tCsrSSIDInfo *)vos_mem_malloc(
5088 request->n_ssids*sizeof(tCsrSSIDInfo));
5089
5090 if(NULL == scanRequest.SSIDs.SSIDList)
5091 {
5092 hddLog(VOS_TRACE_LEVEL_ERROR,
Nirav Shah20ac06f2013-12-12 18:14:06 +05305093 "%s: memory alloc failed SSIDInfo buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 return -ENOMEM;
5095 }
5096
5097 /* copy all the ssid's and their length */
5098 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
5099 {
5100 /* get the ssid length */
5101 SsidInfo->SSID.length = request->ssids[j].ssid_len;
5102 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
5103 SsidInfo->SSID.length);
5104 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
Nirav Shah20ac06f2013-12-12 18:14:06 +05305105 hddLog(VOS_TRACE_LEVEL_INFO, "SSID number %d: %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 j, SsidInfo->SSID.ssId);
5107 }
5108 /* set the scan type to active */
5109 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5110 }
5111 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
5112 {
5113 /* set the scan type to active */
5114 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5115 }
5116 else
5117 {
5118 /*Set the scan type to default type, in this case it is ACTIVE*/
5119 scanRequest.scanType = pScanInfo->scan_mode;
5120 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305121 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
5123 }
5124 else
5125 {
5126 /* set the scan type to active */
5127 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5128 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
5129
5130 /* set min and max channel time to zero */
5131 scanRequest.minChnTime = 0;
5132 scanRequest.maxChnTime = 0;
5133 }
5134
5135 /* set BSSType to default type */
5136 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
5137
5138 /*TODO: scan the requested channels only*/
5139
5140 /*Right now scanning all the channels */
5141 if( request )
5142 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305143 hddLog(VOS_TRACE_LEVEL_INFO,
5144 "No of Scan Channels: %d", request->n_channels);
Jeff Johnson295189b2012-06-20 16:38:30 -07005145 if( request->n_channels )
5146 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305147 char chList [(request->n_channels*5)+1];
5148 int len;
Jeff Johnson295189b2012-06-20 16:38:30 -07005149 channelList = vos_mem_malloc( request->n_channels );
5150 if( NULL == channelList )
5151 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305152 hddLog(VOS_TRACE_LEVEL_ERROR,
Nirav Shah20ac06f2013-12-12 18:14:06 +05305153 "%s: memory alloc failed channelList", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005154 status = -ENOMEM;
5155 goto free_mem;
5156 }
5157
Nirav Shah20ac06f2013-12-12 18:14:06 +05305158 for( i = 0, len = 0; i < request->n_channels ; i++ )
5159 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005160 channelList[i] = request->channels[i]->hw_value;
Nirav Shah20ac06f2013-12-12 18:14:06 +05305161 len += snprintf(chList+len, 5, "%d ", channelList[i]);
5162 }
5163
5164 hddLog(VOS_TRACE_LEVEL_INFO,
5165 "Channel-List: %s ", chList);
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 }
5167
5168 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
5169 scanRequest.ChannelInfo.ChannelList = channelList;
5170
5171 /* set requestType to full scan */
5172 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305173
5174 /* Flush the scan results(only p2p beacons) for STA scan and P2P
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005175 * search (Flush on both full scan and social scan but not on single
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305176 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005177 */
5178
5179 /* Supplicant does single channel scan after 8-way handshake
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305180 * and in that case driver shoudnt flush scan results. If
5181 * driver flushes the scan results here and unfortunately if
5182 * the AP doesnt respond to our probe req then association
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005183 * fails which is not desired
5184 */
5185
5186 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
5187 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305188 hddLog(VOS_TRACE_LEVEL_DEBUG, "Flushing P2P Results");
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005189 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
5190 pAdapter->sessionId );
5191 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005192
5193 if( request->ie_len )
5194 {
5195 /* save this for future association (join requires this) */
Agarwal Ashish4f616132013-12-30 23:32:50 +05305196 /*TODO: Array needs to be converted to dynamic allocation,
5197 * as multiple ie.s can be sent in cfg80211_scan_request structure
5198 * CR 597966
5199 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005200 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
5201 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
5202 pScanInfo->scanAddIE.length = request->ie_len;
5203
Agarwal Ashish4f616132013-12-30 23:32:50 +05305204 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07005205 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
Agarwal Ashish4f616132013-12-30 23:32:50 +05305206 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07005207 {
Agarwal Ashish4f616132013-12-30 23:32:50 +05305208 if ( request->ie_len <= SIR_MAC_MAX_IE_LENGTH)
5209 {
5210 pwextBuf->roamProfile.nAddIEScanLength = request->ie_len;
5211 memcpy( pwextBuf->roamProfile.addIEScan,
5212 request->ie, request->ie_len);
5213 }
5214 else
5215 {
5216 hddLog(VOS_TRACE_LEVEL_ERROR, "Scan Ie length is invalid:"
5217 "%d", request->ie_len);
5218 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005219
Agarwal Ashish4f616132013-12-30 23:32:50 +05305220 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
5222 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
5223
Jeff Johnson295189b2012-06-20 16:38:30 -07005224 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
5225 request->ie_len);
5226 if (pP2pIe != NULL)
5227 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07005228#ifdef WLAN_FEATURE_P2P_DEBUG
5229 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
5230 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
5231 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5232 {
5233 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
5234 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
5235 "Go nego completed to Connection is started");
5236 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
5237 "for 8way Handshake");
5238 }
5239 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
5240 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5241 {
5242 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
5243 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
5244 "Disconnected state to Connection is started");
5245 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
5246 "for 4way Handshake");
5247 }
5248#endif
5249
Jeff Johnsone7245742012-09-05 17:12:55 -07005250 /* no_cck will be set during p2p find to disable 11b rates */
5251 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07005252 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005253 hddLog(VOS_TRACE_LEVEL_INFO,
5254 "%s: This is a P2P Search", __func__);
5255 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07005256
Jeff Johnsone7245742012-09-05 17:12:55 -07005257 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
5258 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07005259 /* set requestType to P2P Discovery */
5260 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07005261 }
5262
5263 /*
5264 Skip Dfs Channel in case of P2P Search
5265 if it is set in ini file
5266 */
5267 if(cfg_param->skipDfsChnlInP2pSearch)
5268 {
5269 scanRequest.skipDfsChnlInP2pSearch = 1;
5270 }
5271 else
5272 {
5273 scanRequest.skipDfsChnlInP2pSearch = 0;
5274 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005275
Jeff Johnson295189b2012-06-20 16:38:30 -07005276 }
5277 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005278 }
5279 }
5280
5281 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
5282
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07005283 /* acquire the wakelock to avoid the apps suspend during the scan. To
5284 * address the following issues.
5285 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
5286 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
5287 * for long time, this result in apps running at full power for long time.
5288 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
5289 * be stuck in full power because of resume BMPS
5290 */
5291 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005292
Nirav Shah20ac06f2013-12-12 18:14:06 +05305293 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
5294 "requestType %d, scanType %d, minChnTime %d, maxChnTime %d,"
5295 "p2pSearch %d, skipDfsChnlInP2pSearch %d", scanRequest.requestType,
5296 scanRequest.scanType, scanRequest.minChnTime, scanRequest.maxChnTime,
5297 scanRequest.p2pSearch, scanRequest.skipDfsChnlInP2pSearch);
5298
Jeff Johnsone7245742012-09-05 17:12:55 -07005299 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005300 pAdapter->sessionId, &scanRequest, &scanId,
5301 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07005302
Jeff Johnson295189b2012-06-20 16:38:30 -07005303 if (eHAL_STATUS_SUCCESS != status)
5304 {
5305 hddLog(VOS_TRACE_LEVEL_ERROR,
5306 "%s: sme_ScanRequest returned error %d", __func__, status);
5307 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07005308 if(eHAL_STATUS_RESOURCES == status)
5309 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305310 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HO is in progress."
5311 "So defer the scan by informing busy",__func__);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07005312 status = -EBUSY;
5313 } else {
5314 status = -EIO;
5315 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07005316 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005317 goto free_mem;
5318 }
5319
5320 pScanInfo->mScanPending = TRUE;
5321 pAdapter->request = request;
5322 pScanInfo->scanId = scanId;
5323
5324 complete(&pScanInfo->scan_req_completion_event);
5325
5326free_mem:
5327 if( scanRequest.SSIDs.SSIDList )
5328 {
5329 vos_mem_free(scanRequest.SSIDs.SSIDList);
5330 }
5331
5332 if( channelList )
5333 vos_mem_free( channelList );
5334
5335 EXIT();
5336
5337 return status;
5338}
5339
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005340
5341void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
5342{
5343 v_U8_t iniDot11Mode =
5344 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
5345 eHddDot11Mode hddDot11Mode = iniDot11Mode;
5346
5347 switch ( iniDot11Mode )
5348 {
5349 case eHDD_DOT11_MODE_AUTO:
5350 case eHDD_DOT11_MODE_11ac:
5351 case eHDD_DOT11_MODE_11ac_ONLY:
5352#ifdef WLAN_FEATURE_11AC
5353 hddDot11Mode = eHDD_DOT11_MODE_11ac;
5354#else
5355 hddDot11Mode = eHDD_DOT11_MODE_11n;
5356#endif
5357 break;
5358 case eHDD_DOT11_MODE_11n:
5359 case eHDD_DOT11_MODE_11n_ONLY:
5360 hddDot11Mode = eHDD_DOT11_MODE_11n;
5361 break;
5362 default:
5363 hddDot11Mode = iniDot11Mode;
5364 break;
5365 }
5366 /* This call decides required channel bonding mode */
5367 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
5368 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
5369 operationChannel);
5370}
5371
Jeff Johnson295189b2012-06-20 16:38:30 -07005372/*
5373 * FUNCTION: wlan_hdd_cfg80211_connect_start
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305374 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -07005375 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305376int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005377 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07005378{
5379 int status = 0;
5380 hdd_wext_state_t *pWextState;
5381 v_U32_t roamId;
5382 tCsrRoamProfile *pRoamProfile;
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 eCsrAuthType RSNAuthType;
5384
5385 ENTER();
5386
5387 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305388
Jeff Johnson295189b2012-06-20 16:38:30 -07005389 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
5390 {
5391 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
5392 return -EINVAL;
5393 }
5394
5395 pRoamProfile = &pWextState->roamProfile;
5396
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305397 if (pRoamProfile)
Jeff Johnson295189b2012-06-20 16:38:30 -07005398 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005399 hdd_station_ctx_t *pHddStaCtx;
5400 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005401
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305402 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07005403 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
5404 {
5405 /*QoS not enabled in cfg file*/
5406 pRoamProfile->uapsd_mask = 0;
5407 }
5408 else
5409 {
5410 /*QoS enabled, update uapsd mask from cfg file*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305411 pRoamProfile->uapsd_mask =
Jeff Johnson295189b2012-06-20 16:38:30 -07005412 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
5413 }
5414
5415 pRoamProfile->SSIDs.numOfSSIDs = 1;
5416 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
5417 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305418 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Jeff Johnson295189b2012-06-20 16:38:30 -07005419 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
5420 ssid, ssid_len);
5421
5422 if (bssid)
5423 {
5424 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
5425 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
5426 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305427 /* Save BSSID in seperate variable as well, as RoamProfile
5428 BSSID is getting zeroed out in the association process. And in
Jeff Johnson295189b2012-06-20 16:38:30 -07005429 case of join failure we should send valid BSSID to supplicant
5430 */
5431 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
5432 WNI_CFG_BSSID_LEN);
5433 }
Dhanashri Atre51981c62013-06-13 11:47:57 -07005434 else
5435 {
5436 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
5437 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005438
5439 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
5440 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305441 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 /*set gen ie*/
5443 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
5444 /*set auth*/
5445 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
5446 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005447#ifdef FEATURE_WLAN_WAPI
5448 if (pAdapter->wapi_info.nWapiMode)
5449 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005450 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005451 switch (pAdapter->wapi_info.wapiAuthMode)
5452 {
5453 case WAPI_AUTH_MODE_PSK:
5454 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005455 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 pAdapter->wapi_info.wapiAuthMode);
5457 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
5458 break;
5459 }
5460 case WAPI_AUTH_MODE_CERT:
5461 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005462 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005463 pAdapter->wapi_info.wapiAuthMode);
5464 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
5465 break;
5466 }
5467 } // End of switch
5468 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
5469 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
5470 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005471 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005472 pRoamProfile->AuthType.numEntries = 1;
5473 pRoamProfile->EncryptionType.numEntries = 1;
5474 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5475 pRoamProfile->mcEncryptionType.numEntries = 1;
5476 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5477 }
5478 }
5479#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305480#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305481 /* Initializing gtkOffloadReqParams */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305482 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5483 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5484 {
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305485 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
5486 sizeof (tSirGtkOffloadParams));
5487 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305488 }
5489#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005490 pRoamProfile->csrPersona = pAdapter->device_mode;
5491
Jeff Johnson32d95a32012-09-10 13:15:23 -07005492 if( operatingChannel )
5493 {
5494 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
5495 pRoamProfile->ChannelInfo.numOfChannels = 1;
5496 }
Chet Lanctot186b5732013-03-18 10:26:30 -07005497 else
5498 {
5499 pRoamProfile->ChannelInfo.ChannelList = NULL;
5500 pRoamProfile->ChannelInfo.numOfChannels = 0;
5501 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005502 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
5503 {
5504 hdd_select_cbmode(pAdapter,operatingChannel);
5505 }
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005506 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
5507 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305508 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005509 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005510 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
5511 */
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305512 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5513 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005514 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
5515 eConnectionState_Connecting);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305516
5517 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005518 pAdapter->sessionId, pRoamProfile, &roamId);
5519
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305520 if ((eHAL_STATUS_SUCCESS != status) &&
5521 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5522 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305523
5524 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005525 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
5526 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
5527 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305528 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005529 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305530 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005531
5532 pRoamProfile->ChannelInfo.ChannelList = NULL;
5533 pRoamProfile->ChannelInfo.numOfChannels = 0;
5534
Jeff Johnson295189b2012-06-20 16:38:30 -07005535 }
5536 else
5537 {
5538 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
5539 return -EINVAL;
5540 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005541 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005542 return status;
5543}
5544
5545/*
5546 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
5547 * This function is used to set the authentication type (OPEN/SHARED).
5548 *
5549 */
5550static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
5551 enum nl80211_auth_type auth_type)
5552{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305553 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005554 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5555
5556 ENTER();
5557
5558 /*set authentication type*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305559 switch (auth_type)
Jeff Johnson295189b2012-06-20 16:38:30 -07005560 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005561 case NL80211_AUTHTYPE_AUTOMATIC:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305562 hddLog(VOS_TRACE_LEVEL_INFO,
5563 "%s: set authentication type to AUTOSWITCH", __func__);
5564 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
5565 break;
5566
5567 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07005568#ifdef WLAN_FEATURE_VOWIFI_11R
5569 case NL80211_AUTHTYPE_FT:
5570#endif /* WLAN_FEATURE_VOWIFI_11R */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305571 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005572 "%s: set authentication type to OPEN", __func__);
5573 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5574 break;
5575
5576 case NL80211_AUTHTYPE_SHARED_KEY:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305577 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 "%s: set authentication type to SHARED", __func__);
5579 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
5580 break;
5581#ifdef FEATURE_WLAN_CCX
5582 case NL80211_AUTHTYPE_NETWORK_EAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305583 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005584 "%s: set authentication type to CCKM WPA", __func__);
5585 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
5586 break;
5587#endif
5588
5589
5590 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305591 hddLog(VOS_TRACE_LEVEL_ERROR,
5592 "%s: Unsupported authentication type %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005593 auth_type);
5594 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
5595 return -EINVAL;
5596 }
5597
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305598 pWextState->roamProfile.AuthType.authType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005599 pHddStaCtx->conn_info.authType;
5600 return 0;
5601}
5602
5603/*
5604 * FUNCTION: wlan_hdd_set_akm_suite
5605 * This function is used to set the key mgmt type(PSK/8021x).
5606 *
5607 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305608static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005609 u32 key_mgmt
5610 )
5611{
5612 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5613 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305614
Jeff Johnson295189b2012-06-20 16:38:30 -07005615 /*set key mgmt type*/
5616 switch(key_mgmt)
5617 {
5618 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305619#ifdef WLAN_FEATURE_VOWIFI_11R
5620 case WLAN_AKM_SUITE_FT_PSK:
5621#endif
5622 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 __func__);
5624 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5625 break;
5626
5627 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305628#ifdef WLAN_FEATURE_VOWIFI_11R
5629 case WLAN_AKM_SUITE_FT_8021X:
5630#endif
5631 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005632 __func__);
5633 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5634 break;
5635#ifdef FEATURE_WLAN_CCX
5636#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5637#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5638 case WLAN_AKM_SUITE_CCKM:
5639 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5640 __func__);
5641 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5642 break;
5643#endif
5644
5645 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305646 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005647 __func__, key_mgmt);
5648 return -EINVAL;
5649
5650 }
5651 return 0;
5652}
5653
5654/*
5655 * FUNCTION: wlan_hdd_cfg80211_set_cipher
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305656 * This function is used to set the encryption type
Jeff Johnson295189b2012-06-20 16:38:30 -07005657 * (NONE/WEP40/WEP104/TKIP/CCMP).
5658 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305659static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5660 u32 cipher,
Jeff Johnson295189b2012-06-20 16:38:30 -07005661 bool ucast
5662 )
5663{
5664 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305665 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005666 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5667
5668 ENTER();
5669
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305670 if (!cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005671 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305672 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
Jeff Johnson295189b2012-06-20 16:38:30 -07005673 __func__, cipher);
5674 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5675 }
5676 else
5677 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305678
Jeff Johnson295189b2012-06-20 16:38:30 -07005679 /*set encryption method*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305680 switch (cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005681 {
5682 case IW_AUTH_CIPHER_NONE:
5683 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5684 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305685
Jeff Johnson295189b2012-06-20 16:38:30 -07005686 case WLAN_CIPHER_SUITE_WEP40:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305687 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson295189b2012-06-20 16:38:30 -07005688 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305689
Jeff Johnson295189b2012-06-20 16:38:30 -07005690 case WLAN_CIPHER_SUITE_WEP104:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305691 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
Jeff Johnson295189b2012-06-20 16:38:30 -07005692 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305693
Jeff Johnson295189b2012-06-20 16:38:30 -07005694 case WLAN_CIPHER_SUITE_TKIP:
5695 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5696 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305697
Jeff Johnson295189b2012-06-20 16:38:30 -07005698 case WLAN_CIPHER_SUITE_CCMP:
5699 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5700 break;
5701#ifdef FEATURE_WLAN_WAPI
5702 case WLAN_CIPHER_SUITE_SMS4:
5703 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5704 break;
5705#endif
5706
5707#ifdef FEATURE_WLAN_CCX
5708 case WLAN_CIPHER_SUITE_KRK:
5709 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5710 break;
5711#endif
5712 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305713 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005714 __func__, cipher);
5715 return -EOPNOTSUPP;
5716 }
5717 }
5718
5719 if (ucast)
5720 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305721 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005722 __func__, encryptionType);
5723 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5724 pWextState->roamProfile.EncryptionType.numEntries = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305725 pWextState->roamProfile.EncryptionType.encryptionType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005726 encryptionType;
5727 }
5728 else
5729 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305730 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005731 __func__, encryptionType);
5732 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5733 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5734 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5735 }
5736
5737 return 0;
5738}
5739
5740
5741/*
5742 * FUNCTION: wlan_hdd_cfg80211_set_ie
5743 * This function is used to parse WPA/RSN IE's.
5744 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305745int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5746 u8 *ie,
Jeff Johnson295189b2012-06-20 16:38:30 -07005747 size_t ie_len
5748 )
5749{
5750 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5751 u8 *genie = ie;
5752 v_U16_t remLen = ie_len;
5753#ifdef FEATURE_WLAN_WAPI
5754 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5755 u16 *tmp;
5756 v_U16_t akmsuiteCount;
5757 int *akmlist;
5758#endif
5759 ENTER();
5760
5761 /* clear previous assocAddIE */
5762 pWextState->assocAddIE.length = 0;
5763 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5764
5765 while (remLen >= 2)
5766 {
5767 v_U16_t eLen = 0;
5768 v_U8_t elementId;
5769 elementId = *genie++;
5770 eLen = *genie++;
5771 remLen -= 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305772
Arif Hussain6d2a3322013-11-17 19:50:10 -08005773 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005774 __func__, elementId, eLen);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305775
5776 switch ( elementId )
Jeff Johnson295189b2012-06-20 16:38:30 -07005777 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305778 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005779 if (4 > eLen) /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005780 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305781 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005782 "%s: Invalid WPA IE", __func__);
5783 return -EINVAL;
5784 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305785 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
Jeff Johnson295189b2012-06-20 16:38:30 -07005786 {
5787 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305788 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005789 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305790
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5792 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005793 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5794 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005795 VOS_ASSERT(0);
5796 return -ENOMEM;
5797 }
5798 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5799 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5800 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305801
Jeff Johnson295189b2012-06-20 16:38:30 -07005802 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5803 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5804 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5805 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305806 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5807 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005808 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5809 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5810 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5811 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5812 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5813 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305814 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
Kiet Lam8da98992013-11-21 15:59:07 +05305815 P2P_OUI_TYPE_SIZE)))
Jeff Johnson295189b2012-06-20 16:38:30 -07005816 {
5817 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305818 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005819 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305820
Jeff Johnson295189b2012-06-20 16:38:30 -07005821 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5822 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005823 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5824 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005825 VOS_ASSERT(0);
5826 return -ENOMEM;
5827 }
5828 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5829 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5830 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305831
Jeff Johnson295189b2012-06-20 16:38:30 -07005832 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5833 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5834 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005835#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305836 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5837 WFD_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 /*Consider WFD IE, only for P2P Client */
5839 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5840 {
5841 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305842 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005843 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305844
Jeff Johnson295189b2012-06-20 16:38:30 -07005845 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5846 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005847 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5848 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005849 VOS_ASSERT(0);
5850 return -ENOMEM;
5851 }
5852 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5853 // WPS IE + P2P IE + WFD IE
5854 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5855 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305856
Jeff Johnson295189b2012-06-20 16:38:30 -07005857 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5858 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5859 }
5860#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005861 /* Appending HS 2.0 Indication Element in Assiciation Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305862 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005863 HS20_OUI_TYPE_SIZE)) )
5864 {
5865 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305866 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005867 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005868
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005869 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5870 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005871 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5872 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005873 VOS_ASSERT(0);
5874 return -ENOMEM;
5875 }
5876 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5877 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005878
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005879 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5880 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5881 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005882
Praveen Kumar Sirisilla7d68b7b2013-09-22 14:01:42 -07005883 if (WLAN_HDD_IBSS == pAdapter->device_mode) {
5884
5885 /* populating as ADDIE in beacon frames */
5886 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5887 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie - 2, eLen + 2,
5888 NULL, eANI_BOOLEAN_FALSE)== eHAL_STATUS_SUCCESS)
5889 {
5890 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5891 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5892 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5893 {
5894 hddLog(LOGE,
5895 "Coldn't pass "
5896 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
5897 }
5898 }/* ccmCfgSetStr(,WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, , )*/
5899 else
5900 hddLog(LOGE,
5901 "Could not pass on "
5902 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
5903
5904 /* IBSS mode doesn't contain params->proberesp_ies still
5905 beaconIE's need to be populated in probe response frames */
5906 if ( (NULL != (genie - 2)) && (0 != eLen + 2) )
5907 {
5908 u16 rem_probe_resp_ie_len = eLen + 2;
5909 u8 probe_rsp_ie_len[3] = {0};
5910 u8 counter = 0;
5911
5912 /* Check Probe Resp Length if it is greater then 255 then
5913 Store Probe Rsp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1
5914 & WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are
5915 not able Store More then 255 bytes into One Variable */
5916
5917 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
5918 {
5919 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
5920 {
5921 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
5922 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
5923 }
5924 else
5925 {
5926 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
5927 rem_probe_resp_ie_len = 0;
5928 }
5929 }
5930
5931 rem_probe_resp_ie_len = 0;
5932
5933 if (probe_rsp_ie_len[0] > 0)
5934 {
5935 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5936 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5937 (tANI_U8*)(genie - 2),
5938 probe_rsp_ie_len[0], NULL,
5939 eANI_BOOLEAN_FALSE)
5940 == eHAL_STATUS_FAILURE)
5941 {
5942 hddLog(LOGE,
5943 "Could not pass"
5944 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
5945 }
5946 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
5947 }
5948
5949 if (probe_rsp_ie_len[1] > 0)
5950 {
5951 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5952 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
5953 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
5954 probe_rsp_ie_len[1], NULL,
5955 eANI_BOOLEAN_FALSE)
5956 == eHAL_STATUS_FAILURE)
5957 {
5958 hddLog(LOGE,
5959 "Could not pass"
5960 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
5961 }
5962 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
5963 }
5964
5965 if (probe_rsp_ie_len[2] > 0)
5966 {
5967 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5968 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
5969 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
5970 probe_rsp_ie_len[2], NULL,
5971 eANI_BOOLEAN_FALSE)
5972 == eHAL_STATUS_FAILURE)
5973 {
5974 hddLog(LOGE,
5975 "Could not pass"
5976 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
5977 }
5978 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
5979 }
5980
5981 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5982 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5983 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5984 {
5985 hddLog(LOGE,
5986 "Could not pass"
5987 "on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
5988 }
5989 }
5990 else
5991 {
5992 // Reset WNI_CFG_PROBE_RSP Flags
5993 wlan_hdd_reset_prob_rspies(pAdapter);
5994
5995 hddLog(VOS_TRACE_LEVEL_INFO,
5996 "%s: No Probe Response IE received in set beacon",
5997 __func__);
5998 }
5999 } /* end of if (WLAN_HDD_IBSS == pAdapter->device_mode) */
Jeff Johnson295189b2012-06-20 16:38:30 -07006000 break;
6001 case DOT11F_EID_RSN:
6002 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
6003 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
6004 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
6005 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
6006 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
6007 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006008 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
6009 case DOT11F_EID_EXTCAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306010 {
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006011 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306012 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006013 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306014
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006015 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
6016 {
Jeff Johnson902c9832012-12-10 14:28:09 -08006017 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
6018 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006019 VOS_ASSERT(0);
6020 return -ENOMEM;
6021 }
6022 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
6023 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306024
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006025 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
6026 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
6027 break;
6028 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006029#ifdef FEATURE_WLAN_WAPI
6030 case WLAN_EID_WAPI:
6031 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006032 hddLog(VOS_TRACE_LEVEL_INFO, "WAPI MODE IS %u",
Jeff Johnson295189b2012-06-20 16:38:30 -07006033 pAdapter->wapi_info.nWapiMode);
6034 tmp = (u16 *)ie;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306035 tmp = tmp + 2; // Skip element Id and Len, Version
Jeff Johnson295189b2012-06-20 16:38:30 -07006036 akmsuiteCount = WPA_GET_LE16(tmp);
6037 tmp = tmp + 1;
6038 akmlist = (int *)(tmp);
6039 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
6040 {
6041 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
6042 }
6043 else
6044 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006045 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count");
Jeff Johnson295189b2012-06-20 16:38:30 -07006046 VOS_ASSERT(0);
6047 return -EINVAL;
6048 }
6049
6050 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
6051 {
6052 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006053 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306055 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006056 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306057 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006058 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006059 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006060 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
6061 }
6062 break;
6063#endif
6064 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306065 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006066 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006067 /* when Unknown IE is received we should break and continue
6068 * to the next IE in the buffer instead we were returning
6069 * so changing this to break */
6070 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006071 }
6072 genie += eLen;
6073 remLen -= eLen;
6074 }
6075 EXIT();
6076 return 0;
6077}
6078
6079/*
Gopichand Nakkala18f0c262013-05-07 23:25:08 +05306080 * FUNCTION: hdd_isWPAIEPresent
6081 * Parse the received IE to find the WPA IE
6082 *
6083 */
6084static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len)
6085{
6086 v_U8_t eLen = 0;
6087 v_U16_t remLen = ie_len;
6088 v_U8_t elementId = 0;
6089
6090 while (remLen >= 2)
6091 {
6092 elementId = *ie++;
6093 eLen = *ie++;
6094 remLen -= 2;
6095 if (eLen > remLen)
6096 {
6097 hddLog(VOS_TRACE_LEVEL_ERROR,
6098 "%s: IE length is wrong %d", __func__, eLen);
6099 return FALSE;
6100 }
6101 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
6102 {
6103 /* OUI - 0x00 0X50 0XF2
6104 WPA Information Element - 0x01
6105 WPA version - 0x01*/
6106 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
6107 return TRUE;
6108 }
6109 ie += eLen;
6110 remLen -= eLen;
6111 }
6112 return FALSE;
6113}
6114
6115/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006116 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306117 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006118 * parameters during connect operation.
6119 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306120int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07006121 struct cfg80211_connect_params *req
6122 )
6123{
6124 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306125 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006126 ENTER();
6127
6128 /*set wpa version*/
6129 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
6130
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306131 if (req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07006132 {
Gopichand Nakkala781ded42013-06-28 12:10:45 +05306133 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07006134 {
6135 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
6136 }
6137 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
6138 {
6139 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
6140 }
6141 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306142
6143 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 pWextState->wpaVersion);
6145
6146 /*set authentication type*/
6147 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
6148
6149 if (0 > status)
6150 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306151 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 "%s: failed to set authentication type ", __func__);
6153 return status;
6154 }
6155
6156 /*set key mgmt type*/
6157 if (req->crypto.n_akm_suites)
6158 {
6159 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
6160 if (0 > status)
6161 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306162 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 __func__);
6164 return status;
6165 }
6166 }
6167
6168 /*set pairwise cipher type*/
6169 if (req->crypto.n_ciphers_pairwise)
6170 {
6171 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
6172 req->crypto.ciphers_pairwise[0], true);
6173 if (0 > status)
6174 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306175 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006176 "%s: failed to set unicast cipher type", __func__);
6177 return status;
6178 }
6179 }
6180 else
6181 {
6182 /*Reset previous cipher suite to none*/
6183 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
6184 if (0 > status)
6185 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306186 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006187 "%s: failed to set unicast cipher type", __func__);
6188 return status;
6189 }
6190 }
6191
6192 /*set group cipher type*/
6193 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
6194 false);
6195
6196 if (0 > status)
6197 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306198 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
Jeff Johnson295189b2012-06-20 16:38:30 -07006199 __func__);
6200 return status;
6201 }
6202
Chet Lanctot186b5732013-03-18 10:26:30 -07006203#ifdef WLAN_FEATURE_11W
6204 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
6205#endif
6206
Jeff Johnson295189b2012-06-20 16:38:30 -07006207 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
6208 if (req->ie_len)
6209 {
6210 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
6211 if ( 0 > status)
6212 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306213 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006214 __func__);
6215 return status;
6216 }
6217 }
6218
6219 /*incase of WEP set default key information*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306220 if (req->key && req->key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07006221 {
6222 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
6223 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
6224 )
6225 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306226 if ( IW_AUTH_KEY_MGMT_802_1X
Jeff Johnson295189b2012-06-20 16:38:30 -07006227 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
6228 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306229 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 __func__);
6231 return -EOPNOTSUPP;
6232 }
6233 else
6234 {
6235 u8 key_len = req->key_len;
6236 u8 key_idx = req->key_idx;
6237
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306238 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07006239 && (CSR_MAX_NUM_KEY > key_idx)
6240 )
6241 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306242 hddLog(VOS_TRACE_LEVEL_INFO,
6243 "%s: setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006244 __func__, key_idx, key_len);
6245 vos_mem_copy(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306246 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07006247 req->key, key_len);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306248 pWextState->roamProfile.Keys.KeyLength[key_idx] =
Jeff Johnson295189b2012-06-20 16:38:30 -07006249 (u8)key_len;
6250 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
6251 }
6252 }
6253 }
6254 }
6255
6256 return status;
6257}
6258
6259/*
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306260 * FUNCTION: wlan_hdd_try_disconnect
6261 * This function is used to disconnect from previous
6262 * connection
6263 */
6264static int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter )
6265{
6266 long ret = 0;
6267 hdd_station_ctx_t *pHddStaCtx;
6268 eMib_dot11DesiredBssType connectedBssType;
6269
6270 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6271
6272 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
6273
6274 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
6275 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
6276 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
6277 {
6278 /* Issue disconnect to CSR */
6279 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6280 if( eHAL_STATUS_SUCCESS ==
6281 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
6282 pAdapter->sessionId,
6283 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
6284 {
6285 ret = wait_for_completion_interruptible_timeout(
6286 &pAdapter->disconnect_comp_var,
6287 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6288 if (0 >= ret)
6289 {
6290 hddLog(LOGE, FL("Failed to receive disconnect event"));
6291 return -EALREADY;
6292 }
6293 }
6294 }
6295 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
6296 {
6297 ret = wait_for_completion_interruptible_timeout(
6298 &pAdapter->disconnect_comp_var,
6299 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6300 if (0 >= ret)
6301 {
6302 hddLog(LOGE, FL("Failed to receive disconnect event"));
6303 return -EALREADY;
6304 }
6305 }
6306
6307 return 0;
6308}
6309
6310/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006311 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306312 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006313 * parameters during connect operation.
6314 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306315static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006316 struct net_device *ndev,
6317 struct cfg80211_connect_params *req
6318 )
6319{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306320 int status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306321 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006322 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
6323 hdd_context_t *pHddCtx = NULL;
6324
6325 ENTER();
6326
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306327 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006328 "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006329
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306330 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6331 status = wlan_hdd_validate_context(pHddCtx);
6332
6333 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006334 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6336 "%s: HDD context is not valid", __func__);
6337 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006338 }
6339
6340#ifdef WLAN_BTAMP_FEATURE
6341 //Infra connect not supported when AMP traffic is on.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306342 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07006343 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306344 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006345 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006346 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07006347 }
6348#endif
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306349
6350 //If Device Mode is Station Concurrent Sessions Exit BMps
6351 //P2P Mode will be taken care in Open/close adapter
6352 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
6353 (vos_concurrent_sessions_running()))
6354 {
6355 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
6356 }
6357
6358 /*Try disconnecting if already in connected state*/
6359 status = wlan_hdd_try_disconnect(pAdapter);
6360 if ( 0 > status)
6361 {
6362 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
6363 " connection"));
6364 return -EALREADY;
6365 }
6366
Jeff Johnson295189b2012-06-20 16:38:30 -07006367 /*initialise security parameters*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306368 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
Jeff Johnson295189b2012-06-20 16:38:30 -07006369
6370 if ( 0 > status)
6371 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306372 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
Jeff Johnson295189b2012-06-20 16:38:30 -07006373 __func__);
6374 return status;
6375 }
6376
Mohit Khanna765234a2012-09-11 15:08:35 -07006377 if ( req->channel )
6378 {
6379 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
6380 req->ssid_len, req->bssid,
6381 req->channel->hw_value);
6382 }
6383 else
6384 {
6385 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306386 req->ssid_len, req->bssid, 0);
Mohit Khanna765234a2012-09-11 15:08:35 -07006387 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006388
6389 if (0 > status)
6390 {
6391 //ReEnable BMPS if disabled
6392 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
6393 (NULL != pHddCtx))
6394 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306395 if (pHddCtx->hdd_wlan_suspended)
6396 {
6397 hdd_set_pwrparams(pHddCtx);
6398 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006399 //ReEnable Bmps and Imps back
6400 hdd_enable_bmps_imps(pHddCtx);
6401 }
6402
6403 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6404 return status;
6405 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306406 pHddCtx->isAmpAllowed = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006407 EXIT();
6408 return status;
6409}
6410
6411
6412/*
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306413 * FUNCTION: wlan_hdd_disconnect
6414 * This function is used to issue a disconnect request to SME
6415 */
6416int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
6417{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306418 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306419 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306420 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306421 long ret;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306422
6423 status = wlan_hdd_validate_context(pHddCtx);
6424
6425 if (0 != status)
6426 {
6427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6428 "%s: HDD context is not valid", __func__);
6429 return status;
6430 }
6431
6432 pHddCtx->isAmpAllowed = VOS_TRUE;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306433 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306434 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306435
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306436 /*issue disconnect*/
6437 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
6438 pAdapter->sessionId, reason);
6439
6440 if ( 0 != status )
6441 {
6442 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006443 "%s csrRoamDisconnect failure, returned %d",
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306444 __func__, (int)status );
6445 return -EINVAL;
6446 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306447 ret = wait_for_completion_interruptible_timeout(
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306448 &pAdapter->disconnect_comp_var,
6449 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306450 if (ret <= 0)
6451 {
6452 hddLog(VOS_TRACE_LEVEL_ERROR,
6453 FL("wait on disconnect_comp_var failed %ld"), ret);
6454 }
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306455 /*stop tx queues*/
6456 netif_tx_disable(pAdapter->dev);
6457 netif_carrier_off(pAdapter->dev);
6458 return status;
6459}
6460
6461
6462/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006463 * FUNCTION: wlan_hdd_cfg80211_disconnect
6464 * This function is used to issue a disconnect request to SME
6465 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306466static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006467 struct net_device *dev,
6468 u16 reason
6469 )
6470{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306471 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6472 tCsrRoamProfile *pRoamProfile =
Jeff Johnson295189b2012-06-20 16:38:30 -07006473 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306474 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006475 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006476 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306477#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006478 tANI_U8 staIdx;
6479#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306480
Jeff Johnson295189b2012-06-20 16:38:30 -07006481 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306482
Arif Hussain6d2a3322013-11-17 19:50:10 -08006483 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006484 __func__,pAdapter->device_mode);
6485
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306486 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
6487 __func__, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07006488
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306489 status = wlan_hdd_validate_context(pHddCtx);
6490
6491 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006492 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6494 "%s: HDD context is not valid", __func__);
6495 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006496 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306497
Jeff Johnson295189b2012-06-20 16:38:30 -07006498 if (NULL != pRoamProfile)
6499 {
6500 /*issue disconnect request to SME, if station is in connected state*/
Mahesh A Saptasagar280fd5a2013-12-05 15:38:31 +05306501 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
6502 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting))
Jeff Johnson295189b2012-06-20 16:38:30 -07006503 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306504 eCsrRoamDisconnectReason reasonCode =
Jeff Johnson295189b2012-06-20 16:38:30 -07006505 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306506 hdd_scaninfo_t *pScanInfo;
Jeff Johnson295189b2012-06-20 16:38:30 -07006507 switch(reason)
6508 {
6509 case WLAN_REASON_MIC_FAILURE:
6510 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
6511 break;
6512
6513 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
6514 case WLAN_REASON_DISASSOC_AP_BUSY:
6515 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
6516 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
6517 break;
6518
6519 case WLAN_REASON_PREV_AUTH_NOT_VALID:
6520 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
6521 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
6522 break;
6523
6524 case WLAN_REASON_DEAUTH_LEAVING:
6525 default:
6526 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
6527 break;
6528 }
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306529 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6530 pScanInfo = &pHddCtx->scan_info;
6531 if (pScanInfo->mScanPending)
6532 {
6533 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
6534 "Aborting Scan");
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306535 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306536 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006537
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006538#ifdef FEATURE_WLAN_TDLS
6539 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006540 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006541 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006542 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
6543 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006544 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006545 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006546 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006547 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006548 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006549 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006550 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006551 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006552 pAdapter->sessionId,
6553 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006554 }
6555 }
6556#endif
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306557 status = wlan_hdd_disconnect(pAdapter, reasonCode);
6558 if ( 0 != status )
Jeff Johnson295189b2012-06-20 16:38:30 -07006559 {
6560 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006561 "%s wlan_hdd_disconnect failure, returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006562 __func__, (int)status );
6563 return -EINVAL;
6564 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006565 }
Mahesh A Saptasagar280fd5a2013-12-05 15:38:31 +05306566 else
6567 {
6568 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unexpected cfg disconnect API"
6569 "called while in %d state", __func__,
6570 pHddStaCtx->conn_info.connState);
6571 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006572 }
6573 else
6574 {
6575 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
6576 }
6577
6578 return status;
6579}
6580
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306581
Jeff Johnson295189b2012-06-20 16:38:30 -07006582/*
6583 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306584 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006585 * settings in IBSS mode.
6586 */
6587static int wlan_hdd_cfg80211_set_privacy_ibss(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306588 hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07006589 struct cfg80211_ibss_params *params
6590 )
6591{
6592 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306593 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006594 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
6595 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306596
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 ENTER();
6598
6599 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Ravi Joshib58ca0d2013-10-29 09:50:23 -07006600 vos_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -07006601
6602 if (params->ie_len && ( NULL != params->ie) )
6603 {
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006604 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6605 params->ie_len, WLAN_EID_RSN ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006606 {
6607 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
6608 encryptionType = eCSR_ENCRYPT_TYPE_AES;
6609 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006610 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006611 {
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006612 tDot11fIEWPA dot11WPAIE;
6613 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006614 u8 *ie;
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006615
Wilson Yang00256342013-10-10 23:13:38 -07006616 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006617 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6618 params->ie_len, DOT11F_EID_WPA);
6619 if ( NULL != ie )
6620 {
6621 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
6622 // Unpack the WPA IE
6623 //Skip past the EID byte and length byte - and four byte WiFi OUI
6624 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
6625 &ie[2+4],
6626 ie[1] - 4,
6627 &dot11WPAIE);
6628 /*Extract the multicast cipher, the encType for unicast
6629 cipher for wpa-none is none*/
6630 encryptionType =
6631 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
6632 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006633 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006634
Jeff Johnson295189b2012-06-20 16:38:30 -07006635 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
6636
6637 if (0 > status)
6638 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306639 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006640 __func__);
6641 return status;
6642 }
6643 }
6644
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306645 pWextState->roamProfile.AuthType.authType[0] =
6646 pHddStaCtx->conn_info.authType =
Jeff Johnson295189b2012-06-20 16:38:30 -07006647 eCSR_AUTH_TYPE_OPEN_SYSTEM;
6648
6649 if (params->privacy)
6650 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306651 /* Security enabled IBSS, At this time there is no information available
6652 * about the security paramters, so initialise the encryption type to
Jeff Johnson295189b2012-06-20 16:38:30 -07006653 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306654 * The correct security parameters will be updated later in
Jeff Johnson295189b2012-06-20 16:38:30 -07006655 * wlan_hdd_cfg80211_add_key */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306656 /* Hal expects encryption type to be set inorder
Jeff Johnson295189b2012-06-20 16:38:30 -07006657 *enable privacy bit in beacons */
6658
6659 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6660 }
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006661 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6662 "encryptionType=%d", encryptionType);
Jeff Johnson295189b2012-06-20 16:38:30 -07006663 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
6664 pWextState->roamProfile.EncryptionType.numEntries = 1;
6665 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
Jeff Johnson295189b2012-06-20 16:38:30 -07006666 return status;
6667}
6668
6669/*
6670 * FUNCTION: wlan_hdd_cfg80211_join_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306671 * This function is used to create/join an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006672 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306673static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006674 struct net_device *dev,
6675 struct cfg80211_ibss_params *params
6676 )
6677{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306678 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006679 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6680 tCsrRoamProfile *pRoamProfile;
6681 int status;
krunal sonie9002db2013-11-25 14:24:17 -08006682 bool alloc_bssid = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006683 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306684 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006685
6686 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306687
6688 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006689 "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006690
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306691 status = wlan_hdd_validate_context(pHddCtx);
6692
6693 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006694 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6696 "%s: HDD context is not valid", __func__);
6697 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006698 }
6699
6700 if (NULL == pWextState)
6701 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006702 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
Jeff Johnson295189b2012-06-20 16:38:30 -07006703 __func__);
6704 return -EIO;
6705 }
6706
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306707 /*Try disconnecting if already in connected state*/
6708 status = wlan_hdd_try_disconnect(pAdapter);
6709 if ( 0 > status)
6710 {
6711 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
6712 " IBSS connection"));
6713 return -EALREADY;
6714 }
6715
Jeff Johnson295189b2012-06-20 16:38:30 -07006716 pRoamProfile = &pWextState->roamProfile;
6717
6718 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
6719 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306720 hddLog (VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006721 "%s Interface type is not set to IBSS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006722 return -EINVAL;
6723 }
6724
Praveen Kumar Sirisillad123d142013-09-24 16:50:13 -07006725 /* BSSID is provided by upper layers hence no need to AUTO generate */
6726 if (NULL != params->bssid) {
6727 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
6728 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) {
6729 hddLog (VOS_TRACE_LEVEL_ERROR,
6730 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
6731 return -EIO;
6732 }
6733 }
krunal sonie9002db2013-11-25 14:24:17 -08006734 else if(pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0)
6735 {
6736 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
6737 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
6738 {
6739 hddLog (VOS_TRACE_LEVEL_ERROR,
6740 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
6741 return -EIO;
6742 }
6743 params->bssid = vos_mem_malloc(sizeof(VOS_MAC_ADDR_SIZE));
6744 if (!params->bssid)
6745 {
6746 hddLog (VOS_TRACE_LEVEL_ERROR,
6747 "%s:Failed memory allocation", __func__);
6748 return -EIO;
6749 }
6750 vos_mem_copy((v_U8_t *)params->bssid,
6751 (v_U8_t *)&pHddCtx->cfg_ini->IbssBssid.bytes[0],
6752 VOS_MAC_ADDR_SIZE);
6753 alloc_bssid = VOS_TRUE;
6754 }
Praveen Kumar Sirisillad123d142013-09-24 16:50:13 -07006755
Jeff Johnson295189b2012-06-20 16:38:30 -07006756 /* Set Channel */
Yue Maf49ba872013-08-19 12:04:25 -07006757 if (NULL !=
6758#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6759 params->chandef.chan)
6760#else
6761 params->channel)
6762#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006763 {
6764 u8 channelNum;
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006765 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6766 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6767 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6768 int indx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006769
6770 /* Get channel number */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306771 channelNum =
Yue Maf49ba872013-08-19 12:04:25 -07006772 ieee80211_frequency_to_channel(
6773#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6774 params->chandef.chan->center_freq);
6775#else
6776 params->channel->center_freq);
6777#endif
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006778
6779 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6780 validChan, &numChans))
Jeff Johnson295189b2012-06-20 16:38:30 -07006781 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006782 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
6783 __func__);
6784 return -EOPNOTSUPP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006785 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006786
6787 for (indx = 0; indx < numChans; indx++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006788 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006789 if (channelNum == validChan[indx])
6790 {
6791 break;
6792 }
6793 }
6794 if (indx >= numChans)
6795 {
6796 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006797 __func__, channelNum);
6798 return -EINVAL;
6799 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006800 /* Set the Operational Channel */
6801 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
6802 channelNum);
6803 pRoamProfile->ChannelInfo.numOfChannels = 1;
6804 pHddStaCtx->conn_info.operationChannel = channelNum;
6805 pRoamProfile->ChannelInfo.ChannelList =
6806 &pHddStaCtx->conn_info.operationChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -07006807 }
6808
6809 /* Initialize security parameters */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306810 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
Jeff Johnson295189b2012-06-20 16:38:30 -07006811 if (status < 0)
6812 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306813 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
Jeff Johnson295189b2012-06-20 16:38:30 -07006814 __func__);
6815 return status;
6816 }
6817
6818 /* Issue connect start */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306819 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006820 params->ssid_len, params->bssid,
6821 pHddStaCtx->conn_info.operationChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07006822
6823 if (0 > status)
6824 {
6825 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6826 return status;
6827 }
6828
krunal sonie9002db2013-11-25 14:24:17 -08006829 if (NULL != params->bssid &&
6830 pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0 &&
6831 alloc_bssid == VOS_TRUE)
6832 {
6833 vos_mem_free(params->bssid);
6834 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006835 return 0;
6836}
6837
6838/*
6839 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306840 * This function is used to leave an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006841 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306842static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006843 struct net_device *dev
6844 )
6845{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306846 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006847 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6848 tCsrRoamProfile *pRoamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306849 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6850 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006851
6852 ENTER();
6853
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306854 status = wlan_hdd_validate_context(pHddCtx);
6855
6856 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006857 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6859 "%s: HDD context is not valid", __func__);
6860 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006861 }
6862
Arif Hussain6d2a3322013-11-17 19:50:10 -08006863 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006864 if (NULL == pWextState)
6865 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006866 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
Jeff Johnson295189b2012-06-20 16:38:30 -07006867 __func__);
6868 return -EIO;
6869 }
6870
6871 pRoamProfile = &pWextState->roamProfile;
6872
6873 /* Issue disconnect only if interface type is set to IBSS */
6874 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
6875 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306876 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
Jeff Johnson295189b2012-06-20 16:38:30 -07006877 __func__);
6878 return -EINVAL;
6879 }
6880
6881 /* Issue Disconnect request */
6882 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6883 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6884 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6885
6886 return 0;
6887}
6888
6889/*
6890 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
6891 * This function is used to set the phy parameters
6892 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
6893 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306894static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006895 u32 changed)
6896{
6897 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6898 tHalHandle hHal = pHddCtx->hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306899 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006900
6901 ENTER();
6902
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306903 status = wlan_hdd_validate_context(pHddCtx);
6904
6905 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006906 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6908 "%s: HDD context is not valid", __func__);
6909 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006910 }
6911
Jeff Johnson295189b2012-06-20 16:38:30 -07006912 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
6913 {
6914 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
6915 WNI_CFG_RTS_THRESHOLD_STAMAX :
6916 wiphy->rts_threshold;
6917
6918 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306919 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
Jeff Johnson295189b2012-06-20 16:38:30 -07006920 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306921 hddLog(VOS_TRACE_LEVEL_ERROR,
6922 "%s: Invalid RTS Threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006923 __func__, rts_threshold);
6924 return -EINVAL;
6925 }
6926
6927 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
6928 rts_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306929 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006930 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306931 hddLog(VOS_TRACE_LEVEL_ERROR,
6932 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006933 __func__, rts_threshold);
6934 return -EIO;
6935 }
6936
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306937 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006938 rts_threshold);
6939 }
6940
6941 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
6942 {
6943 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
6944 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
6945 wiphy->frag_threshold;
6946
6947 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306948 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006949 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306950 hddLog(VOS_TRACE_LEVEL_ERROR,
6951 "%s: Invalid frag_threshold value %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006952 frag_threshold);
6953 return -EINVAL;
6954 }
6955
6956 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
6957 frag_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306958 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006959 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306960 hddLog(VOS_TRACE_LEVEL_ERROR,
6961 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006962 __func__, frag_threshold);
6963 return -EIO;
6964 }
6965
6966 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
6967 frag_threshold);
6968 }
6969
6970 if ((changed & WIPHY_PARAM_RETRY_SHORT)
6971 || (changed & WIPHY_PARAM_RETRY_LONG))
6972 {
6973 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
6974 wiphy->retry_short :
6975 wiphy->retry_long;
6976
6977 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
6978 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
6979 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306980 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006981 __func__, retry_value);
6982 return -EINVAL;
6983 }
6984
6985 if (changed & WIPHY_PARAM_RETRY_SHORT)
6986 {
6987 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
6988 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306989 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07006990 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306991 hddLog(VOS_TRACE_LEVEL_ERROR,
6992 "%s: ccmCfgSetInt failed for long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 __func__, retry_value);
6994 return -EIO;
6995 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306996 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006997 __func__, retry_value);
6998 }
6999 else if (changed & WIPHY_PARAM_RETRY_SHORT)
7000 {
7001 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
7002 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307003 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007004 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307005 hddLog(VOS_TRACE_LEVEL_ERROR,
7006 "%s: ccmCfgSetInt failed for short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007007 __func__, retry_value);
7008 return -EIO;
7009 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307010 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007011 __func__, retry_value);
7012 }
7013 }
7014
7015 return 0;
7016}
7017
7018/*
7019 * FUNCTION: wlan_hdd_cfg80211_set_txpower
7020 * This function is used to set the txpower
7021 */
7022static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Yue Maf49ba872013-08-19 12:04:25 -07007023#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
7024 struct wireless_dev *wdev,
7025#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007026#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307027 enum tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07007028#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307029 enum nl80211_tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07007030#endif
7031 int dbm)
7032{
7033 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307034 tHalHandle hHal = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007035 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
7036 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307037 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007038
7039 ENTER();
7040
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307041 status = wlan_hdd_validate_context(pHddCtx);
7042
7043 if (0 != status)
7044 {
7045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7046 "%s: HDD context is not valid", __func__);
7047 return status;
7048 }
7049
7050 hHal = pHddCtx->hHal;
7051
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307052 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
7053 dbm, ccmCfgSetCallback,
7054 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007055 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307056 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007057 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
7058 return -EIO;
7059 }
7060
7061 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
7062 dbm);
7063
7064 switch(type)
7065 {
7066 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
7067 /* Fall through */
7068 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
7069 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
7070 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307071 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
7072 __func__);
7073 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007074 }
7075 break;
7076 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307077 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07007078 __func__);
7079 return -EOPNOTSUPP;
7080 break;
7081 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307082 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
7083 __func__, type);
Jeff Johnson295189b2012-06-20 16:38:30 -07007084 return -EIO;
7085 }
7086
7087 return 0;
7088}
7089
7090/*
7091 * FUNCTION: wlan_hdd_cfg80211_get_txpower
7092 * This function is used to read the txpower
7093 */
Yue Maf49ba872013-08-19 12:04:25 -07007094static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
7095#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
7096 struct wireless_dev *wdev,
7097#endif
7098 int *dbm)
Jeff Johnson295189b2012-06-20 16:38:30 -07007099{
7100
7101 hdd_adapter_t *pAdapter;
7102 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307103 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007104
Jeff Johnsone7245742012-09-05 17:12:55 -07007105 ENTER();
7106
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307107 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007108
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307109 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007110 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7112 "%s: HDD context is not valid", __func__);
7113 *dbm = 0;
7114 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007115 }
7116
Jeff Johnson295189b2012-06-20 16:38:30 -07007117 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
7118 if (NULL == pAdapter)
7119 {
7120 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
7121 return -ENOENT;
7122 }
7123
7124 wlan_hdd_get_classAstats(pAdapter);
7125 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
7126
Jeff Johnsone7245742012-09-05 17:12:55 -07007127 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007128 return 0;
7129}
7130
7131static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
7132 u8* mac, struct station_info *sinfo)
7133{
7134 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
7135 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7136 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
7137 tANI_U8 rate_flags;
7138
7139 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
7140 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07007141
7142 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
7143 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
7144 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
7145 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
7146 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
7147 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
7148 tANI_U16 maxRate = 0;
7149 tANI_U16 myRate;
7150 tANI_U16 currentRate = 0;
7151 tANI_U8 maxSpeedMCS = 0;
7152 tANI_U8 maxMCSIdx = 0;
7153 tANI_U8 rateFlag = 1;
7154 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07007155 tANI_U16 temp;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307156 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007157
Leo Chang6f8870f2013-03-26 18:11:36 -07007158#ifdef WLAN_FEATURE_11AC
7159 tANI_U32 vht_mcs_map;
7160 eDataRate11ACMaxMcs vhtMaxMcs;
7161#endif /* WLAN_FEATURE_11AC */
7162
Jeff Johnsone7245742012-09-05 17:12:55 -07007163 ENTER();
7164
Jeff Johnson295189b2012-06-20 16:38:30 -07007165 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
7166 (0 == ssidlen))
7167 {
7168 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
7169 " Invalid ssidlen, %d", __func__, ssidlen);
7170 /*To keep GUI happy*/
7171 return 0;
7172 }
7173
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307174 status = wlan_hdd_validate_context(pHddCtx);
7175
7176 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007177 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7179 "%s: HDD context is not valid", __func__);
7180 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007181 }
7182
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07007183 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007184 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
7185
Kiet Lam3b17fc82013-09-27 05:24:08 +05307186 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
7187 sinfo->filled |= STATION_INFO_SIGNAL;
7188
Jeff Johnson295189b2012-06-20 16:38:30 -07007189 //convert to the UI units of 100kbps
7190 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
7191
7192#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07007193 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07007194 sinfo->signal,
7195 pCfg->reportMaxLinkSpeed,
7196 myRate,
7197 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007198 (int) pCfg->linkSpeedRssiMid,
7199 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07007200 (int) rate_flags,
7201 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07007202#endif //LINKSPEED_DEBUG_ENABLED
7203
7204 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
7205 {
7206 // we do not want to necessarily report the current speed
7207 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
7208 {
7209 // report the max possible speed
7210 rssidx = 0;
7211 }
7212 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
7213 {
7214 // report the max possible speed with RSSI scaling
7215 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
7216 {
7217 // report the max possible speed
7218 rssidx = 0;
7219 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007220 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07007221 {
7222 // report middle speed
7223 rssidx = 1;
7224 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007225 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
7226 {
7227 // report middle speed
7228 rssidx = 2;
7229 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007230 else
7231 {
7232 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007233 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07007234 }
7235 }
7236 else
7237 {
7238 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
7239 hddLog(VOS_TRACE_LEVEL_ERROR,
7240 "%s: Invalid value for reportMaxLinkSpeed: %u",
7241 __func__, pCfg->reportMaxLinkSpeed);
7242 rssidx = 0;
7243 }
7244
7245 maxRate = 0;
7246
7247 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307248 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
7249 OperationalRates, &ORLeng))
7250 {
7251 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7252 /*To keep GUI happy*/
7253 return 0;
7254 }
7255
Jeff Johnson295189b2012-06-20 16:38:30 -07007256 for (i = 0; i < ORLeng; i++)
7257 {
Jeff Johnsone7245742012-09-05 17:12:55 -07007258 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07007259 {
7260 /* Validate Rate Set */
7261 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
7262 {
7263 currentRate = supported_data_rate[j].supported_rate[rssidx];
7264 break;
7265 }
7266 }
7267 /* Update MAX rate */
7268 maxRate = (currentRate > maxRate)?currentRate:maxRate;
7269 }
7270
7271 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307272 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
7273 ExtendedRates, &ERLeng))
7274 {
7275 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7276 /*To keep GUI happy*/
7277 return 0;
7278 }
7279
Jeff Johnson295189b2012-06-20 16:38:30 -07007280 for (i = 0; i < ERLeng; i++)
7281 {
Jeff Johnsone7245742012-09-05 17:12:55 -07007282 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07007283 {
7284 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
7285 {
7286 currentRate = supported_data_rate[j].supported_rate[rssidx];
7287 break;
7288 }
7289 }
7290 /* Update MAX rate */
7291 maxRate = (currentRate > maxRate)?currentRate:maxRate;
7292 }
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307293 /* Get MCS Rate Set --
Kaushik, Sushantdc304d82014-01-22 10:58:37 +05307294 Only if we are always reporting max speed (or)
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307295 if we have good rssi */
Kaushik, Sushantdc304d82014-01-22 10:58:37 +05307296 if ((0 == rssidx) ||
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307297 (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed))
Jeff Johnson295189b2012-06-20 16:38:30 -07007298 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307299 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
7300 MCSRates, &MCSLeng))
7301 {
7302 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7303 /*To keep GUI happy*/
7304 return 0;
7305 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007306 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07007307#ifdef WLAN_FEATURE_11AC
7308 /* VHT80 rate has seperate rate table */
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307309 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
Jeff Johnson295189b2012-06-20 16:38:30 -07007310 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007311 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307312 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
Leo Chang6f8870f2013-03-26 18:11:36 -07007313 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07007314 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007315 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07007316 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007317 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07007318 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007319 maxMCSIdx = 7;
7320 }
7321 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
7322 {
7323 maxMCSIdx = 8;
7324 }
7325 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
7326 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307327 //VHT20 is supporting 0~8
7328 if (rate_flags & eHAL_TX_RATE_VHT20)
7329 maxMCSIdx = 8;
7330 else
7331 maxMCSIdx = 9;
Leo Chang6f8870f2013-03-26 18:11:36 -07007332 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307333
7334 if (rate_flags & eHAL_TX_RATE_VHT80)
7335 {
7336 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
7337 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
7338 }
7339 else if (rate_flags & eHAL_TX_RATE_VHT40)
7340 {
7341 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
7342 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
7343 }
7344 else if (rate_flags & eHAL_TX_RATE_VHT20)
7345 {
7346 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
7347 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
7348 }
7349
Leo Chang6f8870f2013-03-26 18:11:36 -07007350 maxSpeedMCS = 1;
7351 if (currentRate > maxRate)
7352 {
7353 maxRate = currentRate;
7354 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307355
Leo Chang6f8870f2013-03-26 18:11:36 -07007356 }
7357 else
7358#endif /* WLAN_FEATURE_11AC */
7359 {
7360 if (rate_flags & eHAL_TX_RATE_HT40)
7361 {
7362 rateFlag |= 1;
7363 }
7364 if (rate_flags & eHAL_TX_RATE_SGI)
7365 {
7366 rateFlag |= 2;
7367 }
7368
7369 for (i = 0; i < MCSLeng; i++)
7370 {
7371 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
7372 for (j = 0; j < temp; j++)
7373 {
7374 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
7375 {
7376 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
7377 break;
7378 }
7379 }
7380 if ((j < temp) && (currentRate > maxRate))
7381 {
7382 maxRate = currentRate;
7383 maxSpeedMCS = 1;
7384 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
7385 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007386 }
7387 }
7388 }
7389
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307390 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
7391 {
7392 maxRate = myRate;
7393 maxSpeedMCS = 1;
7394 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
7395 }
7396
Jeff Johnson295189b2012-06-20 16:38:30 -07007397 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007398 if (((maxRate < myRate) && (0 == rssidx)) ||
7399 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07007400 {
7401 maxRate = myRate;
7402 if (rate_flags & eHAL_TX_RATE_LEGACY)
7403 {
7404 maxSpeedMCS = 0;
7405 }
7406 else
7407 {
7408 maxSpeedMCS = 1;
7409 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
7410 }
7411 }
7412
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307413 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson295189b2012-06-20 16:38:30 -07007414 {
7415 sinfo->txrate.legacy = maxRate;
7416#ifdef LINKSPEED_DEBUG_ENABLED
7417 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
7418#endif //LINKSPEED_DEBUG_ENABLED
7419 }
7420 else
7421 {
7422 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07007423#ifdef WLAN_FEATURE_11AC
7424 sinfo->txrate.nss = 1;
7425 if (rate_flags & eHAL_TX_RATE_VHT80)
7426 {
7427 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307428 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Leo Chang6f8870f2013-03-26 18:11:36 -07007429 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307430 else if (rate_flags & eHAL_TX_RATE_VHT40)
Leo Chang6f8870f2013-03-26 18:11:36 -07007431 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307432 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7433 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7434 }
7435 else if (rate_flags & eHAL_TX_RATE_VHT20)
7436 {
7437 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7438 }
7439#endif /* WLAN_FEATURE_11AC */
7440 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
7441 {
7442 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
7443 if (rate_flags & eHAL_TX_RATE_HT40)
7444 {
7445 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7446 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007447 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007448 if (rate_flags & eHAL_TX_RATE_SGI)
7449 {
7450 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
7451 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307452
Jeff Johnson295189b2012-06-20 16:38:30 -07007453#ifdef LINKSPEED_DEBUG_ENABLED
7454 pr_info("Reporting MCS rate %d flags %x\n",
7455 sinfo->txrate.mcs,
7456 sinfo->txrate.flags );
7457#endif //LINKSPEED_DEBUG_ENABLED
7458 }
7459 }
7460 else
7461 {
7462 // report current rate instead of max rate
7463
7464 if (rate_flags & eHAL_TX_RATE_LEGACY)
7465 {
7466 //provide to the UI in units of 100kbps
7467 sinfo->txrate.legacy = myRate;
7468#ifdef LINKSPEED_DEBUG_ENABLED
7469 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
7470#endif //LINKSPEED_DEBUG_ENABLED
7471 }
7472 else
7473 {
7474 //must be MCS
7475 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07007476#ifdef WLAN_FEATURE_11AC
7477 sinfo->txrate.nss = 1;
7478 if (rate_flags & eHAL_TX_RATE_VHT80)
7479 {
7480 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7481 }
7482 else
7483#endif /* WLAN_FEATURE_11AC */
7484 {
7485 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
7486 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007487 if (rate_flags & eHAL_TX_RATE_SGI)
7488 {
7489 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
7490 }
7491 if (rate_flags & eHAL_TX_RATE_HT40)
7492 {
7493 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7494 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007495#ifdef WLAN_FEATURE_11AC
7496 else if (rate_flags & eHAL_TX_RATE_VHT80)
7497 {
7498 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
7499 }
7500#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007501#ifdef LINKSPEED_DEBUG_ENABLED
7502 pr_info("Reporting actual MCS rate %d flags %x\n",
7503 sinfo->txrate.mcs,
7504 sinfo->txrate.flags );
7505#endif //LINKSPEED_DEBUG_ENABLED
7506 }
7507 }
7508 sinfo->filled |= STATION_INFO_TX_BITRATE;
7509
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07007510 sinfo->tx_packets =
7511 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
7512 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
7513 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
7514 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
7515
7516 sinfo->tx_retries =
7517 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
7518 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
7519 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
7520 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
7521
7522 sinfo->tx_failed =
7523 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
7524 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
7525 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
7526 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
7527
7528 sinfo->filled |=
7529 STATION_INFO_TX_PACKETS |
7530 STATION_INFO_TX_RETRIES |
7531 STATION_INFO_TX_FAILED;
7532
7533 EXIT();
7534 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007535}
7536
7537static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Sameer Thalappilc9f26e92013-06-07 10:11:06 -07007538 struct net_device *dev, bool mode, int timeout)
Jeff Johnson295189b2012-06-20 16:38:30 -07007539{
7540 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307541 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007542 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307543 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007544
Jeff Johnsone7245742012-09-05 17:12:55 -07007545 ENTER();
7546
Jeff Johnson295189b2012-06-20 16:38:30 -07007547 if (NULL == pAdapter)
7548 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007549 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007550 return -ENODEV;
7551 }
7552
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307553 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307554 status = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307555
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307556 if (0 != status)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307557 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7559 "%s: HDD context is not valid", __func__);
7560 return status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307561 }
7562
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307563 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
7564 (TRUE == pHddCtx->hdd_wlan_suspended) &&
7565 (pHddCtx->cfg_ini->fhostArpOffload) &&
7566 (eConnectionState_Associated ==
7567 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
7568 {
Amar Singhald53568e2013-09-26 11:03:45 -07007569
7570 hddLog(VOS_TRACE_LEVEL_INFO,
7571 "offload: in cfg80211_set_power_mgmt, calling arp offload");
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05307572 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307573 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7574 {
7575 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08007576 "%s:Failed to enable ARPOFFLOAD Feature %d",
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307577 __func__, vos_status);
7578 }
7579 }
7580
Jeff Johnson295189b2012-06-20 16:38:30 -07007581 /**The get power cmd from the supplicant gets updated by the nl only
7582 *on successful execution of the function call
7583 *we are oppositely mapped w.r.t mode in the driver
7584 **/
7585 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
7586
Jeff Johnsone7245742012-09-05 17:12:55 -07007587 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007588 if (VOS_STATUS_E_FAILURE == vos_status)
7589 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7591 "%s: failed to enter bmps mode", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007592 return -EINVAL;
7593 }
7594 return 0;
7595}
7596
7597
7598#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7599static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
7600 struct net_device *netdev,
7601 u8 key_index)
7602{
Jeff Johnsone7245742012-09-05 17:12:55 -07007603 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007604 return 0;
7605}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307606#endif //LINUX_VERSION_CODE
Jeff Johnson295189b2012-06-20 16:38:30 -07007607
7608#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
7609static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7610 struct net_device *dev,
7611 struct ieee80211_txq_params *params)
7612{
Jeff Johnsone7245742012-09-05 17:12:55 -07007613 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007614 return 0;
7615}
7616#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7617static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7618 struct ieee80211_txq_params *params)
7619{
Jeff Johnsone7245742012-09-05 17:12:55 -07007620 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007621 return 0;
7622}
7623#endif //LINUX_VERSION_CODE
7624
7625static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
7626 struct net_device *dev, u8 *mac)
7627{
7628 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307629 hdd_context_t *pHddCtx;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007630 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307631 int status;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007632 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007633
Jeff Johnsone7245742012-09-05 17:12:55 -07007634 ENTER();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307635 if ( NULL == pAdapter )
Jeff Johnson295189b2012-06-20 16:38:30 -07007636 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307637 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007638 return -EINVAL;
7639 }
7640
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307641 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7642 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007643
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307644 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007645 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7647 "%s: HDD context is not valid", __func__);
7648 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007649 }
7650
Jeff Johnson295189b2012-06-20 16:38:30 -07007651 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007652 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007653 )
7654 {
7655 if( NULL == mac )
7656 {
7657 v_U16_t i;
7658 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
7659 {
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007660 if ((pAdapter->aStaInfo[i].isUsed) &&
7661 (!pAdapter->aStaInfo[i].isDeauthInProgress))
Jeff Johnson295189b2012-06-20 16:38:30 -07007662 {
7663 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
7664 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007665 "%s: Delete STA with MAC::"
7666 MAC_ADDRESS_STR,
7667 __func__, MAC_ADDR_ARRAY(macAddr));
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007668 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
7669 if (VOS_IS_STATUS_SUCCESS(vos_status))
7670 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007671 }
7672 }
7673 }
7674 else
7675 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007676
7677 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
7678 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7679 {
7680 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007681 "%s: Skip this DEL STA as this is not used::"
7682 MAC_ADDRESS_STR,
7683 __func__, MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007684 return -ENOENT;
7685 }
7686
7687 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
7688 {
7689 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007690 "%s: Skip this DEL STA as deauth is in progress::"
7691 MAC_ADDRESS_STR,
7692 __func__, MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007693 return -ENOENT;
7694 }
7695
7696 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
7697
Jeff Johnson295189b2012-06-20 16:38:30 -07007698 hddLog(VOS_TRACE_LEVEL_INFO,
7699 "%s: Delete STA with MAC::"
Arif Hussain24bafea2013-11-15 15:10:03 -08007700 MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007701 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08007702 MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007703
7704 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
7705 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7706 {
7707 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
7708 hddLog(VOS_TRACE_LEVEL_INFO,
7709 "%s: STA removal failed for ::"
Arif Hussain24bafea2013-11-15 15:10:03 -08007710 MAC_ADDRESS_STR,
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007711 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08007712 MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007713 return -ENOENT;
7714 }
7715
Jeff Johnson295189b2012-06-20 16:38:30 -07007716 }
7717 }
7718
7719 EXIT();
7720
7721 return 0;
7722}
7723
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007724static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
7725 struct net_device *dev, u8 *mac, struct station_parameters *params)
7726{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007727 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007728#ifdef FEATURE_WLAN_TDLS
7729 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007730 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007731 mask = params->sta_flags_mask;
7732
7733 set = params->sta_flags_set;
7734
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007735#ifdef WLAN_FEATURE_TDLS_DEBUG
7736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7737 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
7738 __func__, mask, set, MAC_ADDR_ARRAY(mac));
7739#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007740
7741 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7742 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007743 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007744 }
7745 }
7746#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007747 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007748}
7749
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007750
7751#ifdef FEATURE_WLAN_LFR
Wilson Yang6507c4e2013-10-01 20:11:19 -07007752#define MAX_PMKSAIDS_IN_CACHE 8
7753
7754static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD local cache
7755static tANI_U32 PMKIDCacheIndex; // HDD local Cache index
7756
7757
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007758static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007759 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007760{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307761 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007762 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7763 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307764 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307765 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007766 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307767 hdd_context_t *pHddCtx;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307768
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007769 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: set PMKSA for " MAC_ADDRESS_STR,
7770 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Jeff Johnsone7245742012-09-05 17:12:55 -07007771
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307772 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307773 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007774 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307775 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007776 return -EINVAL;
7777 }
7778
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307779 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7780 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007781
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307782 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007783 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7785 "%s: HDD context is not valid", __func__);
7786 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007787 }
7788
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307789 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007790 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7791
Wilson Yang6507c4e2013-10-01 20:11:19 -07007792 for (j = 0; j < PMKIDCacheIndex; j++)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007793 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307794 if(vos_mem_compare(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007795 pmksa->bssid, WNI_CFG_BSSID_LEN))
7796 {
7797 /* BSSID matched previous entry. Overwrite it. */
7798 BSSIDMatched = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307799 vos_mem_copy(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007800 pmksa->bssid, WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307801 vos_mem_copy(PMKIDCache[j].PMKID,
7802 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007803 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307804 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007805 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007806 dump_bssid(pmksa->bssid);
7807 dump_pmkid(halHandle, pmksa->pmkid);
7808 break;
7809 }
7810 }
7811
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007812 /* Check we compared all entries,if then take the first slot now */
Wilson Yang6507c4e2013-10-01 20:11:19 -07007813 if(j == MAX_PMKSAIDS_IN_CACHE) PMKIDCacheIndex=0;
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007814
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007815 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307816 {
7817 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
Wilson Yang6507c4e2013-10-01 20:11:19 -07007818 vos_mem_copy(PMKIDCache[PMKIDCacheIndex].BSSID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307819 pmksa->bssid, ETHER_ADDR_LEN);
Wilson Yang6507c4e2013-10-01 20:11:19 -07007820 vos_mem_copy(PMKIDCache[PMKIDCacheIndex].PMKID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307821 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007822 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307823 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Wilson Yang6507c4e2013-10-01 20:11:19 -07007824 __func__, PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007825 dump_bssid(pmksa->bssid);
7826 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307827 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007828 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Wilson Yang6507c4e2013-10-01 20:11:19 -07007829 if (PMKIDCacheIndex <= (MAX_PMKSAIDS_IN_CACHE-1)) PMKIDCacheIndex++; else PMKIDCacheIndex = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007830 }
7831
7832
7833 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307834 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007835 // __func__, i );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307836 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Wilson Yang6507c4e2013-10-01 20:11:19 -07007837 __func__, PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007838 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307839 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
7840 PMKIDCache,
Wilson Yang6507c4e2013-10-01 20:11:19 -07007841 PMKIDCacheIndex);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007842 return 0;
7843}
7844
7845
Wilson Yang6507c4e2013-10-01 20:11:19 -07007846
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007847static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Wilson Yang6507c4e2013-10-01 20:11:19 -07007848 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007849{
Wilson Yang6507c4e2013-10-01 20:11:19 -07007850 tANI_U32 j=0;
7851 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7852 tHalHandle halHandle;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007853 tANI_U8 BSSIDMatched = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007854 hdd_context_t *pHddCtx;
Wilson Yangef657d32014-01-15 19:19:23 -08007855 int status = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007856
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007857 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: deleting PMKSA for " MAC_ADDRESS_STR,
7858 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Wilson Yang6507c4e2013-10-01 20:11:19 -07007859
7860 /* Validate pAdapter */
7861 if (NULL == pAdapter)
7862 {
7863 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
7864 return -EINVAL;
7865 }
7866
7867 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7868 status = wlan_hdd_validate_context(pHddCtx);
7869
7870 if (0 != status)
7871 {
7872 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7873 "%s: HDD context is not valid", __func__);
7874 return status;
7875 }
7876
7877 /*Retrieve halHandle*/
7878 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7879
7880 /*in case index is 0,no entry to delete*/
7881 if (0 == PMKIDCacheIndex)
7882 {
7883 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid entry to delete" ,
7884 __func__);
7885 return -EINVAL;
7886 }
7887
7888 /*find the matching PMKSA entry from j=0 to (index-1),
7889 * and delete the matched one
7890 */
7891 for (j = 0; j<PMKIDCacheIndex; j++)
7892 {
7893 if (vos_mem_compare(PMKIDCache[j].BSSID,
7894 pmksa->bssid,
7895 WNI_CFG_BSSID_LEN))
7896 {
7897 /* BSSID matched entry */
7898 BSSIDMatched = 1;
7899
7900 if (j<PMKIDCacheIndex-1)
7901 {
7902 /*replace the matching entry with the last entry in HDD local cache*/
7903 vos_mem_copy(PMKIDCache[j].BSSID,
7904 PMKIDCache[PMKIDCacheIndex-1].BSSID,
7905 WNI_CFG_BSSID_LEN);
7906 vos_mem_copy(PMKIDCache[j].PMKID,
7907 PMKIDCache[PMKIDCacheIndex-1].PMKID,
7908 CSR_RSN_PMKID_SIZE);
7909 }
7910
7911 /*clear the last entry in HDD cache ---[index-1]*/
Wilson Yang6507c4e2013-10-01 20:11:19 -07007912 vos_mem_zero(PMKIDCache[PMKIDCacheIndex-1].BSSID, WNI_CFG_BSSID_LEN);
7913 vos_mem_zero(PMKIDCache[PMKIDCacheIndex-1].PMKID, CSR_RSN_PMKID_SIZE);
7914
7915 /*reduce the PMKID array index*/
7916 PMKIDCacheIndex--;
7917
7918 /*delete the last PMKID cache in CSR*/
Wilson Yangef657d32014-01-15 19:19:23 -08007919 if (eHAL_STATUS_SUCCESS !=
7920 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pmksa->bssid))
Wilson Yang6507c4e2013-10-01 20:11:19 -07007921 {
7922 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cannot delete PMKSA %d CONTENT.",
7923 __func__,PMKIDCacheIndex);
Wilson Yangef657d32014-01-15 19:19:23 -08007924 status = -EINVAL;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007925 }
7926
7927 dump_bssid(pmksa->bssid);
7928 dump_pmkid(halHandle,pmksa->pmkid);
7929
7930 break;
7931 }
7932 }
7933
7934 /* we compare all entries,but cannot find matching entry */
7935 if (j == MAX_PMKSAIDS_IN_CACHE && !BSSIDMatched)
7936 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007937 hddLog(VOS_TRACE_LEVEL_FATAL,
7938 "%s: No such PMKSA entry existed " MAC_ADDRESS_STR,
7939 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Wilson Yang6507c4e2013-10-01 20:11:19 -07007940 dump_bssid(pmksa->bssid);
7941 dump_pmkid(halHandle, pmksa->pmkid);
7942 return -EINVAL;
7943 }
Wilson Yangef657d32014-01-15 19:19:23 -08007944 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007945}
7946
Wilson Yang6507c4e2013-10-01 20:11:19 -07007947
7948
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007949static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
7950{
Wilson Yang6507c4e2013-10-01 20:11:19 -07007951 tANI_U32 j=0;
7952 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7953 tHalHandle halHandle;
7954 hdd_context_t *pHddCtx;
7955 tANI_U8 *pBSSId;
Wilson Yangef657d32014-01-15 19:19:23 -08007956 int status = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007957
7958 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: flushing PMKSA ",__func__);
7959
7960 /* Validate pAdapter */
7961 if (NULL == pAdapter)
7962 {
7963 hddLog(VOS_TRACE_LEVEL_ERROR,
7964 "%s: Invalid Adapter" ,__func__);
7965 return -EINVAL;
7966 }
7967
7968 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7969 status = wlan_hdd_validate_context(pHddCtx);
7970
7971 if (0 != status)
7972 {
7973 hddLog(VOS_TRACE_LEVEL_ERROR,
7974 "%s: HDD context is not valid", __func__);
7975 return status;
7976 }
7977
7978 /*Retrieve halHandle*/
7979 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7980
7981 /*in case index is 0,no entry to delete*/
7982 if (0 == PMKIDCacheIndex)
7983 {
7984 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid entry to delete" ,
7985 __func__);
7986 return -EINVAL;
7987 }
7988
7989 /*delete all the PMKSA one by one */
7990 for (j = 0; j<PMKIDCacheIndex; j++)
7991 {
Wilson Yang6507c4e2013-10-01 20:11:19 -07007992 pBSSId =(tANI_U8 *)(PMKIDCache[j].BSSID);
Wilson Yang6507c4e2013-10-01 20:11:19 -07007993
7994 /*delete the PMKID in CSR*/
Wilson Yangef657d32014-01-15 19:19:23 -08007995 if (eHAL_STATUS_SUCCESS !=
7996 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pBSSId))
Wilson Yang6507c4e2013-10-01 20:11:19 -07007997 {
7998 hddLog(VOS_TRACE_LEVEL_ERROR ,"%s cannot flush PMKIDCache %d.",
7999 __func__,j);
Wilson Yangef657d32014-01-15 19:19:23 -08008000 status = -EINVAL;
Wilson Yang6507c4e2013-10-01 20:11:19 -07008001 }
Kiet Lam8d21d5b2013-10-31 17:18:29 +05308002 /*clear the entry in HDD cache 0--index-1 */
8003 vos_mem_zero(PMKIDCache[j].BSSID, WNI_CFG_BSSID_LEN);
8004 vos_mem_zero(PMKIDCache[j].PMKID, CSR_RSN_PMKID_SIZE);
Wilson Yang6507c4e2013-10-01 20:11:19 -07008005 }
8006
8007 PMKIDCacheIndex = 0;
Wilson Yangef657d32014-01-15 19:19:23 -08008008 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008009}
8010#endif
8011
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008012#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308013static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008014 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
8015{
8016 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8017 hdd_station_ctx_t *pHddStaCtx;
8018
8019 if (NULL == pAdapter)
8020 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008021 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008022 return -ENODEV;
8023 }
8024
8025 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8026
8027 // Added for debug on reception of Re-assoc Req.
8028 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
8029 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008030 hddLog(LOGE, FL("Called with Ie of length = %zu when not associated"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008031 ftie->ie_len);
Arif Hussain6d2a3322013-11-17 19:50:10 -08008032 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008033 }
8034
8035#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Arif Hussain6d2a3322013-11-17 19:50:10 -08008036 hddLog(LOGE, FL("%s called with Ie of length = %zu"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008037 ftie->ie_len);
8038#endif
8039
8040 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05308041 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
8042 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008043 ftie->ie_len);
8044 return 0;
8045}
8046#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008047
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308048#ifdef FEATURE_WLAN_SCAN_PNO
8049
8050void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
8051 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
8052{
8053 int ret;
8054 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
8055 hdd_context_t *pHddCtx;
8056
Nirav Shah80830bf2013-12-31 16:35:12 +05308057 ENTER();
8058
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308059 if (NULL == pAdapter)
8060 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308062 "%s: HDD adapter is Null", __func__);
8063 return ;
8064 }
8065
8066 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8067 if (NULL == pHddCtx)
8068 {
8069 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8070 "%s: HDD context is Null!!!", __func__);
8071 return ;
8072 }
8073
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308074 spin_lock(&pHddCtx->schedScan_lock);
8075 if (TRUE == pHddCtx->isWiphySuspended)
8076 {
8077 pHddCtx->isSchedScanUpdatePending = TRUE;
8078 spin_unlock(&pHddCtx->schedScan_lock);
8079 hddLog(VOS_TRACE_LEVEL_INFO,
8080 "%s: Update cfg80211 scan database after it resume", __func__);
8081 return ;
8082 }
8083 spin_unlock(&pHddCtx->schedScan_lock);
8084
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308085 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
8086
8087 if (0 > ret)
8088 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
8089
8090 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8092 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308093}
8094
8095/*
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308096 * FUNCTION: wlan_hdd_is_pno_allowed
8097 * To check is there any P2P GO/SAP or P2P Client/STA
8098 * session is active
8099 */
8100static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter)
8101{
8102 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8103 hdd_adapter_t *pTempAdapter = NULL;
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308104 hdd_station_ctx_t *pStaCtx;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308105 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8106 int status = 0;
8107 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
8108
8109 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status))
8110 {
8111 pTempAdapter = pAdapterNode->pAdapter;
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308112 pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pTempAdapter);
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308113
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308114 if (((WLAN_HDD_INFRA_STATION == pTempAdapter->device_mode)
8115 && (eConnectionState_NotConnected != pStaCtx->conn_info.connState))
8116 || (WLAN_HDD_P2P_CLIENT == pTempAdapter->device_mode)
8117 || (WLAN_HDD_P2P_GO == pTempAdapter->device_mode)
8118 || (WLAN_HDD_SOFTAP == pTempAdapter->device_mode)
8119 )
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308120 {
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308121 return eHAL_STATUS_FAILURE;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308122 }
8123 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8124 pAdapterNode = pNext;
8125 }
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308126 return eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308127}
8128
8129/*
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308130 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
8131 * NL interface to enable PNO
8132 */
8133static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
8134 struct net_device *dev, struct cfg80211_sched_scan_request *request)
8135{
8136 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8137 tpSirPNOScanReq pPnoRequest = NULL;
8138 hdd_context_t *pHddCtx;
8139 tHalHandle hHal;
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05308140 v_U32_t i, indx, num_ch, tempInterval;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308141 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
8142 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN];
8143 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
8144 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308145 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308146
8147 if (NULL == pAdapter)
8148 {
8149 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8150 "%s: HDD adapter is Null", __func__);
8151 return -ENODEV;
8152 }
8153
8154 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308155 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308156
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308157 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308158 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8160 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308161 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308162 }
8163
8164 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8165 if (NULL == hHal)
8166 {
8167 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8168 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308169 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308170 }
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308171
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308172 /* The current firmware design for PNO does not consider concurrent
8173 * active sessions.Hence , determine the concurrent active sessions
8174 * and return a failure to the framework on a request for schedule
8175 * scan.
8176 */
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308177 if (eHAL_STATUS_SUCCESS != wlan_hdd_is_pno_allowed(pAdapter))
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308178 {
8179 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308180 FL("Cannot handle sched_scan"));
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308181 return -EBUSY;
8182 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308183
8184 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
8185 if (NULL == pPnoRequest)
8186 {
8187 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8188 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308189 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308190 }
8191
Madan Mohan Koyyalamudic3f04352013-09-26 19:21:48 +05308192 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308193 pPnoRequest->enable = 1; /*Enable PNO */
8194 pPnoRequest->ucNetworksCount = request->n_match_sets;
8195
8196 if (( !pPnoRequest->ucNetworksCount ) ||
8197 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
8198 {
8199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308200 "%s: Network input is not correct %d",
8201 __func__, pPnoRequest->ucNetworksCount);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308202 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308203 goto error;
8204 }
8205
8206 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
8207 {
8208 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308209 "%s: Incorrect number of channels %d",
8210 __func__, request->n_channels);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308211 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308212 goto error;
8213 }
8214
8215 /* Framework provides one set of channels(all)
8216 * common for all saved profile */
8217 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
8218 channels_allowed, &num_channels_allowed))
8219 {
8220 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8221 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308222 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308223 goto error;
8224 }
8225 /* Checking each channel against allowed channel list */
8226 num_ch = 0;
Nirav Shah80830bf2013-12-31 16:35:12 +05308227 if (request->n_channels)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308228 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308229 char chList [(request->n_channels*5)+1];
8230 int len;
8231 for (i = 0, len = 0; i < request->n_channels; i++)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308232 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308233 for (indx = 0; indx < num_channels_allowed; indx++)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308234 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308235 if (request->channels[i]->hw_value == channels_allowed[indx])
8236 {
8237 valid_ch[num_ch++] = request->channels[i]->hw_value;
8238 len += snprintf(chList+len, 5, "%d ",
8239 request->channels[i]->hw_value);
8240 break ;
8241 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308242 }
8243 }
Nirav Shah80830bf2013-12-31 16:35:12 +05308244 hddLog(VOS_TRACE_LEVEL_INFO,"Channel-List: %s ", chList);
8245 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308246
8247 /* Filling per profile params */
8248 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
8249 {
8250 pPnoRequest->aNetworks[i].ssId.length =
8251 request->match_sets[i].ssid.ssid_len;
8252
8253 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
8254 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
8255 {
8256 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308257 "%s: SSID Len %d is not correct for network %d",
8258 __func__, pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308259 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308260 goto error;
8261 }
8262
8263 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
8264 request->match_sets[i].ssid.ssid,
8265 request->match_sets[i].ssid.ssid_len);
8266 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
8267 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
8268 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
8269
8270 /*Copying list of valid channel into request */
8271 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
8272 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
8273
8274 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
8275 }
8276
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +05308277 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson59a121e2013-11-30 09:46:08 -08008278 "request->ie_len = %zu", request->ie_len);
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +05308279 if ((0 < request->ie_len) && (NULL != request->ie))
8280 {
8281 pPnoRequest->us24GProbeTemplateLen = request->ie_len;
8282 memcpy(&pPnoRequest->p24GProbeTemplate, request->ie,
8283 pPnoRequest->us24GProbeTemplateLen);
8284
8285 pPnoRequest->us5GProbeTemplateLen = request->ie_len;
8286 memcpy(&pPnoRequest->p5GProbeTemplate, request->ie,
8287 pPnoRequest->us5GProbeTemplateLen);
8288 }
8289
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05308290 /* Driver gets only one time interval which is hardcoded in
8291 * supplicant for 10000ms. Taking power consumption into account 6 timers
8292 * will be used, Timervalue is increased exponentially i.e 10,20,40,
8293 * 80,160,320 secs. And number of scan cycle for each timer
8294 * is configurable through INI param gPNOScanTimerRepeatValue.
8295 * If it is set to 0 only one timer will be used and PNO scan cycle
8296 * will be repeated after each interval specified by supplicant
8297 * till PNO is disabled.
8298 */
8299 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
8300 pPnoRequest->scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
8301 else
8302 pPnoRequest->scanTimers.ucScanTimersCount =
8303 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
8304
8305 tempInterval = (request->interval)/1000;
8306 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8307 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
8308 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
8309 for ( i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++)
8310 {
8311 pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat =
8312 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
8313 pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = tempInterval;
8314 tempInterval *= 2;
8315 }
8316 //Repeat last timer until pno disabled.
8317 pPnoRequest->scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
8318
Madan Mohan Koyyalamudid206c7b2013-09-26 22:54:51 +05308319 pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308320
Nirav Shah80830bf2013-12-31 16:35:12 +05308321 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8322 "SessionId %d, enable %d, modePNO %d, ucScanTimersCount %d",
8323 pAdapter->sessionId, pPnoRequest->enable, pPnoRequest->modePNO,
8324 pPnoRequest->scanTimers.ucScanTimersCount);
8325
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308326 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
8327 pPnoRequest, pAdapter->sessionId,
8328 hdd_cfg80211_sched_scan_done_callback, pAdapter);
8329 if (eHAL_STATUS_SUCCESS != status)
8330 {
8331 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308332 "%s: Failed to enable PNO", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308333 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308334 goto error;
8335 }
8336
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8338 "PNO scanRequest offloaded");
8339
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308340error:
8341 vos_mem_free(pPnoRequest);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308342 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308343}
8344
8345/*
8346 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
8347 * NL interface to disable PNO
8348 */
8349static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
8350 struct net_device *dev)
8351{
8352 eHalStatus status = eHAL_STATUS_FAILURE;
8353 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8354 hdd_context_t *pHddCtx;
8355 tHalHandle hHal;
8356 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308357 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308358
8359 ENTER();
8360
8361 if (NULL == pAdapter)
8362 {
8363 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8364 "%s: HDD adapter is Null", __func__);
8365 return -ENODEV;
8366 }
8367
8368 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308369
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308370 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308371 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308373 "%s: HDD context is Null", __func__);
8374 return -ENODEV;
8375 }
8376
8377 /* The return 0 is intentional when isLogpInProgress and
8378 * isLoadUnloadInProgress. We did observe a crash due to a return of
8379 * failure in sched_scan_stop , especially for a case where the unload
8380 * of the happens at the same time. The function __cfg80211_stop_sched_scan
8381 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
8382 * success. If it returns a failure , then its next invocation due to the
8383 * clean up of the second interface will have the dev pointer corresponding
8384 * to the first one leading to a crash.
8385 */
8386 if (pHddCtx->isLogpInProgress)
8387 {
8388 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8389 "%s: LOGP in Progress. Ignore!!!", __func__);
8390 return ret;
8391 }
8392
8393 if (pHddCtx->isLoadUnloadInProgress)
8394 {
8395 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8396 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
8397 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308398 }
8399
8400 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8401 if (NULL == hHal)
8402 {
8403 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8404 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308405 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308406 }
8407
8408 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
8409 if (NULL == pPnoRequest)
8410 {
8411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8412 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308413 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308414 }
8415
8416 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
8417 pPnoRequest->enable = 0; /* Disable PNO */
8418 pPnoRequest->ucNetworksCount = 0;
8419
8420 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
8421 pAdapter->sessionId,
8422 NULL, pAdapter);
8423 if (eHAL_STATUS_SUCCESS != status)
8424 {
8425 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8426 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308427 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308428 }
8429
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8431 "%s: PNO scan disabled", __func__);
8432
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308433 vos_mem_free(pPnoRequest);
8434
8435 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308436 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308437}
8438
8439#endif /*FEATURE_WLAN_SCAN_PNO*/
8440
8441
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008442#ifdef FEATURE_WLAN_TDLS
8443static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
8444 u8 *peer, u8 action_code, u8 dialog_token,
8445 u16 status_code, const u8 *buf, size_t len)
8446{
8447
8448 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8449 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008450 u8 peerMac[6];
8451 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07008452 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08008453 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -07008454 long rc;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008455
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008456 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008457 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008459 "Invalid arguments");
8460 return -EINVAL;
8461 }
8462
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008463 if (pHddCtx->isLogpInProgress)
8464 {
8465 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8466 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008467 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008468 return -EBUSY;
8469 }
8470
Hoonki Lee27511902013-03-14 18:19:06 -07008471 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008472 {
Hoonki Lee27511902013-03-14 18:19:06 -07008473 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
8474 "%s: TDLS mode is disabled OR not enabled in FW."
8475 MAC_ADDRESS_STR " action %d declined.",
8476 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008477 return -ENOTSUPP;
8478 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008479
Hoonki Lee27511902013-03-14 18:19:06 -07008480 /* other than teardown frame, other mgmt frames are not sent if disabled */
8481 if (SIR_MAC_TDLS_TEARDOWN != action_code)
8482 {
8483 /* if tdls_mode is disabled to respond to peer's request */
8484 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
8485 {
8486 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
8487 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008488 " TDLS mode is disabled. action %d declined.",
8489 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07008490
8491 return -ENOTSUPP;
8492 }
8493 }
8494
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008495 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
8496 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308497 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008498 {
8499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008500 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008501 " TDLS setup is ongoing. action %d declined.",
8502 __func__, MAC_ADDR_ARRAY(peer), action_code);
8503 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008504 }
8505 }
8506
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008507 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
8508 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08008509 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008510 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008511 {
8512 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
8513 we return error code at 'add_station()'. Hence we have this
8514 check again in addtion to add_station().
8515 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008516 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08008517 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8519 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008520 " TDLS Max peer already connected. action %d declined.",
8521 __func__, MAC_ADDR_ARRAY(peer), action_code);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308522 return -EINVAL;
Lee Hoonkic1262f22013-01-24 21:59:00 -08008523 }
8524 else
8525 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008526 /* maximum reached. tweak to send error code to peer and return
8527 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08008528 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8530 "%s: " MAC_ADDRESS_STR
8531 " TDLS Max peer already connected send response status %d",
8532 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008533 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008534 /* fall through to send setup resp with failure status
8535 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08008536 }
8537 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008538 else
8539 {
8540 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308541 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008542 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008543 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008545 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
8546 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008547 return -EPERM;
8548 }
8549 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008550 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008551 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008552
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008553#ifdef WLAN_FEATURE_TDLS_DEBUG
8554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008555 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
8556 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
8557 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008558#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008559
Hoonki Leea34dd892013-02-05 22:56:02 -08008560 /*Except teardown responder will not be used so just make 0*/
8561 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008562 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08008563 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008564
8565 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308566 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac, TRUE);
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008567
8568 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
8569 responder = pTdlsPeer->is_responder;
8570 else
Hoonki Leea34dd892013-02-05 22:56:02 -08008571 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8573 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
8574 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
8575 dialog_token, status_code, len);
8576 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08008577 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008578 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008579
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308580 /* For explicit trigger of DIS_REQ come out of BMPS for
8581 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -07008582 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308583 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
8584 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -07008585 {
8586 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
8587 {
8588 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308589 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -07008590 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
8591 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308592 if (SIR_MAC_TDLS_DIS_REQ != action_code)
8593 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -07008594 }
8595
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008596 /* make sure doesn't call send_mgmt() while it is pending */
8597 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
8598 {
8599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008600 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY",
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008601 __func__, MAC_ADDR_ARRAY(peer), action_code);
8602 return -EBUSY;
8603 }
8604
8605 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008606 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
8607
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008608 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08008609 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008610
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008611 if (VOS_STATUS_SUCCESS != status)
8612 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008613 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8614 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008615 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -07008616 wlan_hdd_tdls_check_bmps(pAdapter);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308617 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008618 }
8619
Hoonki Leed37cbb32013-04-20 00:31:14 -07008620 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
8621 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
8622
8623 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008624 {
Hoonki Leed37cbb32013-04-20 00:31:14 -07008625 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008626 "%s: Mgmt Tx Completion failed status %ld TxCompletion %u",
Hoonki Leed37cbb32013-04-20 00:31:14 -07008627 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008628 pAdapter->mgmtTxCompletionStatus = FALSE;
Yue Ma4f55ef32014-01-23 16:45:33 -08008629
8630 if (pHddCtx->isLogpInProgress)
8631 {
8632 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8633 "%s: LOGP in Progress. Ignore!!!", __func__);
8634 return -EAGAIN;
8635 }
8636
Hoonki Leed37cbb32013-04-20 00:31:14 -07008637 wlan_hdd_tdls_check_bmps(pAdapter);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308638 return -EINVAL;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008639 }
8640
Gopichand Nakkala05922802013-03-14 12:23:19 -07008641 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07008642 {
8643 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008644 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07008645 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008646
Hoonki Leea34dd892013-02-05 22:56:02 -08008647 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
8648 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008649 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08008650 }
8651 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
8652 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008653 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08008654 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008655
8656 return 0;
8657}
8658
8659static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
8660 u8 *peer, enum nl80211_tdls_operation oper)
8661{
8662 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8663 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308664 int status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008665 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008666
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308667 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008668 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07008670 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008671 return -EINVAL;
8672 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008673
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308674 status = wlan_hdd_validate_context(pHddCtx);
8675
8676 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008677 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308678 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8679 "%s: HDD context is not valid", __func__);
8680 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008681 }
8682
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008683
8684 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008685 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008686 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07008688 "TDLS Disabled in INI OR not enabled in FW. "
8689 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008690 return -ENOTSUPP;
8691 }
8692
8693 switch (oper) {
8694 case NL80211_TDLS_ENABLE_LINK:
8695 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008696 VOS_STATUS status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308697 long ret;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308698 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008699
Sunil Dutt41de4e22013-11-14 18:09:02 +05308700 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8701
8702 if ( NULL == pTdlsPeer ) {
8703 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
8704 " (oper %d) not exsting. ignored",
8705 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
8706 return -EINVAL;
8707 }
8708
8709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8710 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
8711 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
8712 "NL80211_TDLS_ENABLE_LINK");
8713
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -07008714 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
8715 {
8716 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
8717 MAC_ADDRESS_STR " failed",
8718 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
8719 return -EINVAL;
8720 }
8721
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008722 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008723 {
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308724 if (IS_ADVANCE_TDLS_ENABLE) {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05308725
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308726 if (0 != wlan_hdd_tdls_get_link_establish_params(
8727 pAdapter, peer,&tdlsLinkEstablishParams)) {
8728 return -EINVAL;
8729 }
8730 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308731
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308732 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
8733 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
8734 /* Send TDLS peer UAPSD capabilities to the firmware and
8735 * register with the TL on after the response for this operation
8736 * is received .
8737 */
8738 ret = wait_for_completion_interruptible_timeout(
8739 &pAdapter->tdls_link_establish_req_comp,
8740 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
8741 if (ret <= 0)
8742 {
8743 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8744 "%s: Link Establish Request Faled Status %ld",
8745 __func__, ret);
8746 return -EINVAL;
8747 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308748 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008749 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +05308750 /* Mark TDLS client Authenticated .*/
8751 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
8752 pTdlsPeer->staId,
8753 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008754 if (VOS_STATUS_SUCCESS == status)
8755 {
Hoonki Lee14621352013-04-16 17:51:19 -07008756 if (pTdlsPeer->is_responder == 0)
8757 {
8758 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
8759
8760 wlan_hdd_tdls_timer_restart(pAdapter,
8761 &pTdlsPeer->initiatorWaitTimeoutTimer,
8762 WAIT_TIME_TDLS_INITIATOR);
8763 /* suspend initiator TX until it receives direct packet from the
8764 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
8765 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8766 &staId, NULL);
8767 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008768 wlan_hdd_tdls_increment_peer_count(pAdapter);
8769 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008770 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308771
8772 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308773 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
8774 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308775 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308776 int ac;
8777 uint8 ucAc[4] = { WLANTL_AC_VO,
8778 WLANTL_AC_VI,
8779 WLANTL_AC_BK,
8780 WLANTL_AC_BE };
8781 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
8782 for(ac=0; ac < 4; ac++)
8783 {
8784 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8785 pTdlsPeer->staId, ucAc[ac],
8786 tlTid[ac], tlTid[ac], 0, 0,
8787 WLANTL_BI_DIR );
8788 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308789 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008790 }
8791
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008792 }
8793 break;
8794 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08008795 {
Sunil Dutt41de4e22013-11-14 18:09:02 +05308796 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8797
8798 if ( NULL == pTdlsPeer ) {
8799 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
8800 " (oper %d) not exsting. ignored",
8801 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
8802 return -EINVAL;
8803 }
8804
8805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8806 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
8807 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
8808 "NL80211_TDLS_DISABLE_LINK");
8809
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008810 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008811 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008812 long status;
8813
8814 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
8815
Lee Hoonkic1262f22013-01-24 21:59:00 -08008816 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
8817 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008818
8819 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
8820 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
8821 if (status <= 0)
8822 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008823 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008824 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8825 "%s: Del station failed status %ld",
8826 __func__, status);
8827 return -EPERM;
8828 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008829 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008830 }
8831 else
8832 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008833 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8834 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008835 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008836 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008837 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008838 case NL80211_TDLS_TEARDOWN:
Sunil Dutt41de4e22013-11-14 18:09:02 +05308839 {
8840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8841 " %s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR,
8842 __func__, MAC_ADDR_ARRAY(peer));
8843
8844 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
8845 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
8846
8847 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8848 " %s TDLS External control and Implicit Trigger not enabled ",
8849 __func__);
8850 return -ENOTSUPP;
8851 }
8852
Sunil Dutt41de4e22013-11-14 18:09:02 +05308853
8854 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8855
8856 if ( NULL == pTdlsPeer ) {
8857 hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR
8858 " peer not exsting",
8859 __func__, MAC_ADDR_ARRAY(peer));
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308860 return -EINVAL;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308861 }
8862 else {
8863 wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer,
8864 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
8865 }
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308866
8867 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE) )
8868 return -EINVAL;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308869 break;
8870 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008871 case NL80211_TDLS_SETUP:
Sunil Dutt41de4e22013-11-14 18:09:02 +05308872 {
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308873 hddTdlsPeer_t *pTdlsPeer;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308874 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8875 " %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR,
8876 __func__, MAC_ADDR_ARRAY(peer));
8877
8878 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
8879 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
8880
8881 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8882 " %s TDLS External control and Implicit Trigger not enabled ",
8883 __func__);
8884 return -ENOTSUPP;
8885 }
8886
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308887 /* To cater the requirement of establishing the TDLS link
8888 * irrespective of the data traffic , get an entry of TDLS peer.
8889 */
8890 pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer);
8891 if (pTdlsPeer == NULL) {
8892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8893 "%s: peer " MAC_ADDRESS_STR " not existing",
8894 __func__, MAC_ADDR_ARRAY(peer));
8895 return -EINVAL;
8896 }
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308897
8898 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) {
8899
8900 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8901 " %s TDLS Add Force Peer Failed",
8902 __func__);
8903 return -EINVAL;
8904 }
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308905 break;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308906 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008907 case NL80211_TDLS_DISCOVERY_REQ:
8908 /* We don't support in-driver setup/teardown/discovery */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308909 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8910 "%s: We don't support in-driver setup/teardown/discovery "
8911 ,__func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008912 return -ENOTSUPP;
8913 default:
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308914 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8915 "%s: unsupported event",__func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008916 return -ENOTSUPP;
8917 }
8918 return 0;
8919}
Chilam NG571c65a2013-01-19 12:27:36 +05308920
8921int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
8922 struct net_device *dev, u8 *peer)
8923{
Arif Hussaina7c8e412013-11-20 11:06:42 -08008924 hddLog(VOS_TRACE_LEVEL_INFO,
8925 "tdls send discover req: "MAC_ADDRESS_STR,
8926 MAC_ADDR_ARRAY(peer));
Chilam NG571c65a2013-01-19 12:27:36 +05308927
8928 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
8929 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
8930}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008931#endif
8932
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308933#ifdef WLAN_FEATURE_GTK_OFFLOAD
8934/*
8935 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
8936 * Callback rountine called upon receiving response for
8937 * get offload info
8938 */
8939void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
8940 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
8941{
8942
8943 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308944 tANI_U8 tempReplayCounter[8];
8945 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308946
8947 ENTER();
8948
8949 if (NULL == pAdapter)
8950 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308952 "%s: HDD adapter is Null", __func__);
8953 return ;
8954 }
8955
8956 if (NULL == pGtkOffloadGetInfoRsp)
8957 {
8958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8959 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
8960 return ;
8961 }
8962
8963 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
8964 {
8965 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8966 "%s: wlan Failed to get replay counter value",
8967 __func__);
8968 return ;
8969 }
8970
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308971 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8972 /* Update replay counter */
8973 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
8974 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
8975
8976 {
8977 /* changing from little to big endian since supplicant
8978 * works on big endian format
8979 */
8980 int i;
8981 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
8982
8983 for (i = 0; i < 8; i++)
8984 {
8985 tempReplayCounter[7-i] = (tANI_U8)p[i];
8986 }
8987 }
8988
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308989 /* Update replay counter to NL */
8990 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05308991 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308992}
8993
8994/*
8995 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
8996 * This function is used to offload GTK rekeying job to the firmware.
8997 */
8998int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
8999 struct cfg80211_gtk_rekey_data *data)
9000{
9001 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9002 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9003 hdd_station_ctx_t *pHddStaCtx;
9004 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309005 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309006 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309007 eHalStatus status = eHAL_STATUS_FAILURE;
9008
9009 ENTER();
9010
9011 if (NULL == pAdapter)
9012 {
9013 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9014 "%s: HDD adapter is Null", __func__);
9015 return -ENODEV;
9016 }
9017
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309018 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309019
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309020 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309021 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309022 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9023 "%s: HDD context is not valid", __func__);
9024 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309025 }
9026
9027 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9028 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9029 if (NULL == hHal)
9030 {
9031 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9032 "%s: HAL context is Null!!!", __func__);
9033 return -EAGAIN;
9034 }
9035
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309036 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
9037 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
9038 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
9039 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309040 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309041 {
9042 /* changing from big to little endian since driver
9043 * works on little endian format
9044 */
9045 tANI_U8 *p =
9046 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
9047 int i;
9048
9049 for (i = 0; i < 8; i++)
9050 {
9051 p[7-i] = data->replay_ctr[i];
9052 }
9053 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309054
9055 if (TRUE == pHddCtx->hdd_wlan_suspended)
9056 {
9057 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309058 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
9059 sizeof (tSirGtkOffloadParams));
9060 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309061 pAdapter->sessionId);
9062
9063 if (eHAL_STATUS_SUCCESS != status)
9064 {
9065 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9066 "%s: sme_SetGTKOffload failed, returned %d",
9067 __func__, status);
9068 return status;
9069 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309070 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9071 "%s: sme_SetGTKOffload successfull", __func__);
9072 }
9073 else
9074 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309075 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9076 "%s: wlan not suspended GTKOffload request is stored",
9077 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309078 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309079
9080 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309081}
9082#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
9083
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05309084/*
9085 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
9086 * This function is used to set access control policy
9087 */
9088static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
9089 struct net_device *dev, const struct cfg80211_acl_data *params)
9090{
9091 int i;
9092 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9093 hdd_hostapd_state_t *pHostapdState;
9094 tsap_Config_t *pConfig;
9095 v_CONTEXT_t pVosContext = NULL;
9096 hdd_context_t *pHddCtx;
9097 int status;
9098
9099 ENTER();
9100
9101 if (NULL == pAdapter)
9102 {
9103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9104 "%s: HDD adapter is Null", __func__);
9105 return -ENODEV;
9106 }
9107
9108 if (NULL == params)
9109 {
9110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9111 "%s: params is Null", __func__);
9112 return -EINVAL;
9113 }
9114
9115 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9116 status = wlan_hdd_validate_context(pHddCtx);
9117
9118 if (0 != status)
9119 {
9120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9121 "%s: HDD context is not valid", __func__);
9122 return status;
9123 }
9124
9125 pVosContext = pHddCtx->pvosContext;
9126 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9127
9128 if (NULL == pHostapdState)
9129 {
9130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9131 "%s: pHostapdState is Null", __func__);
9132 return -EINVAL;
9133 }
9134
9135 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
9136 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
9137
9138 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
9139 {
9140 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
9141
9142 /* default value */
9143 pConfig->num_accept_mac = 0;
9144 pConfig->num_deny_mac = 0;
9145
9146 /**
9147 * access control policy
9148 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
9149 * listed in hostapd.deny file.
9150 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
9151 * listed in hostapd.accept file.
9152 */
9153 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
9154 {
9155 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
9156 }
9157 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
9158 {
9159 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
9160 }
9161 else
9162 {
9163 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9164 "%s:Acl Policy : %d is not supported",
9165 __func__, params->acl_policy);
9166 return -ENOTSUPP;
9167 }
9168
9169 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
9170 {
9171 pConfig->num_accept_mac = params->n_acl_entries;
9172 for (i = 0; i < params->n_acl_entries; i++)
9173 {
9174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9175 "** Add ACL MAC entry %i in WhiletList :"
9176 MAC_ADDRESS_STR, i,
9177 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
9178
9179 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
9180 sizeof(qcmacaddr));
9181 }
9182 }
9183 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
9184 {
9185 pConfig->num_deny_mac = params->n_acl_entries;
9186 for (i = 0; i < params->n_acl_entries; i++)
9187 {
9188 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9189 "** Add ACL MAC entry %i in BlackList :"
9190 MAC_ADDRESS_STR, i,
9191 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
9192
9193 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
9194 sizeof(qcmacaddr));
9195 }
9196 }
9197
9198 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
9199 {
9200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9201 "%s: SAP Set Mac Acl fail", __func__);
9202 return -EINVAL;
9203 }
9204 }
9205 else
9206 {
9207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9208 "%s: Invalid device_mode = %d",
9209 __func__, pAdapter->device_mode);
9210 return -EINVAL;
9211 }
9212
9213 return 0;
9214}
9215
Leo Chang9056f462013-08-01 19:21:11 -07009216#ifdef WLAN_NL80211_TESTMODE
9217#ifdef FEATURE_WLAN_LPHB
Leo Changd9df8aa2013-09-26 13:32:26 -07009218void wlan_hdd_cfg80211_lphb_ind_handler
Leo Chang9056f462013-08-01 19:21:11 -07009219(
9220 void *pAdapter,
9221 void *indCont
9222)
9223{
Leo Changd9df8aa2013-09-26 13:32:26 -07009224 tSirLPHBInd *lphbInd;
9225 struct sk_buff *skb;
Leo Chang9056f462013-08-01 19:21:11 -07009226
9227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -07009228 "LPHB indication arrived");
Leo Chang9056f462013-08-01 19:21:11 -07009229
9230 if (NULL == indCont)
9231 {
9232 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -07009233 "LPHB IND, invalid argument");
Leo Chang9056f462013-08-01 19:21:11 -07009234 return;
9235 }
9236
Leo Changd9df8aa2013-09-26 13:32:26 -07009237 lphbInd = (tSirLPHBInd *)indCont;
Leo Chang9056f462013-08-01 19:21:11 -07009238 skb = cfg80211_testmode_alloc_event_skb(
9239 ((hdd_adapter_t *)pAdapter)->wdev.wiphy,
Leo Changd9df8aa2013-09-26 13:32:26 -07009240 sizeof(tSirLPHBInd),
Leo Chang9056f462013-08-01 19:21:11 -07009241 GFP_ATOMIC);
9242 if (!skb)
9243 {
9244 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9245 "LPHB timeout, NL buffer alloc fail");
9246 return;
9247 }
9248
Leo Changac3ba772013-10-07 09:47:04 -07009249 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB))
Leo Changd9df8aa2013-09-26 13:32:26 -07009250 {
9251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9252 "WLAN_HDD_TM_ATTR_CMD put fail");
9253 goto nla_put_failure;
9254 }
Leo Changac3ba772013-10-07 09:47:04 -07009255 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType))
Leo Changd9df8aa2013-09-26 13:32:26 -07009256 {
9257 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9258 "WLAN_HDD_TM_ATTR_TYPE put fail");
9259 goto nla_put_failure;
9260 }
Leo Changac3ba772013-10-07 09:47:04 -07009261 if(nla_put(skb, WLAN_HDD_TM_ATTR_DATA,
Leo Changd9df8aa2013-09-26 13:32:26 -07009262 sizeof(tSirLPHBInd), lphbInd))
9263 {
9264 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9265 "WLAN_HDD_TM_ATTR_DATA put fail");
9266 goto nla_put_failure;
9267 }
Leo Chang9056f462013-08-01 19:21:11 -07009268 cfg80211_testmode_event(skb, GFP_ATOMIC);
9269 return;
9270
9271nla_put_failure:
9272 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9273 "NLA Put fail");
9274 kfree_skb(skb);
9275
9276 return;
9277}
9278#endif /* FEATURE_WLAN_LPHB */
9279
9280static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
9281{
9282 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
9283 int err = 0;
9284#ifdef FEATURE_WLAN_LPHB
9285 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Leo Changd9df8aa2013-09-26 13:32:26 -07009286 eHalStatus smeStatus;
Leo Chang9056f462013-08-01 19:21:11 -07009287#endif /* FEATURE_WLAN_LPHB */
9288
9289 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
9290 if (err)
9291 {
9292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9293 "%s Testmode INV ATTR", __func__);
9294 return err;
9295 }
9296
9297 if (!tb[WLAN_HDD_TM_ATTR_CMD])
9298 {
9299 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9300 "%s Testmode INV CMD", __func__);
9301 return -EINVAL;
9302 }
9303
9304 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
9305 {
9306#ifdef FEATURE_WLAN_LPHB
9307 /* Low Power Heartbeat configuration request */
9308 case WLAN_HDD_TM_CMD_WLAN_HB:
9309 {
9310 int buf_len;
9311 void *buf;
9312 tSirLPHBReq *hb_params = NULL;
9313
9314 if (!tb[WLAN_HDD_TM_ATTR_DATA])
9315 {
9316 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9317 "%s Testmode INV DATA", __func__);
9318 return -EINVAL;
9319 }
9320
9321 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
9322 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
9323 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
9324 if (NULL == hb_params)
9325 {
9326 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9327 "%s Request Buffer Alloc Fail", __func__);
9328 return -EINVAL;
9329 }
9330
9331 vos_mem_copy(hb_params, buf, buf_len);
Leo Changd9df8aa2013-09-26 13:32:26 -07009332 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
9333 hb_params,
9334 wlan_hdd_cfg80211_lphb_ind_handler);
9335 if (eHAL_STATUS_SUCCESS != smeStatus)
Leo Chang9056f462013-08-01 19:21:11 -07009336 {
Leo Changd9df8aa2013-09-26 13:32:26 -07009337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9338 "LPHB Config Fail, disable");
Leo Chang9056f462013-08-01 19:21:11 -07009339 vos_mem_free(hb_params);
9340 }
Leo Chang9056f462013-08-01 19:21:11 -07009341 return 0;
9342 }
9343#endif /* FEATURE_WLAN_LPHB */
9344 default:
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309345 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9346 "%s: unsupported event",__func__);
Leo Chang9056f462013-08-01 19:21:11 -07009347 return -EOPNOTSUPP;
9348 }
9349
9350 return err;
9351}
9352#endif /* CONFIG_NL80211_TESTMODE */
9353
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309354static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
9355 struct net_device *dev,
9356 int idx, struct survey_info *survey)
9357{
9358 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9359 hdd_context_t *pHddCtx;
Mihir Sheted9072e02013-08-21 17:02:29 +05309360 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309361 tHalHandle halHandle;
Mihir Sheted9072e02013-08-21 17:02:29 +05309362 v_U32_t channel = 0, freq = 0; /* Initialization Required */
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309363 v_S7_t snr,rssi;
9364 int status, i, j, filled = 0;
9365
9366 ENTER();
9367
9368
9369 if (NULL == pAdapter)
9370 {
9371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9372 "%s: HDD adapter is Null", __func__);
9373 return -ENODEV;
9374 }
9375
9376 if (NULL == wiphy)
9377 {
9378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9379 "%s: wiphy is Null", __func__);
9380 return -ENODEV;
9381 }
9382
9383 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9384 status = wlan_hdd_validate_context(pHddCtx);
9385
9386 if (0 != status)
9387 {
9388 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9389 "%s: HDD context is not valid", __func__);
9390 return status;
9391 }
9392
Mihir Sheted9072e02013-08-21 17:02:29 +05309393 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9394
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309395 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
Mihir Sheted9072e02013-08-21 17:02:29 +05309396 0 != pAdapter->survey_idx ||
9397 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309398 {
9399 /* The survey dump ops when implemented completely is expected to
9400 * return a survey of all channels and the ops is called by the
9401 * kernel with incremental values of the argument 'idx' till it
9402 * returns -ENONET. But we can only support the survey for the
9403 * operating channel for now. survey_idx is used to track
9404 * that the ops is called only once and then return -ENONET for
9405 * the next iteration
9406 */
9407 pAdapter->survey_idx = 0;
9408 return -ENONET;
9409 }
9410
9411 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9412
9413 wlan_hdd_get_snr(pAdapter, &snr);
9414 wlan_hdd_get_rssi(pAdapter, &rssi);
9415
9416 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
9417 hdd_wlan_get_freq(channel, &freq);
9418
9419
9420 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
9421 {
9422 if (NULL == wiphy->bands[i])
9423 {
9424 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
9425 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
9426 continue;
9427 }
9428
9429 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
9430 {
9431 struct ieee80211_supported_band *band = wiphy->bands[i];
9432
9433 if (band->channels[j].center_freq == (v_U16_t)freq)
9434 {
9435 survey->channel = &band->channels[j];
9436 /* The Rx BDs contain SNR values in dB for the received frames
9437 * while the supplicant expects noise. So we calculate and
9438 * return the value of noise (dBm)
9439 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
9440 */
9441 survey->noise = rssi - snr;
9442 survey->filled = SURVEY_INFO_NOISE_DBM;
9443 filled = 1;
9444 }
9445 }
9446 }
9447
9448 if (filled)
9449 pAdapter->survey_idx = 1;
9450 else
9451 {
9452 pAdapter->survey_idx = 0;
9453 return -ENONET;
9454 }
9455
9456 return 0;
9457}
9458
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309459/*
9460 * FUNCTION: wlan_hdd_cfg80211_resume_wlan
9461 * this is called when cfg80211 driver resume
9462 * driver updates latest sched_scan scan result(if any) to cfg80211 database
9463 */
9464int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
9465{
9466 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9467 hdd_adapter_t *pAdapter;
9468 hdd_adapter_list_node_t *pAdapterNode, *pNext;
9469 VOS_STATUS status = VOS_STATUS_SUCCESS;
9470
9471 ENTER();
9472
9473 if ( NULL == pHddCtx )
9474 {
9475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9476 "%s: HddCtx validation failed", __func__);
9477 return 0;
9478 }
9479
9480 if (pHddCtx->isLogpInProgress)
9481 {
9482 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9483 "%s: LOGP in Progress. Ignore!!!", __func__);
9484 return 0;
9485 }
9486
9487 if (pHddCtx->isLoadUnloadInProgress)
9488 {
9489 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9490 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
9491 return 0;
9492 }
9493
9494 spin_lock(&pHddCtx->schedScan_lock);
9495 pHddCtx->isWiphySuspended = FALSE;
9496 if (TRUE != pHddCtx->isSchedScanUpdatePending)
9497 {
9498 spin_unlock(&pHddCtx->schedScan_lock);
9499 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9500 "%s: Return resume is not due to PNO indication", __func__);
9501 return 0;
9502 }
9503 // Reset flag to avoid updatating cfg80211 data old results again
9504 pHddCtx->isSchedScanUpdatePending = FALSE;
9505 spin_unlock(&pHddCtx->schedScan_lock);
9506
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309507
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309508 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9509
9510 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9511 {
9512 pAdapter = pAdapterNode->pAdapter;
9513 if ( (NULL != pAdapter) &&
9514 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
9515 {
9516 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309517 {
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309518 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9519 "%s: NO SCAN result", __func__);
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309520 }
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309521 else
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309522 {
9523 /* Acquire wakelock to handle the case where APP's tries to
9524 * suspend immediately after updating the scan results. Whis
9525 * results in app's is in suspended state and not able to
9526 * process the connect request to AP
9527 */
9528 hdd_prevent_suspend_timeout(2000);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309529 cfg80211_sched_scan_results(pHddCtx->wiphy);
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309530 }
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309531
9532 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9533 "%s : cfg80211 scan result database updated", __func__);
9534
9535 return 0;
9536
9537 }
9538 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9539 pAdapterNode = pNext;
9540 }
9541
9542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9543 "%s: Failed to find Adapter", __func__);
9544 return 0;
9545}
9546
9547/*
9548 * FUNCTION: wlan_hdd_cfg80211_suspend_wlan
9549 * this is called when cfg80211 driver suspends
9550 */
9551int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
9552 struct cfg80211_wowlan *wow)
9553{
9554 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9555
9556 ENTER();
9557 if (NULL == pHddCtx)
9558 {
9559 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9560 "%s: HddCtx validation failed", __func__);
9561 return 0;
9562 }
9563
9564 pHddCtx->isWiphySuspended = TRUE;
9565
9566 EXIT();
9567
9568 return 0;
9569}
9570
Jeff Johnson295189b2012-06-20 16:38:30 -07009571/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309572static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -07009573{
9574 .add_virtual_intf = wlan_hdd_add_virtual_intf,
9575 .del_virtual_intf = wlan_hdd_del_virtual_intf,
9576 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
9577 .change_station = wlan_hdd_change_station,
9578#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
9579 .add_beacon = wlan_hdd_cfg80211_add_beacon,
9580 .del_beacon = wlan_hdd_cfg80211_del_beacon,
9581 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07009582#else
9583 .start_ap = wlan_hdd_cfg80211_start_ap,
9584 .change_beacon = wlan_hdd_cfg80211_change_beacon,
9585 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07009586#endif
9587 .change_bss = wlan_hdd_cfg80211_change_bss,
9588 .add_key = wlan_hdd_cfg80211_add_key,
9589 .get_key = wlan_hdd_cfg80211_get_key,
9590 .del_key = wlan_hdd_cfg80211_del_key,
9591 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08009592#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07009593 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08009594#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009595 .scan = wlan_hdd_cfg80211_scan,
9596 .connect = wlan_hdd_cfg80211_connect,
9597 .disconnect = wlan_hdd_cfg80211_disconnect,
9598 .join_ibss = wlan_hdd_cfg80211_join_ibss,
9599 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
9600 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
9601 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
9602 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07009603 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
9604 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
9605 .mgmt_tx = wlan_hdd_action,
9606#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9607 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
9608 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
9609 .set_txq_params = wlan_hdd_set_txq_params,
9610#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009611 .get_station = wlan_hdd_cfg80211_get_station,
9612 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
9613 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07009614 .add_station = wlan_hdd_cfg80211_add_station,
9615#ifdef FEATURE_WLAN_LFR
9616 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
9617 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
9618 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
9619#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07009620#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
9621 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
9622#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08009623#ifdef FEATURE_WLAN_TDLS
9624 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
9625 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
9626#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309627#ifdef WLAN_FEATURE_GTK_OFFLOAD
9628 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
9629#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05309630#ifdef FEATURE_WLAN_SCAN_PNO
9631 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
9632 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
9633#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309634 .resume = wlan_hdd_cfg80211_resume_wlan,
9635 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05309636 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -07009637#ifdef WLAN_NL80211_TESTMODE
9638 .testmode_cmd = wlan_hdd_cfg80211_testmode,
9639#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309640 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -07009641};
9642