blob: ce7a01a9bc7457baf995ba7af3abff0ae94d249f [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lamaa8e15a2014-02-11 23:30:06 -08002 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
3 * All Rights Reserved.
4 * Qualcomm Atheros Confidential and Proprietary.
5 */
Jeff Johnson295189b2012-06-20 16:38:30 -07006/**========================================================================
7
8 \file wlan_hdd_cfg80211.c
9
10 \brief WLAN Host Device Driver implementation
11
Gopichand Nakkala747461f2013-04-24 19:24:45 +053012 Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070013
Gopichand Nakkala747461f2013-04-24 19:24:45 +053014 Qualcomm Technologies Confidential and Proprietary.
Jeff Johnson295189b2012-06-20 16:38:30 -070015
16 ========================================================================*/
17
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070018/**=========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -070019
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070020 EDIT HISTORY FOR FILE
Jeff Johnson295189b2012-06-20 16:38:30 -070021
22
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070023 This section contains comments describing changes made to the module.
24 Notice that changes are listed in reverse chronological order.
Jeff Johnson295189b2012-06-20 16:38:30 -070025
26
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070027 $Header:$ $DateTime: $ $Author: $
Jeff Johnson295189b2012-06-20 16:38:30 -070028
29
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070030 when who what, where, why
Jeff Johnson295189b2012-06-20 16:38:30 -070031 -------- --- --------------------------------------------------------
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070032 21/12/09 Ashwani Created module.
Jeff Johnson295189b2012-06-20 16:38:30 -070033
34 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070035 Ganesh K
Jeff Johnson295189b2012-06-20 16:38:30 -070036 ==========================================================================*/
37
Jeff Johnson295189b2012-06-20 16:38:30 -070038
39#include <linux/version.h>
40#include <linux/module.h>
41#include <linux/kernel.h>
42#include <linux/init.h>
43#include <linux/wireless.h>
44#include <wlan_hdd_includes.h>
45#include <net/arp.h>
46#include <net/cfg80211.h>
47#include <linux/wireless.h>
48#include <wlan_hdd_wowl.h>
49#include <aniGlobal.h>
50#include "ccmApi.h"
51#include "sirParams.h"
52#include "dot11f.h"
53#include "wlan_hdd_assoc.h"
54#include "wlan_hdd_wext.h"
55#include "sme_Api.h"
56#include "wlan_hdd_p2p.h"
57#include "wlan_hdd_cfg80211.h"
58#include "wlan_hdd_hostapd.h"
59#include "sapInternal.h"
60#include "wlan_hdd_softap_tx_rx.h"
61#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053062#include "wlan_hdd_assoc.h"
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053063#include "wlan_hdd_power.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070064#ifdef WLAN_BTAMP_FEATURE
65#include "bap_hdd_misc.h"
66#endif
67#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -080068#ifdef FEATURE_WLAN_TDLS
69#include "wlan_hdd_tdls.h"
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053070#include "wlan_hdd_wmm.h"
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +053071#include "wlan_qct_wda.h"
Mohit Khanna698ba2a2012-12-04 15:08:18 -080072#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +053073#include "wlan_nv.h"
Leo Chang6fe1f922013-06-07 19:21:24 -070074#include "wlan_hdd_dev_pwr.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070075
76#define g_mode_rates_size (12)
77#define a_mode_rates_size (8)
78#define FREQ_BASE_80211G (2407)
79#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070080#define MAX_SCAN_SSID 9
Kiet Lamac06e2c2013-10-23 16:25:07 +053081#define MAX_PENDING_LOG 5
Jeff Johnson295189b2012-06-20 16:38:30 -070082#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
83 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
84
85#define HDD2GHZCHAN(freq, chan, flag) { \
86 .band = IEEE80211_BAND_2GHZ, \
87 .center_freq = (freq), \
88 .hw_value = (chan),\
89 .flags = (flag), \
90 .max_antenna_gain = 0 ,\
91 .max_power = 30, \
92}
93
94#define HDD5GHZCHAN(freq, chan, flag) { \
95 .band = IEEE80211_BAND_5GHZ, \
96 .center_freq = (freq), \
97 .hw_value = (chan),\
98 .flags = (flag), \
99 .max_antenna_gain = 0 ,\
100 .max_power = 30, \
101}
102
103#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
104{\
105 .bitrate = rate, \
106 .hw_value = rate_id, \
107 .flags = flag, \
108}
109
Lee Hoonkic1262f22013-01-24 21:59:00 -0800110#ifndef WLAN_FEATURE_TDLS_DEBUG
111#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
112#else
113#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
114#endif
115
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530116#ifdef WLAN_FEATURE_VOWIFI_11R
117#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
118#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
119#endif
120
Naresh Jayaram3180aa42014-02-12 21:47:26 +0530121#define HDD_CHANNEL_14 14
122
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530123static const u32 hdd_cipher_suites[] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700124{
125 WLAN_CIPHER_SUITE_WEP40,
126 WLAN_CIPHER_SUITE_WEP104,
127 WLAN_CIPHER_SUITE_TKIP,
128#ifdef FEATURE_WLAN_CCX
129#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
130 WLAN_CIPHER_SUITE_KRK,
131 WLAN_CIPHER_SUITE_CCMP,
132#else
133 WLAN_CIPHER_SUITE_CCMP,
134#endif
135#ifdef FEATURE_WLAN_WAPI
136 WLAN_CIPHER_SUITE_SMS4,
137#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700138#ifdef WLAN_FEATURE_11W
139 WLAN_CIPHER_SUITE_AES_CMAC,
140#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700141};
142
143static inline int is_broadcast_ether_addr(const u8 *addr)
144{
145 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
146 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
147}
148
149static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530150{
Jeff Johnson295189b2012-06-20 16:38:30 -0700151 HDD2GHZCHAN(2412, 1, 0) ,
152 HDD2GHZCHAN(2417, 2, 0) ,
153 HDD2GHZCHAN(2422, 3, 0) ,
154 HDD2GHZCHAN(2427, 4, 0) ,
155 HDD2GHZCHAN(2432, 5, 0) ,
156 HDD2GHZCHAN(2437, 6, 0) ,
157 HDD2GHZCHAN(2442, 7, 0) ,
158 HDD2GHZCHAN(2447, 8, 0) ,
159 HDD2GHZCHAN(2452, 9, 0) ,
160 HDD2GHZCHAN(2457, 10, 0) ,
161 HDD2GHZCHAN(2462, 11, 0) ,
162 HDD2GHZCHAN(2467, 12, 0) ,
163 HDD2GHZCHAN(2472, 13, 0) ,
164 HDD2GHZCHAN(2484, 14, 0) ,
165};
166
Jeff Johnson295189b2012-06-20 16:38:30 -0700167static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
168{
169 HDD2GHZCHAN(2412, 1, 0) ,
170 HDD2GHZCHAN(2437, 6, 0) ,
171 HDD2GHZCHAN(2462, 11, 0) ,
172};
Jeff Johnson295189b2012-06-20 16:38:30 -0700173
174static struct ieee80211_channel hdd_channels_5_GHZ[] =
175{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700176 HDD5GHZCHAN(4920, 240, 0) ,
177 HDD5GHZCHAN(4940, 244, 0) ,
178 HDD5GHZCHAN(4960, 248, 0) ,
179 HDD5GHZCHAN(4980, 252, 0) ,
180 HDD5GHZCHAN(5040, 208, 0) ,
181 HDD5GHZCHAN(5060, 212, 0) ,
182 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700183 HDD5GHZCHAN(5180, 36, 0) ,
184 HDD5GHZCHAN(5200, 40, 0) ,
185 HDD5GHZCHAN(5220, 44, 0) ,
186 HDD5GHZCHAN(5240, 48, 0) ,
187 HDD5GHZCHAN(5260, 52, 0) ,
188 HDD5GHZCHAN(5280, 56, 0) ,
189 HDD5GHZCHAN(5300, 60, 0) ,
190 HDD5GHZCHAN(5320, 64, 0) ,
191 HDD5GHZCHAN(5500,100, 0) ,
192 HDD5GHZCHAN(5520,104, 0) ,
193 HDD5GHZCHAN(5540,108, 0) ,
194 HDD5GHZCHAN(5560,112, 0) ,
195 HDD5GHZCHAN(5580,116, 0) ,
196 HDD5GHZCHAN(5600,120, 0) ,
197 HDD5GHZCHAN(5620,124, 0) ,
198 HDD5GHZCHAN(5640,128, 0) ,
199 HDD5GHZCHAN(5660,132, 0) ,
200 HDD5GHZCHAN(5680,136, 0) ,
201 HDD5GHZCHAN(5700,140, 0) ,
Leo Chang80de3c22013-11-26 10:52:12 -0800202#ifdef FEATURE_WLAN_CH144
203 HDD5GHZCHAN(5720,144, 0) ,
204#endif /* FEATURE_WLAN_CH144 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700205 HDD5GHZCHAN(5745,149, 0) ,
206 HDD5GHZCHAN(5765,153, 0) ,
207 HDD5GHZCHAN(5785,157, 0) ,
208 HDD5GHZCHAN(5805,161, 0) ,
209 HDD5GHZCHAN(5825,165, 0) ,
210};
211
212static struct ieee80211_rate g_mode_rates[] =
213{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530214 HDD_G_MODE_RATETAB(10, 0x1, 0),
215 HDD_G_MODE_RATETAB(20, 0x2, 0),
216 HDD_G_MODE_RATETAB(55, 0x4, 0),
217 HDD_G_MODE_RATETAB(110, 0x8, 0),
218 HDD_G_MODE_RATETAB(60, 0x10, 0),
219 HDD_G_MODE_RATETAB(90, 0x20, 0),
220 HDD_G_MODE_RATETAB(120, 0x40, 0),
221 HDD_G_MODE_RATETAB(180, 0x80, 0),
222 HDD_G_MODE_RATETAB(240, 0x100, 0),
223 HDD_G_MODE_RATETAB(360, 0x200, 0),
224 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 HDD_G_MODE_RATETAB(540, 0x800, 0),
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530226};
Jeff Johnson295189b2012-06-20 16:38:30 -0700227
228static struct ieee80211_rate a_mode_rates[] =
229{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530230 HDD_G_MODE_RATETAB(60, 0x10, 0),
231 HDD_G_MODE_RATETAB(90, 0x20, 0),
232 HDD_G_MODE_RATETAB(120, 0x40, 0),
233 HDD_G_MODE_RATETAB(180, 0x80, 0),
234 HDD_G_MODE_RATETAB(240, 0x100, 0),
235 HDD_G_MODE_RATETAB(360, 0x200, 0),
236 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700237 HDD_G_MODE_RATETAB(540, 0x800, 0),
238};
239
240static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
241{
242 .channels = hdd_channels_2_4_GHZ,
243 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
244 .band = IEEE80211_BAND_2GHZ,
245 .bitrates = g_mode_rates,
246 .n_bitrates = g_mode_rates_size,
247 .ht_cap.ht_supported = 1,
248 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
249 | IEEE80211_HT_CAP_GRN_FLD
250 | IEEE80211_HT_CAP_DSSSCCK40
251 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
252 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
253 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
254 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
255 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
256 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
257};
258
Jeff Johnson295189b2012-06-20 16:38:30 -0700259static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
260{
261 .channels = hdd_social_channels_2_4_GHZ,
262 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
263 .band = IEEE80211_BAND_2GHZ,
264 .bitrates = g_mode_rates,
265 .n_bitrates = g_mode_rates_size,
266 .ht_cap.ht_supported = 1,
267 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
268 | IEEE80211_HT_CAP_GRN_FLD
269 | IEEE80211_HT_CAP_DSSSCCK40
270 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
271 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
272 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
273 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
274 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
275 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
276};
Jeff Johnson295189b2012-06-20 16:38:30 -0700277
278static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
279{
280 .channels = hdd_channels_5_GHZ,
281 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
282 .band = IEEE80211_BAND_5GHZ,
283 .bitrates = a_mode_rates,
284 .n_bitrates = a_mode_rates_size,
285 .ht_cap.ht_supported = 1,
286 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
287 | IEEE80211_HT_CAP_GRN_FLD
288 | IEEE80211_HT_CAP_DSSSCCK40
289 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
290 | IEEE80211_HT_CAP_SGI_40
291 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
292 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
293 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
294 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
295 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
296 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
297};
298
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530299/* This structure contain information what kind of frame are expected in
Jeff Johnson295189b2012-06-20 16:38:30 -0700300 TX/RX direction for each kind of interface */
301static const struct ieee80211_txrx_stypes
302wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
303 [NL80211_IFTYPE_STATION] = {
304 .tx = 0xffff,
305 .rx = BIT(SIR_MAC_MGMT_ACTION) |
306 BIT(SIR_MAC_MGMT_PROBE_REQ),
307 },
308 [NL80211_IFTYPE_AP] = {
309 .tx = 0xffff,
310 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
311 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
312 BIT(SIR_MAC_MGMT_PROBE_REQ) |
313 BIT(SIR_MAC_MGMT_DISASSOC) |
314 BIT(SIR_MAC_MGMT_AUTH) |
315 BIT(SIR_MAC_MGMT_DEAUTH) |
316 BIT(SIR_MAC_MGMT_ACTION),
317 },
Jeff Johnsonbc006202013-04-29 14:05:30 -0700318 [NL80211_IFTYPE_ADHOC] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
321 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
322 BIT(SIR_MAC_MGMT_PROBE_REQ) |
323 BIT(SIR_MAC_MGMT_DISASSOC) |
324 BIT(SIR_MAC_MGMT_AUTH) |
325 BIT(SIR_MAC_MGMT_DEAUTH) |
326 BIT(SIR_MAC_MGMT_ACTION),
327 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700328 [NL80211_IFTYPE_P2P_CLIENT] = {
329 .tx = 0xffff,
330 .rx = BIT(SIR_MAC_MGMT_ACTION) |
331 BIT(SIR_MAC_MGMT_PROBE_REQ),
332 },
333 [NL80211_IFTYPE_P2P_GO] = {
334 /* This is also same as for SoftAP */
335 .tx = 0xffff,
336 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ) |
339 BIT(SIR_MAC_MGMT_DISASSOC) |
340 BIT(SIR_MAC_MGMT_AUTH) |
341 BIT(SIR_MAC_MGMT_DEAUTH) |
342 BIT(SIR_MAC_MGMT_ACTION),
343 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700344};
345
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800346#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800347static const struct ieee80211_iface_limit
348wlan_hdd_iface_limit[] = {
349 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800350 /* max = 3 ; Our driver create two interfaces during driver init
351 * wlan0 and p2p0 interfaces. p2p0 is considered as station
352 * interface until a group is formed. In JB architecture, once the
353 * group is formed, interface type of p2p0 is changed to P2P GO or
354 * Client.
355 * When supplicant remove the group, it first issue a set interface
356 * cmd to change the mode back to Station. In JB this works fine as
357 * we advertize two station type interface during driver init.
358 * Some vendors create separate interface for P2P GO/Client,
359 * after group formation(Third one). But while group remove
360 * supplicant first tries to change the mode(3rd interface) to STATION
361 * But as we advertized only two sta type interfaces nl80211 was
362 * returning error for the third one which was leading to failure in
363 * delete interface. Ideally while removing the group, supplicant
364 * should not try to change the 3rd interface mode to Station type.
365 * Till we get a fix in wpa_supplicant, we advertize max STA
366 * interface type to 3
367 */
368 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800369 .types = BIT(NL80211_IFTYPE_STATION),
370 },
371 {
372 .max = 1,
Jeff Johnsonbc006202013-04-29 14:05:30 -0700373 .types = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP),
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800374 },
375 {
376 .max = 1,
377 .types = BIT(NL80211_IFTYPE_P2P_GO) |
378 BIT(NL80211_IFTYPE_P2P_CLIENT),
379 },
380};
381
382/* By default, only single channel concurrency is allowed */
383static struct ieee80211_iface_combination
384wlan_hdd_iface_combination = {
385 .limits = wlan_hdd_iface_limit,
386 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800387 /*
388 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
389 * and p2p0 interfaces during driver init
390 * Some vendors create separate interface for P2P operations.
391 * wlan0: STA interface
392 * p2p0: P2P Device interface, action frames goes
393 * through this interface.
394 * p2p-xx: P2P interface, After GO negotiation this interface is
395 * created for p2p operations(GO/CLIENT interface).
396 */
397 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800398 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
399 .beacon_int_infra_match = false,
400};
401#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800402
Jeff Johnson295189b2012-06-20 16:38:30 -0700403static struct cfg80211_ops wlan_hdd_cfg80211_ops;
404
405/* Data rate 100KBPS based on IE Index */
406struct index_data_rate_type
407{
408 v_U8_t beacon_rate_index;
409 v_U16_t supported_rate[4];
410};
411
412/* 11B, 11G Rate table include Basic rate and Extended rate
413 The IDX field is the rate index
414 The HI field is the rate when RSSI is strong or being ignored
415 (in this case we report actual rate)
416 The MID field is the rate when RSSI is moderate
417 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
418 The LO field is the rate when RSSI is low
419 (in this case we don't report rates, actual current rate used)
420 */
421static const struct
422{
423 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700424 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700425} supported_data_rate[] =
426{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700427/* IDX HI HM LM LO (RSSI-based index */
428 {2, { 10, 10, 10, 0}},
429 {4, { 20, 20, 10, 0}},
430 {11, { 55, 20, 10, 0}},
431 {12, { 60, 55, 20, 0}},
432 {18, { 90, 55, 20, 0}},
433 {22, {110, 55, 20, 0}},
434 {24, {120, 90, 60, 0}},
435 {36, {180, 120, 60, 0}},
436 {44, {220, 180, 60, 0}},
437 {48, {240, 180, 90, 0}},
438 {66, {330, 180, 90, 0}},
439 {72, {360, 240, 90, 0}},
440 {96, {480, 240, 120, 0}},
441 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700442};
443
444/* MCS Based rate table */
445static struct index_data_rate_type supported_mcs_rate[] =
446{
447/* MCS L20 L40 S20 S40 */
448 {0, {65, 135, 72, 150}},
449 {1, {130, 270, 144, 300}},
450 {2, {195, 405, 217, 450}},
451 {3, {260, 540, 289, 600}},
452 {4, {390, 810, 433, 900}},
453 {5, {520, 1080, 578, 1200}},
454 {6, {585, 1215, 650, 1350}},
455 {7, {650, 1350, 722, 1500}}
456};
457
Leo Chang6f8870f2013-03-26 18:11:36 -0700458#ifdef WLAN_FEATURE_11AC
459
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530460#define DATA_RATE_11AC_MCS_MASK 0x03
Leo Chang6f8870f2013-03-26 18:11:36 -0700461
462struct index_vht_data_rate_type
463{
464 v_U8_t beacon_rate_index;
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530465 v_U16_t supported_VHT80_rate[2];
466 v_U16_t supported_VHT40_rate[2];
467 v_U16_t supported_VHT20_rate[2];
Leo Chang6f8870f2013-03-26 18:11:36 -0700468};
469
470typedef enum
471{
472 DATA_RATE_11AC_MAX_MCS_7,
473 DATA_RATE_11AC_MAX_MCS_8,
474 DATA_RATE_11AC_MAX_MCS_9,
475 DATA_RATE_11AC_MAX_MCS_NA
476} eDataRate11ACMaxMcs;
477
478/* MCS Based VHT rate table */
479static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
480{
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530481/* MCS L80 S80 L40 S40 L20 S40*/
482 {0, {293, 325}, {135, 150}, {65, 72}},
483 {1, {585, 650}, {270, 300}, {130, 144}},
484 {2, {878, 975}, {405, 450}, {195, 217}},
485 {3, {1170, 1300}, {540, 600}, {260, 289}},
486 {4, {1755, 1950}, {810, 900}, {390, 433}},
487 {5, {2340, 2600}, {1080, 1200}, {520, 578}},
488 {6, {2633, 2925}, {1215, 1350}, {585, 650}},
489 {7, {2925, 3250}, {1350, 1500}, {650, 722}},
490 {8, {3510, 3900}, {1620, 1800}, {780, 867}},
491 {9, {3900, 4333}, {1800, 2000}, {780, 867}}
Leo Chang6f8870f2013-03-26 18:11:36 -0700492};
493#endif /* WLAN_FEATURE_11AC */
494
Jeff Johnson295189b2012-06-20 16:38:30 -0700495extern struct net_device_ops net_ops_struct;
496
Leo Chang9056f462013-08-01 19:21:11 -0700497#ifdef WLAN_NL80211_TESTMODE
498enum wlan_hdd_tm_attr
499{
500 WLAN_HDD_TM_ATTR_INVALID = 0,
501 WLAN_HDD_TM_ATTR_CMD = 1,
502 WLAN_HDD_TM_ATTR_DATA = 2,
503 WLAN_HDD_TM_ATTR_TYPE = 3,
504 /* keep last */
505 WLAN_HDD_TM_ATTR_AFTER_LAST,
506 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
507};
508
509enum wlan_hdd_tm_cmd
510{
511 WLAN_HDD_TM_CMD_WLAN_HB = 1,
512};
513
514#define WLAN_HDD_TM_DATA_MAX_LEN 5000
515
516static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] =
517{
518 [WLAN_HDD_TM_ATTR_CMD] = { .type = NLA_U32 },
519 [WLAN_HDD_TM_ATTR_DATA] = { .type = NLA_BINARY,
520 .len = WLAN_HDD_TM_DATA_MAX_LEN },
521};
522#endif /* WLAN_NL80211_TESTMODE */
523
Rajesh Chauhan98a31f82014-01-06 20:15:25 -0800524#ifdef FEATURE_WLAN_CH_AVOID
525/*
526 * FUNCTION: wlan_hdd_send_avoid_freq_event
527 * This is called when wlan driver needs to send vendor specific
528 * avoid frequency range event to userspace
529 */
530int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
531 tHddAvoidFreqList *pAvoidFreqList)
532{
533 struct sk_buff *vendor_event;
534
535 ENTER();
536
537 if (!pHddCtx)
538 {
539 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
540 "%s: HDD context is null", __func__);
541 return -1;
542 }
543
544 if (!pAvoidFreqList)
545 {
546 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
547 "%s: pAvoidFreqList is null", __func__);
548 return -1;
549 }
550
551 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
552 sizeof(tHddAvoidFreqList),
553 QCOM_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
554 GFP_KERNEL);
555 if (!vendor_event)
556 {
557 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
558 "%s: cfg80211_vendor_event_alloc failed", __func__);
559 return -1;
560 }
561
562 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
563 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
564
565 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
566
567 EXIT();
568 return 0;
569}
570#endif /* FEATURE_WLAN_CH_AVOID */
571
572/* vendor specific events */
573static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
574{
575#ifdef FEATURE_WLAN_CH_AVOID
576 {
577 .vendor_id = QCOM_NL80211_VENDOR_ID,
578 .subcmd = QCOM_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
579 },
580#endif /* FEATURE_WLAN_CH_AVOID */
581};
582
Jeff Johnson295189b2012-06-20 16:38:30 -0700583/*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530584 * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530585 * This function is called by hdd_wlan_startup()
586 * during initialization.
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530587 * This function is used to allocate wiphy structure.
Jeff Johnson295189b2012-06-20 16:38:30 -0700588 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530589struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size)
Jeff Johnson295189b2012-06-20 16:38:30 -0700590{
591 struct wiphy *wiphy;
592 ENTER();
593
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530594 /*
595 * Create wiphy device
Jeff Johnson295189b2012-06-20 16:38:30 -0700596 */
597 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
598
599 if (!wiphy)
600 {
601 /* Print error and jump into err label and free the memory */
602 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
603 return NULL;
604 }
605
606 return wiphy;
607}
608
609/*
610 * FUNCTION: wlan_hdd_cfg80211_update_band
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530611 * This function is called from the supplicant through a
Jeff Johnson295189b2012-06-20 16:38:30 -0700612 * private ioctl to change the band value
613 */
614int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
615{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530616 int i, j;
617 eNVChannelEnabledType channelEnabledState;
618
Jeff Johnsone7245742012-09-05 17:12:55 -0700619 ENTER();
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530620 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
Jeff Johnson295189b2012-06-20 16:38:30 -0700621 {
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530622
623 if (NULL == wiphy->bands[i])
624 {
625 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
626 __func__, i);
627 continue;
628 }
629
630 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
631 {
632 struct ieee80211_supported_band *band = wiphy->bands[i];
633
634 channelEnabledState = vos_nv_getChannelEnabledState(
635 band->channels[j].hw_value);
636
637 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only
638 {
639 // Enable Social channels for P2P
640 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) &&
641 NV_CHANNEL_ENABLE == channelEnabledState)
642 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
643 else
644 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
645 continue;
646 }
647 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only
648 {
649 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
650 continue;
651 }
652
653 if (NV_CHANNEL_DISABLE == channelEnabledState ||
654 NV_CHANNEL_INVALID == channelEnabledState)
655 {
656 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
657 }
658 else if (NV_CHANNEL_DFS == channelEnabledState)
659 {
660 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
661 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
662 }
663 else
664 {
665 band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
666 |IEEE80211_CHAN_RADAR);
667 }
668 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700669 }
670 return 0;
671}
672/*
673 * FUNCTION: wlan_hdd_cfg80211_init
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530674 * This function is called by hdd_wlan_startup()
675 * during initialization.
Jeff Johnson295189b2012-06-20 16:38:30 -0700676 * This function is used to initialize and register wiphy structure.
677 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530678int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700679 struct wiphy *wiphy,
680 hdd_config_t *pCfg
681 )
682{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530683 int i, j;
Jeff Johnsone7245742012-09-05 17:12:55 -0700684 ENTER();
685
Jeff Johnson295189b2012-06-20 16:38:30 -0700686 /* Now bind the underlying wlan device with wiphy */
687 set_wiphy_dev(wiphy, dev);
688
689 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700690
Kiet Lam6c583332013-10-14 05:37:09 +0530691#ifndef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -0700692 /* the flag for the other case would be initialzed in
693 vos_init_wiphy_from_nv_bin */
Amar Singhal0a402232013-10-11 20:57:16 -0700694 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
Kiet Lam6c583332013-10-14 05:37:09 +0530695#endif
Amar Singhala49cbc52013-10-08 18:37:44 -0700696
Amar Singhalfddc28c2013-09-05 13:03:40 -0700697 /* This will disable updating of NL channels from passive to
698 * active if a beacon is received on passive channel. */
699 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhalf0073192013-09-20 12:34:56 -0700700
Amar Singhalfddc28c2013-09-05 13:03:40 -0700701
Amar Singhala49cbc52013-10-08 18:37:44 -0700702
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700703#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700704 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
705 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
706 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700707 | WIPHY_FLAG_OFFCHAN_TX;
Kiet Lam6c583332013-10-14 05:37:09 +0530708 wiphy->country_ie_pref = NL80211_COUNTRY_IE_IGNORE_CORE;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700709#endif
Amar Singhala49cbc52013-10-08 18:37:44 -0700710
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700711#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
712 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800713#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700714 || pCfg->isFastRoamIniFeatureEnabled
715#endif
716#ifdef FEATURE_WLAN_CCX
717 || pCfg->isCcxIniFeatureEnabled
718#endif
719 )
720 {
721 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
722 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800723#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800724#ifdef FEATURE_WLAN_TDLS
725 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
726 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
727#endif
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530728#ifdef FEATURE_WLAN_SCAN_PNO
Hardik Kantilal Patel3dfd8792013-11-13 20:34:57 +0530729 if (pCfg->configPNOScanSupport)
730 {
731 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
732 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
733 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
734 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
735 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530736#endif/*FEATURE_WLAN_SCAN_PNO*/
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800737
Amar Singhalfddc28c2013-09-05 13:03:40 -0700738#ifdef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700739 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
740 driver can still register regulatory callback and
Amar Singhalfddc28c2013-09-05 13:03:40 -0700741 it will get regulatory settings in wiphy->band[], but
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700742 driver need to determine what to do with both
743 regulatory settings */
Amar Singhalfddc28c2013-09-05 13:03:40 -0700744
745 wiphy->reg_notifier = wlan_hdd_linux_reg_notifier;
Amar Singhala49cbc52013-10-08 18:37:44 -0700746#else
747 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700748#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700749
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530750 wiphy->max_scan_ssids = MAX_SCAN_SSID;
751
Madan Mohan Koyyalamudi6815b162013-07-19 17:17:46 +0530752 wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Jeff Johnson295189b2012-06-20 16:38:30 -0700753
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +0530754 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
755
Jeff Johnson295189b2012-06-20 16:38:30 -0700756 /* Supports STATION & AD-HOC modes right now */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530757 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -0700758 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700759 | BIT(NL80211_IFTYPE_P2P_CLIENT)
760 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700761 | BIT(NL80211_IFTYPE_AP);
762
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800763#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800764 if( pCfg->enableMCC )
765 {
766 /* Currently, supports up to two channels */
767 wlan_hdd_iface_combination.num_different_channels = 2;
768
769 if( !pCfg->allowMCCGODiffBI )
770 wlan_hdd_iface_combination.beacon_int_infra_match = true;
771
772 }
773 wiphy->iface_combinations = &wlan_hdd_iface_combination;
774 wiphy->n_iface_combinations = 1;
775#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800776
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 /* Before registering we need to update the ht capabilitied based
778 * on ini values*/
779 if( !pCfg->ShortGI20MhzEnable )
780 {
781 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
782 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
783 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
784 }
785
786 if( !pCfg->ShortGI40MhzEnable )
787 {
788 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
789 }
790
791 if( !pCfg->nChannelBondingMode5GHz )
792 {
793 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
794 }
795
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530796 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
797 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
798
799 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
800 {
801
802 if (NULL == wiphy->bands[i])
803 {
804 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
805 __func__, i);
806 continue;
807 }
808
809 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
810 {
811 struct ieee80211_supported_band *band = wiphy->bands[i];
812
813 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
814 {
815 // Enable social channels for P2P
816 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
817 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
818 else
819 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
820 continue;
821 }
822 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
823 {
824 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
825 continue;
826 }
827 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700828 }
829 /*Initialise the supported cipher suite details*/
830 wiphy->cipher_suites = hdd_cipher_suites;
831 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
832
833 /*signal strength in mBm (100*dBm) */
834 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
835
836#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700837 wiphy->max_remain_on_channel_duration = 1000;
838#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700839
Rajesh Chauhan98a31f82014-01-06 20:15:25 -0800840 wiphy->n_vendor_commands = 0;
841 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
842 wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
843
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530844 EXIT();
845 return 0;
846}
847
848/* In this function we are registering wiphy. */
849int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
850{
851 ENTER();
852 /* Register our wiphy dev with cfg80211 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700853 if (0 > wiphy_register(wiphy))
854 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530855 /* print error */
Jeff Johnson295189b2012-06-20 16:38:30 -0700856 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
857 return -EIO;
858 }
859
860 EXIT();
861 return 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530862}
Jeff Johnson295189b2012-06-20 16:38:30 -0700863
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530864/* In this function we are updating channel list when,
865 regulatory domain is FCC and country code is US.
866 Here In FCC standard 5GHz UNII-1 Bands are indoor only.
867 As per FCC smart phone is not a indoor device.
868 GO should not opeate on indoor channels */
869void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy)
870{
871 int j;
872 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
873 tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE;
874 //Default counrtycode from NV at the time of wiphy initialization.
875 if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal,
876 &defaultCountryCode[0]))
877 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700878 hddLog(LOGE, FL("Failed to get default country code from NV"));
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530879 }
880 if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S'))
881 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530882 if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ])
883 {
884 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ );
885 return;
886 }
887 for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
888 {
889 struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ];
890 // Mark UNII -1 band channel as passive
891 if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq))
892 band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
893 }
894 }
895}
896
Jeff Johnson295189b2012-06-20 16:38:30 -0700897/* In this function we will do all post VOS start initialization.
898 In this function we will register for all frame in which supplicant
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530899 is interested.
Jeff Johnson295189b2012-06-20 16:38:30 -0700900*/
901void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
902{
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
904 /* Register for all P2P action, public action etc frames */
905 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
906
Jeff Johnsone7245742012-09-05 17:12:55 -0700907 ENTER();
908
Jeff Johnson295189b2012-06-20 16:38:30 -0700909 /* Right now we are registering these frame when driver is getting
910 initialized. Once we will move to 2.6.37 kernel, in which we have
911 frame register ops, we will move this code as a part of that */
912 /* GAS Initial Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530913 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Jeff Johnson295189b2012-06-20 16:38:30 -0700914 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
915
916 /* GAS Initial Response */
917 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
918 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530919
Jeff Johnson295189b2012-06-20 16:38:30 -0700920 /* GAS Comeback Request */
921 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
922 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
923
924 /* GAS Comeback Response */
925 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
926 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
927
928 /* P2P Public Action */
929 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530930 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700931 P2P_PUBLIC_ACTION_FRAME_SIZE );
932
933 /* P2P Action */
934 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
935 (v_U8_t*)P2P_ACTION_FRAME,
936 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700937
Gopichand Nakkalae3d56e72013-04-21 23:33:32 +0530938 /* WNM BSS Transition Request frame */
939 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
940 (v_U8_t*)WNM_BSS_ACTION_FRAME,
941 WNM_BSS_ACTION_FRAME_SIZE );
942
Chet Lanctot186b5732013-03-18 10:26:30 -0700943#ifdef WLAN_FEATURE_11W
944 /* SA Query Response Action Frame */
945 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
946 (v_U8_t*)SA_QUERY_FRAME_RSP,
947 SA_QUERY_FRAME_RSP_SIZE );
948#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700949}
950
951void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
952{
Jeff Johnson295189b2012-06-20 16:38:30 -0700953 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
954 /* Register for all P2P action, public action etc frames */
955 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
956
Jeff Johnsone7245742012-09-05 17:12:55 -0700957 ENTER();
958
Jeff Johnson295189b2012-06-20 16:38:30 -0700959 /* Right now we are registering these frame when driver is getting
960 initialized. Once we will move to 2.6.37 kernel, in which we have
961 frame register ops, we will move this code as a part of that */
962 /* GAS Initial Request */
963
964 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
965 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
966
967 /* GAS Initial Response */
968 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
969 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530970
Jeff Johnson295189b2012-06-20 16:38:30 -0700971 /* GAS Comeback Request */
972 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
973 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
974
975 /* GAS Comeback Response */
976 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
977 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
978
979 /* P2P Public Action */
980 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530981 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700982 P2P_PUBLIC_ACTION_FRAME_SIZE );
983
984 /* P2P Action */
985 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
986 (v_U8_t*)P2P_ACTION_FRAME,
987 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700988
989#ifdef WLAN_FEATURE_11W
990 /* SA Query Response Action Frame */
991 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
992 (v_U8_t*)SA_QUERY_FRAME_RSP,
993 SA_QUERY_FRAME_RSP_SIZE );
994#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700995}
996
997#ifdef FEATURE_WLAN_WAPI
998void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
999 const u8 *mac_addr, u8 *key , int key_Len)
1000{
1001 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1002 tCsrRoamSetKey setKey;
1003 v_BOOL_t isConnected = TRUE;
1004 int status = 0;
1005 v_U32_t roamId= 0xFF;
1006 tANI_U8 *pKeyPtr = NULL;
1007 int n = 0;
1008
Arif Hussain6d2a3322013-11-17 19:50:10 -08001009 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001010 __func__,pAdapter->device_mode);
1011
Gopichand Nakkalae7480202013-02-11 15:24:22 +05301012 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -07001013 setKey.keyId = key_index; // Store Key ID
1014 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
1015 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
1016 setKey.paeRole = 0 ; // the PAE role
1017 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
1018 {
1019 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
1020 }
1021 else
1022 {
1023 isConnected = hdd_connIsConnected(pHddStaCtx);
1024 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
1025 }
1026 setKey.keyLength = key_Len;
1027 pKeyPtr = setKey.Key;
1028 memcpy( pKeyPtr, key, key_Len);
1029
Arif Hussain6d2a3322013-11-17 19:50:10 -08001030 hddLog(VOS_TRACE_LEVEL_INFO,"%s: WAPI KEY LENGTH:0x%04x",
Jeff Johnson295189b2012-06-20 16:38:30 -07001031 __func__, key_Len);
1032 for (n = 0 ; n < key_Len; n++)
1033 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
1034 __func__,n,setKey.Key[n]);
1035
1036 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
1037 if ( isConnected )
1038 {
1039 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
1040 pAdapter->sessionId, &setKey, &roamId );
1041 }
1042 if ( status != 0 )
1043 {
1044 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1045 "[%4d] sme_RoamSetKey returned ERROR status= %d",
1046 __LINE__, status );
1047 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
1048 }
1049}
1050#endif /* FEATURE_WLAN_WAPI*/
1051
1052#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301053int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07001054 beacon_data_t **ppBeacon,
1055 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001056#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301057int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001058 beacon_data_t **ppBeacon,
1059 struct cfg80211_beacon_data *params,
1060 int dtim_period)
1061#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301062{
Jeff Johnson295189b2012-06-20 16:38:30 -07001063 int size;
1064 beacon_data_t *beacon = NULL;
1065 beacon_data_t *old = NULL;
1066 int head_len,tail_len;
1067
Jeff Johnsone7245742012-09-05 17:12:55 -07001068 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001069 if (params->head && !params->head_len)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301070 {
1071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1072 FL("head_len is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001073 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301074 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001075
1076 old = pAdapter->sessionCtx.ap.beacon;
1077
1078 if (!params->head && !old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301079 {
1080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1081 FL("session(%d) old and new heads points to NULL"),
1082 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001083 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301084 }
1085
1086 if (params->tail && !params->tail_len)
1087 {
1088 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1089 FL("tail_len is zero but tail is not NULL"));
1090 return -EINVAL;
1091 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001092
Jeff Johnson295189b2012-06-20 16:38:30 -07001093#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
1094 /* Kernel 3.0 is not updating dtim_period for set beacon */
1095 if (!params->dtim_period)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301096 {
1097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1098 FL("dtim period is 0"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001099 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301100 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001101#endif
1102
1103 if(params->head)
1104 head_len = params->head_len;
1105 else
1106 head_len = old->head_len;
1107
1108 if(params->tail || !old)
1109 tail_len = params->tail_len;
1110 else
1111 tail_len = old->tail_len;
1112
1113 size = sizeof(beacon_data_t) + head_len + tail_len;
1114
1115 beacon = kzalloc(size, GFP_KERNEL);
1116
1117 if( beacon == NULL )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301118 {
1119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1120 FL("Mem allocation for beacon failed"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001121 return -ENOMEM;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301122 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001123
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001124#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001125 if(params->dtim_period || !old )
1126 beacon->dtim_period = params->dtim_period;
1127 else
1128 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001129#else
1130 if(dtim_period || !old )
1131 beacon->dtim_period = dtim_period;
1132 else
1133 beacon->dtim_period = old->dtim_period;
1134#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301135
Jeff Johnson295189b2012-06-20 16:38:30 -07001136 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
1137 beacon->tail = beacon->head + head_len;
1138 beacon->head_len = head_len;
1139 beacon->tail_len = tail_len;
1140
1141 if(params->head) {
1142 memcpy (beacon->head,params->head,beacon->head_len);
1143 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301144 else {
Jeff Johnson295189b2012-06-20 16:38:30 -07001145 if(old)
1146 memcpy (beacon->head,old->head,beacon->head_len);
1147 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301148
Jeff Johnson295189b2012-06-20 16:38:30 -07001149 if(params->tail) {
1150 memcpy (beacon->tail,params->tail,beacon->tail_len);
1151 }
1152 else {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301153 if(old)
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 memcpy (beacon->tail,old->tail,beacon->tail_len);
1155 }
1156
1157 *ppBeacon = beacon;
1158
1159 kfree(old);
1160
1161 return 0;
1162
1163}
Jeff Johnson295189b2012-06-20 16:38:30 -07001164
1165v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
1166{
1167 int left = length;
1168 v_U8_t *ptr = pIes;
1169 v_U8_t elem_id,elem_len;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301170
Jeff Johnson295189b2012-06-20 16:38:30 -07001171 while(left >= 2)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301172 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001173 elem_id = ptr[0];
1174 elem_len = ptr[1];
1175 left -= 2;
1176 if(elem_len > left)
1177 {
1178 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001179 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -07001180 eid,elem_len,left);
1181 return NULL;
1182 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301183 if (elem_id == eid)
Jeff Johnson295189b2012-06-20 16:38:30 -07001184 {
1185 return ptr;
1186 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301187
Jeff Johnson295189b2012-06-20 16:38:30 -07001188 left -= elem_len;
1189 ptr += (elem_len + 2);
1190 }
1191 return NULL;
1192}
1193
Jeff Johnson295189b2012-06-20 16:38:30 -07001194/* Check if rate is 11g rate or not */
1195static int wlan_hdd_rate_is_11g(u8 rate)
1196{
Sanjay Devnani28322e22013-06-21 16:13:40 -07001197 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001198 u8 i;
1199 for (i = 0; i < 8; i++)
1200 {
1201 if(rate == gRateArray[i])
1202 return TRUE;
1203 }
1204 return FALSE;
1205}
1206
1207/* Check for 11g rate and set proper 11g only mode */
1208static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1209 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1210{
1211 u8 i, num_rates = pIe[0];
1212
1213 pIe += 1;
1214 for ( i = 0; i < num_rates; i++)
1215 {
1216 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1217 {
1218 /* If rate set have 11g rate than change the mode to 11G */
1219 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1220 if (pIe[i] & BASIC_RATE_MASK)
1221 {
1222 /* If we have 11g rate as basic rate, it means mode
1223 is 11g only mode.
1224 */
1225 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1226 *pCheckRatesfor11g = FALSE;
1227 }
1228 }
1229 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1230 {
1231 *require_ht = TRUE;
1232 }
1233 }
1234 return;
1235}
1236
1237static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1238{
1239 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1240 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1241 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1242 u8 checkRatesfor11g = TRUE;
1243 u8 require_ht = FALSE;
1244 u8 *pIe=NULL;
1245
1246 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1247
1248 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1249 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1250 if (pIe != NULL)
1251 {
1252 pIe += 1;
1253 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1254 &pConfig->SapHw_mode);
1255 }
1256
1257 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1258 WLAN_EID_EXT_SUPP_RATES);
1259 if (pIe != NULL)
1260 {
1261
1262 pIe += 1;
1263 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1264 &pConfig->SapHw_mode);
1265 }
1266
1267 if( pConfig->channel > 14 )
1268 {
1269 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1270 }
1271
1272 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1273 WLAN_EID_HT_CAPABILITY);
1274
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301275 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 {
1277 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1278 if(require_ht)
1279 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1280 }
1281}
1282
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301283static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1284 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1285{
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001286 v_U16_t ielen = 0;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301287 v_U8_t *pIe = NULL;
1288 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1289
1290 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1291 pBeacon->tail, pBeacon->tail_len);
1292
1293 if (pIe)
1294 {
1295 ielen = pIe[1] + 2;
1296 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1297 {
1298 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1299 }
1300 else
1301 {
1302 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1303 return -EINVAL;
1304 }
1305 *total_ielen += ielen;
1306 }
1307 return 0;
1308}
1309
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001310static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter,
1311 v_U8_t *genie, v_U8_t *total_ielen)
1312{
1313 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1314 int left = pBeacon->tail_len;
1315 v_U8_t *ptr = pBeacon->tail;
1316 v_U8_t elem_id, elem_len;
1317 v_U16_t ielen = 0;
1318
1319 if ( NULL == ptr || 0 == left )
1320 return;
1321
1322 while (left >= 2)
1323 {
1324 elem_id = ptr[0];
1325 elem_len = ptr[1];
1326 left -= 2;
1327 if (elem_len > left)
1328 {
1329 hddLog( VOS_TRACE_LEVEL_ERROR,
1330 "****Invalid IEs eid = %d elem_len=%d left=%d*****",
1331 elem_id, elem_len, left);
1332 return;
1333 }
1334 if (IE_EID_VENDOR == elem_id)
1335 {
1336 /* skipping the VSIE's which we don't want to include or
1337 * it will be included by existing code
1338 */
1339 if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) &&
1340#ifdef WLAN_FEATURE_WFD
1341 (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) &&
1342#endif
1343 (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1344 (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1345 (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) &&
1346 (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1347 (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0))
1348 {
1349 ielen = ptr[1] + 2;
1350 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1351 {
1352 vos_mem_copy(&genie[*total_ielen], ptr, ielen);
1353 *total_ielen += ielen;
1354 }
1355 else
1356 {
1357 hddLog( VOS_TRACE_LEVEL_ERROR,
1358 "IE Length is too big "
1359 "IEs eid=%d elem_len=%d total_ie_lent=%d",
1360 elem_id, elem_len, *total_ielen);
1361 }
1362 }
1363 }
1364
1365 left -= elem_len;
1366 ptr += (elem_len + 2);
1367 }
1368 return;
1369}
1370
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001371#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001372static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1373 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001374#else
1375static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1376 struct cfg80211_beacon_data *params)
1377#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001378{
1379 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301380 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001381 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001382 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001383
1384 genie = vos_mem_malloc(MAX_GENIE_LEN);
1385
1386 if(genie == NULL) {
1387
1388 return -ENOMEM;
1389 }
1390
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301391 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1392 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001393 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301394 hddLog(LOGE,
1395 FL("Adding WPS IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301396 ret = -EINVAL;
1397 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001398 }
1399
1400#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301401 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1402 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1403 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301404 hddLog(LOGE,
1405 FL("Adding WFD IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301406 ret = -EINVAL;
1407 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001408 }
1409#endif
1410
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301411 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1412 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001413 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301414 hddLog(LOGE,
1415 FL("Adding P2P IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301416 ret = -EINVAL;
1417 goto done;
1418 }
1419
1420 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1421 {
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001422 wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen);
Jeff Johnson295189b2012-06-20 16:38:30 -07001423 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001424
1425 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1426 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1427 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1428 {
1429 hddLog(LOGE,
1430 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001431 ret = -EINVAL;
1432 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001433 }
1434
1435 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1436 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1437 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1438 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1439 ==eHAL_STATUS_FAILURE)
1440 {
1441 hddLog(LOGE,
1442 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001443 ret = -EINVAL;
1444 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001445 }
1446
1447 // Added for ProResp IE
1448 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1449 {
1450 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1451 u8 probe_rsp_ie_len[3] = {0};
1452 u8 counter = 0;
1453 /* Check Probe Resp Length if it is greater then 255 then Store
1454 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1455 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1456 Store More then 255 bytes into One Variable.
1457 */
1458 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1459 {
1460 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1461 {
1462 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1463 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1464 }
1465 else
1466 {
1467 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1468 rem_probe_resp_ie_len = 0;
1469 }
1470 }
1471
1472 rem_probe_resp_ie_len = 0;
1473
1474 if (probe_rsp_ie_len[0] > 0)
1475 {
1476 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1477 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1478 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1479 probe_rsp_ie_len[0], NULL,
1480 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1481 {
1482 hddLog(LOGE,
1483 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001484 ret = -EINVAL;
1485 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001486 }
1487 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1488 }
1489
1490 if (probe_rsp_ie_len[1] > 0)
1491 {
1492 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1493 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1494 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1495 probe_rsp_ie_len[1], NULL,
1496 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1497 {
1498 hddLog(LOGE,
1499 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001500 ret = -EINVAL;
1501 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001502 }
1503 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1504 }
1505
1506 if (probe_rsp_ie_len[2] > 0)
1507 {
1508 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1509 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1510 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1511 probe_rsp_ie_len[2], NULL,
1512 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1513 {
1514 hddLog(LOGE,
1515 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001516 ret = -EINVAL;
1517 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001518 }
1519 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1520 }
1521
1522 if (probe_rsp_ie_len[1] == 0 )
1523 {
1524 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1525 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1526 eANI_BOOLEAN_FALSE) )
1527 {
1528 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001529 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001530 }
1531 }
1532
1533 if (probe_rsp_ie_len[2] == 0 )
1534 {
1535 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1536 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1537 eANI_BOOLEAN_FALSE) )
1538 {
1539 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001540 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001541 }
1542 }
1543
1544 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1545 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1546 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1547 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1548 == eHAL_STATUS_FAILURE)
1549 {
1550 hddLog(LOGE,
1551 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001552 ret = -EINVAL;
1553 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001554 }
1555 }
1556 else
1557 {
1558 // Reset WNI_CFG_PROBE_RSP Flags
1559 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1560
1561 hddLog(VOS_TRACE_LEVEL_INFO,
1562 "%s: No Probe Response IE received in set beacon",
1563 __func__);
1564 }
1565
1566 // Added for AssocResp IE
1567 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1568 {
1569 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1570 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1571 params->assocresp_ies_len, NULL,
1572 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1573 {
1574 hddLog(LOGE,
1575 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001576 ret = -EINVAL;
1577 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001578 }
1579
1580 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1581 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1582 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1583 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1584 == eHAL_STATUS_FAILURE)
1585 {
1586 hddLog(LOGE,
1587 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001588 ret = -EINVAL;
1589 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001590 }
1591 }
1592 else
1593 {
1594 hddLog(VOS_TRACE_LEVEL_INFO,
1595 "%s: No Assoc Response IE received in set beacon",
1596 __func__);
1597
1598 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1599 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1600 eANI_BOOLEAN_FALSE) )
1601 {
1602 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001603 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001604 }
1605 }
1606
Jeff Johnsone7245742012-09-05 17:12:55 -07001607done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001608 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301609 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001610}
Jeff Johnson295189b2012-06-20 16:38:30 -07001611
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301612/*
Jeff Johnson295189b2012-06-20 16:38:30 -07001613 * FUNCTION: wlan_hdd_validate_operation_channel
1614 * called by wlan_hdd_cfg80211_start_bss() and
1615 * wlan_hdd_cfg80211_set_channel()
1616 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301617 * channel list.
1618 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001619VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001620{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301621
Jeff Johnson295189b2012-06-20 16:38:30 -07001622 v_U32_t num_ch = 0;
1623 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1624 u32 indx = 0;
1625 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301626 v_U8_t fValidChannel = FALSE, count = 0;
1627 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301628
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1630
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301631 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001632 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301633 /* Validate the channel */
1634 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001635 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301636 if ( channel == rfChannels[count].channelNum )
1637 {
1638 fValidChannel = TRUE;
1639 break;
1640 }
1641 }
1642 if (fValidChannel != TRUE)
1643 {
1644 hddLog(VOS_TRACE_LEVEL_ERROR,
1645 "%s: Invalid Channel [%d]", __func__, channel);
1646 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001647 }
1648 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301649 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001650 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301651 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1652 valid_ch, &num_ch))
1653 {
1654 hddLog(VOS_TRACE_LEVEL_ERROR,
1655 "%s: failed to get valid channel list", __func__);
1656 return VOS_STATUS_E_FAILURE;
1657 }
1658 for (indx = 0; indx < num_ch; indx++)
1659 {
1660 if (channel == valid_ch[indx])
1661 {
1662 break;
1663 }
1664 }
1665
1666 if (indx >= num_ch)
1667 {
1668 hddLog(VOS_TRACE_LEVEL_ERROR,
1669 "%s: Invalid Channel [%d]", __func__, channel);
1670 return VOS_STATUS_E_FAILURE;
1671 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 }
1673 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301674
Jeff Johnson295189b2012-06-20 16:38:30 -07001675}
1676
Viral Modi3a32cc52013-02-08 11:14:52 -08001677/**
1678 * FUNCTION: wlan_hdd_cfg80211_set_channel
1679 * This function is used to set the channel number
1680 */
1681static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1682 struct ieee80211_channel *chan,
1683 enum nl80211_channel_type channel_type
1684 )
1685{
1686 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001687 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001688 hdd_adapter_t *pAdapter = NULL;
1689 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301690 hdd_context_t *pHddCtx;
1691 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001692
1693 ENTER();
1694
1695 if( NULL == dev )
1696 {
1697 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001698 "%s: Called with dev = NULL.", __func__);
Viral Modi3a32cc52013-02-08 11:14:52 -08001699 return -ENODEV;
1700 }
1701 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1702
1703 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001704 "%s: device_mode = %d freq = %d", __func__,
Viral Modi3a32cc52013-02-08 11:14:52 -08001705 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301706
1707 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1708 status = wlan_hdd_validate_context(pHddCtx);
1709
1710 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08001711 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1713 "%s: HDD context is not valid", __func__);
1714 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001715 }
1716
1717 /*
1718 * Do freq to chan conversion
1719 * TODO: for 11a
1720 */
1721
1722 channel = ieee80211_frequency_to_channel(freq);
1723
1724 /* Check freq range */
1725 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1726 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1727 {
1728 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001729 "%s: Channel [%d] is outside valid range from %d to %d",
Viral Modi3a32cc52013-02-08 11:14:52 -08001730 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1731 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1732 return -EINVAL;
1733 }
1734
1735 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1736
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301737 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1738 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001739 {
1740 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1741 {
1742 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001743 "%s: Invalid Channel [%d]", __func__, channel);
Viral Modi3a32cc52013-02-08 11:14:52 -08001744 return -EINVAL;
1745 }
1746 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1747 "%s: set channel to [%d] for device mode =%d",
1748 __func__, channel,pAdapter->device_mode);
1749 }
1750 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001751 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001752 )
1753 {
1754 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1755 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1756 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1757
1758 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1759 {
1760 /* Link is up then return cant set channel*/
1761 hddLog( VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001762 "%s: IBSS Associated, can't set the channel", __func__);
Viral Modi3a32cc52013-02-08 11:14:52 -08001763 return -EINVAL;
1764 }
1765
1766 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1767 pHddStaCtx->conn_info.operationChannel = channel;
1768 pRoamProfile->ChannelInfo.ChannelList =
1769 &pHddStaCtx->conn_info.operationChannel;
1770 }
1771 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001772 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001773 )
1774 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301775 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1776 {
1777 if(VOS_STATUS_SUCCESS !=
1778 wlan_hdd_validate_operation_channel(pAdapter,channel))
1779 {
1780 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001781 "%s: Invalid Channel [%d]", __func__, channel);
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301782 return -EINVAL;
1783 }
1784 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1785 }
1786 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001787 {
1788 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1789
1790 /* If auto channel selection is configured as enable/ 1 then ignore
1791 channel set by supplicant
1792 */
1793 if ( cfg_param->apAutoChannelSelection )
1794 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301795 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1796 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001797 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1798 "%s: set channel to auto channel (0) for device mode =%d",
1799 __func__, pAdapter->device_mode);
1800 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301801 else
1802 {
1803 if(VOS_STATUS_SUCCESS !=
1804 wlan_hdd_validate_operation_channel(pAdapter,channel))
1805 {
1806 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001807 "%s: Invalid Channel [%d]", __func__, channel);
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301808 return -EINVAL;
1809 }
1810 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1811 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001812 }
1813 }
1814 else
1815 {
1816 hddLog(VOS_TRACE_LEVEL_FATAL,
1817 "%s: Invalid device mode failed to set valid channel", __func__);
1818 return -EINVAL;
1819 }
1820 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301821 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001822}
1823
Jeff Johnson295189b2012-06-20 16:38:30 -07001824#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1825static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1826 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001827#else
1828static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1829 struct cfg80211_beacon_data *params,
1830 const u8 *ssid, size_t ssid_len,
1831 enum nl80211_hidden_ssid hidden_ssid)
1832#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001833{
1834 tsap_Config_t *pConfig;
1835 beacon_data_t *pBeacon = NULL;
1836 struct ieee80211_mgmt *pMgmt_frame;
1837 v_U8_t *pIe=NULL;
1838 v_U16_t capab_info;
1839 eCsrAuthType RSNAuthType;
1840 eCsrEncryptionType RSNEncryptType;
1841 eCsrEncryptionType mcRSNEncryptType;
1842 int status = VOS_STATUS_SUCCESS;
1843 tpWLAN_SAPEventCB pSapEventCallback;
1844 hdd_hostapd_state_t *pHostapdState;
1845 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1846 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301847 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001848 struct qc_mac_acl_entry *acl_entry = NULL;
1849 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001850 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001851
1852 ENTER();
1853
1854 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1855
1856 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1857
1858 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1859
1860 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1861
1862 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1863
1864 //channel is already set in the set_channel Call back
1865 //pConfig->channel = pCommitConfig->channel;
1866
1867 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301868 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07001869 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1870
1871 pConfig->dtim_period = pBeacon->dtim_period;
1872
Arif Hussain6d2a3322013-11-17 19:50:10 -08001873 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***",
Jeff Johnson295189b2012-06-20 16:38:30 -07001874 pConfig->dtim_period);
1875
1876
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001877 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001878 {
1879 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001880 WLAN_EID_COUNTRY);
Kiet Lam083504c2013-11-25 14:17:45 +05301881 if(memcmp(pHddCtx->cfg_ini->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0)
1882 {
1883 tANI_BOOLEAN restartNeeded;
1884 pConfig->ieee80211d = 1;
1885 vos_mem_copy(pConfig->countryCode, pHddCtx->cfg_ini->apCntryCode, 3);
1886 sme_setRegInfo(hHal, pConfig->countryCode);
1887 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1888 }
1889 else if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001890 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001891 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001892 pConfig->ieee80211d = 1;
1893 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1894 sme_setRegInfo(hHal, pConfig->countryCode);
1895 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001896 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001897 else
1898 {
1899 pConfig->ieee80211d = 0;
1900 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301901 /*
1902 * If auto channel is configured i.e. channel is 0,
1903 * so skip channel validation.
1904 */
1905 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1906 {
1907 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1908 {
1909 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001910 "%s: Invalid Channel [%d]", __func__, pConfig->channel);
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301911 return -EINVAL;
1912 }
1913 }
1914 else
1915 {
1916 if(1 != pHddCtx->is_dynamic_channel_range_set)
1917 {
1918 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1919 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1920 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1921 }
1922 pHddCtx->is_dynamic_channel_range_set = 0;
1923 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001924 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001925 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001926 {
1927 pConfig->ieee80211d = 0;
1928 }
1929 pConfig->authType = eSAP_AUTO_SWITCH;
1930
1931 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301932
1933 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07001934 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1935
1936 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1937
1938 /*Set wps station to configured*/
1939 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1940
1941 if(pIe)
1942 {
1943 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1944 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08001945 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***");
Jeff Johnson295189b2012-06-20 16:38:30 -07001946 return -EINVAL;
1947 }
1948 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1949 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001950 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001951 /* Check 15 bit of WPS IE as it contain information for wps state
1952 * WPS state
1953 */
1954 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1955 {
1956 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1957 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1958 {
1959 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1960 }
1961 }
1962 }
1963 else
1964 {
1965 pConfig->wps_state = SAP_WPS_DISABLED;
1966 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301967 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07001968
1969 pConfig->RSNWPAReqIELength = 0;
1970 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301971 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001972 WLAN_EID_RSN);
1973 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301974 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1976 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1977 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301978 /* The actual processing may eventually be more extensive than
1979 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07001980 * by the app.
1981 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301982 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07001983 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1984 &RSNEncryptType,
1985 &mcRSNEncryptType,
1986 &RSNAuthType,
1987 pConfig->pRSNWPAReqIE[1]+2,
1988 pConfig->pRSNWPAReqIE );
1989
1990 if( VOS_STATUS_SUCCESS == status )
1991 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301992 /* Now copy over all the security attributes you have
1993 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07001994 * */
1995 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1996 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1997 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1998 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301999 hddLog( LOG1, FL("CSR AuthType = %d, "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002000 "EncryptionType = %d mcEncryptionType = %d"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002001 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
2002 }
2003 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302004
Jeff Johnson295189b2012-06-20 16:38:30 -07002005 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2006 pBeacon->tail, pBeacon->tail_len);
2007
2008 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
2009 {
2010 if (pConfig->pRSNWPAReqIE)
2011 {
2012 /*Mixed mode WPA/WPA2*/
2013 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
2014 pConfig->RSNWPAReqIELength += pIe[1] + 2;
2015 }
2016 else
2017 {
2018 pConfig->RSNWPAReqIELength = pIe[1] + 2;
2019 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
2020 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302021 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07002022 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
2023 &RSNEncryptType,
2024 &mcRSNEncryptType,
2025 &RSNAuthType,
2026 pConfig->pRSNWPAReqIE[1]+2,
2027 pConfig->pRSNWPAReqIE );
2028
2029 if( VOS_STATUS_SUCCESS == status )
2030 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302031 /* Now copy over all the security attributes you have
2032 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07002033 * */
2034 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
2035 pConfig->mcRSNEncryptType = mcRSNEncryptType;
2036 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
2037 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302038 hddLog( LOG1, FL("CSR AuthType = %d, "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002039 "EncryptionType = %d mcEncryptionType = %d"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
2041 }
2042 }
2043 }
2044
Jeff Johnson4416a782013-03-25 14:17:50 -07002045 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
2046 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
2047 return -EINVAL;
2048 }
2049
Jeff Johnson295189b2012-06-20 16:38:30 -07002050 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
2051
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002052#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002053 if (params->ssid != NULL)
2054 {
2055 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
2056 pConfig->SSIDinfo.ssid.length = params->ssid_len;
2057 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2058 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
2059 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002060#else
2061 if (ssid != NULL)
2062 {
2063 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
2064 pConfig->SSIDinfo.ssid.length = ssid_len;
2065 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2066 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
2067 }
2068#endif
2069
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302070 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07002071 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302072
Jeff Johnson295189b2012-06-20 16:38:30 -07002073 /* default value */
2074 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
2075 pConfig->num_accept_mac = 0;
2076 pConfig->num_deny_mac = 0;
2077
2078 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2079 pBeacon->tail, pBeacon->tail_len);
2080
2081 /* pIe for black list is following form:
2082 type : 1 byte
2083 length : 1 byte
2084 OUI : 4 bytes
2085 acl type : 1 byte
2086 no of mac addr in black list: 1 byte
2087 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302088 */
2089 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002090 {
2091 pConfig->SapMacaddr_acl = pIe[6];
2092 pConfig->num_deny_mac = pIe[7];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002093 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002094 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302095 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
2096 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002097 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2098 for (i = 0; i < pConfig->num_deny_mac; i++)
2099 {
2100 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2101 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302102 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002103 }
2104 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2105 pBeacon->tail, pBeacon->tail_len);
2106
2107 /* pIe for white list is following form:
2108 type : 1 byte
2109 length : 1 byte
2110 OUI : 4 bytes
2111 acl type : 1 byte
2112 no of mac addr in white list: 1 byte
2113 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302114 */
2115 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002116 {
2117 pConfig->SapMacaddr_acl = pIe[6];
2118 pConfig->num_accept_mac = pIe[7];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002119 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302121 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
2122 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002123 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2124 for (i = 0; i < pConfig->num_accept_mac; i++)
2125 {
2126 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2127 acl_entry++;
2128 }
2129 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302130
Jeff Johnson295189b2012-06-20 16:38:30 -07002131 wlan_hdd_set_sapHwmode(pHostapdAdapter);
2132
Jeff Johnsone7245742012-09-05 17:12:55 -07002133#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002134 /* Overwrite the hostapd setting for HW mode only for 11ac.
Kiet Lam0f320422013-11-21 19:29:17 +05302135 * This is valid only if mode is set to 11n in hostapd, either AUTO or
2136 * 11ac in .ini and 11ac is supported by both host and firmware.
2137 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode)
2138 */
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002139 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
2140 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302141 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002142 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
Kiet Lam0f320422013-11-21 19:29:17 +05302143 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) &&
2144 (sme_IsFeatureSupportedByDriver(DOT11AC)) && (sme_IsFeatureSupportedByFW(DOT11AC)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07002145 {
2146 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Ravi Joshi83bfaa12013-05-28 22:12:08 -07002147
2148 /* Disable VHT support in 2.4 GHz band */
2149 if (pConfig->channel <= 14 &&
2150 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->enableVhtFor24GHzBand == FALSE)
2151 {
2152 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
2153 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002154 }
2155#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302156
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07002157 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
2158 {
2159 sme_SelectCBMode(hHal,
2160 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
2161 pConfig->channel);
2162 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002163 // ht_capab is not what the name conveys,this is used for protection bitmap
2164 pConfig->ht_capab =
2165 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
2166
2167 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
2168 {
2169 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
2170 return -EINVAL;
2171 }
2172
2173 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302174 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07002175 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
2176 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302177 pConfig->obssProtEnabled =
2178 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07002179
Arif Hussain6d2a3322013-11-17 19:50:10 -08002180 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR),
Jeff Johnson295189b2012-06-20 16:38:30 -07002181 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Arif Hussain6d2a3322013-11-17 19:50:10 -08002182 hddLog(LOGW,FL("ssid =%s, beaconint=%d, channel=%d"),
2183 pConfig->SSIDinfo.ssid.ssId, (int)pConfig->beacon_int,
2184 (int)pConfig->channel);
2185 hddLog(LOGW,FL("hw_mode=%x, privacy=%d, authType=%d"),
2186 pConfig->SapHw_mode, pConfig->privacy,
2187 pConfig->authType);
2188 hddLog(LOGW,FL("RSN/WPALen=%d, Uapsd = %d"),
2189 (int)pConfig->RSNWPAReqIELength, pConfig->UapsdEnable);
2190 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d"),
2191 pConfig->protEnabled, pConfig->obssProtEnabled);
Jeff Johnson295189b2012-06-20 16:38:30 -07002192
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302193 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002194 {
2195 //Bss already started. just return.
2196 //TODO Probably it should update some beacon params.
2197 hddLog( LOGE, "Bss Already started...Ignore the request");
2198 EXIT();
2199 return 0;
2200 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302201
Jeff Johnson295189b2012-06-20 16:38:30 -07002202 pConfig->persona = pHostapdAdapter->device_mode;
2203
2204 pSapEventCallback = hdd_hostapd_SAPEventCB;
2205 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2206 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2207 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08002208 hddLog(LOGE,FL("SAP Start Bss fail"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002209 return -EINVAL;
2210 }
2211
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302212 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002213 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2214
2215 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302216
Jeff Johnson295189b2012-06-20 16:38:30 -07002217 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302218 {
2219 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002220 ("ERROR: HDD vos wait for single_event failed!!"));
Tushnim Bhattacharyyaad37df12013-10-02 12:01:33 -07002221 smeGetCommandQStatus(hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 VOS_ASSERT(0);
2223 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302224
Jeff Johnson295189b2012-06-20 16:38:30 -07002225 //Succesfully started Bss update the state bit.
2226 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2227
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002228#ifdef WLAN_FEATURE_P2P_DEBUG
2229 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2230 {
2231 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2232 {
2233 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2234 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002235 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002236 }
2237 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2238 {
2239 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2240 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002241 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002242 }
2243 }
2244#endif
2245
Jeff Johnson295189b2012-06-20 16:38:30 -07002246 pHostapdState->bCommit = TRUE;
2247 EXIT();
2248
2249 return 0;
2250}
2251
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002252#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302253static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2254 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07002255 struct beacon_parameters *params)
2256{
2257 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302258 hdd_context_t *pHddCtx;
2259 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002260
2261 ENTER();
2262
Arif Hussain6d2a3322013-11-17 19:50:10 -08002263 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d",pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002264
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302265 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2266 status = wlan_hdd_validate_context(pHddCtx);
2267
2268 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002269 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2271 "%s: HDD context is not valid", __func__);
2272 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002273 }
2274
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302275 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002276 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002277 )
2278 {
2279 beacon_data_t *old,*new;
2280
2281 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302282
Jeff Johnson295189b2012-06-20 16:38:30 -07002283 if (old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302284 {
2285 hddLog(VOS_TRACE_LEVEL_WARN,
2286 FL("already beacon info added to session(%d)"),
2287 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002288 return -EALREADY;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302289 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002290
2291 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2292
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302293 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07002294 {
2295 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002296 "%s:Error!!! Allocating the new beacon",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002297 return -EINVAL;
2298 }
2299
2300 pAdapter->sessionCtx.ap.beacon = new;
2301
2302 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2303 }
2304
2305 EXIT();
2306 return status;
2307}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302308
2309static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07002310 struct net_device *dev,
2311 struct beacon_parameters *params)
2312{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302313 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302314 hdd_context_t *pHddCtx;
2315 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002316
2317 ENTER();
2318
Arif Hussain6d2a3322013-11-17 19:50:10 -08002319 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002320 __func__,pAdapter->device_mode);
2321
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302322 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2323 status = wlan_hdd_validate_context(pHddCtx);
2324
2325 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002326 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2328 "%s: HDD context is not valid", __func__);
2329 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002330 }
2331
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302332 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002333 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302334 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002335 {
2336 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302337
Jeff Johnson295189b2012-06-20 16:38:30 -07002338 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302339
Jeff Johnson295189b2012-06-20 16:38:30 -07002340 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302341 {
2342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2343 FL("session(%d) old and new heads points to NULL"),
2344 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002345 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302346 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002347
2348 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2349
2350 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302351 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002352 "%s: Error!!! Allocating the new beacon",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002353 return -EINVAL;
2354 }
2355
2356 pAdapter->sessionCtx.ap.beacon = new;
2357
2358 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2359 }
2360
2361 EXIT();
2362 return status;
2363}
2364
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002365#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2366
2367#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002368static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2369 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002370#else
2371static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2372 struct net_device *dev)
2373#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002374{
2375 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002376 hdd_context_t *pHddCtx = NULL;
2377 hdd_scaninfo_t *pScanInfo = NULL;
2378 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302379 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002380
2381 ENTER();
2382
2383 if (NULL == pAdapter)
2384 {
2385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002386 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002387 return -ENODEV;
2388 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002389
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302390 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2391 status = wlan_hdd_validate_context(pHddCtx);
2392
2393 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002394 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2396 "%s: HDD context is not valid", __func__);
2397 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07002398 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002399
2400 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2401 if (NULL == staAdapter)
2402 {
2403 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2404 if (NULL == staAdapter)
2405 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002406 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2407 "%s: HDD adapter context for STA/P2P-CLI is Null",
2408 __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002409 }
2410 }
2411
2412 pScanInfo = &pHddCtx->scan_info;
2413
Arif Hussain6d2a3322013-11-17 19:50:10 -08002414 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002415 __func__,pAdapter->device_mode);
2416
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002417 if ((pScanInfo != NULL) && pScanInfo->mScanPending && staAdapter)
Jeff Johnsone7245742012-09-05 17:12:55 -07002418 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302419 long ret;
2420
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002421 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05302422 hdd_abort_mac_scan(staAdapter->pHddCtx, pAdapter->sessionId,
2423 eCSR_SCAN_ABORT_DEFAULT);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302424 ret = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002425 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002426 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302427 if (ret <= 0)
Jeff Johnsone7245742012-09-05 17:12:55 -07002428 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302430 FL("Timeout occurred while waiting for abortscan %ld"),
2431 ret);
Yue Ma4f55ef32014-01-23 16:45:33 -08002432
2433 if (pHddCtx->isLogpInProgress)
2434 {
2435 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2436 "%s: LOGP in Progress. Ignore!!!", __func__);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302437
2438 VOS_ASSERT(pScanInfo->mScanPending);
Yue Ma4f55ef32014-01-23 16:45:33 -08002439 return -EAGAIN;
2440 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002441 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07002442 }
2443 }
2444
Arun Kumar Khandavallia3bd8002014-01-17 16:21:19 +05302445 hdd_hostapd_stop(dev);
2446
Jeff Johnson295189b2012-06-20 16:38:30 -07002447 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002448 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002449 )
2450 {
2451 beacon_data_t *old;
2452
2453 old = pAdapter->sessionCtx.ap.beacon;
2454
2455 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302456 {
2457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2458 FL("session(%d) beacon data points to NULL"),
2459 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002460 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302461 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002462
Jeff Johnson295189b2012-06-20 16:38:30 -07002463 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002464
2465 mutex_lock(&pHddCtx->sap_lock);
2466 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2467 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002468 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002469 {
2470 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2471
2472 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2473
2474 if (!VOS_IS_STATUS_SUCCESS(status))
2475 {
2476 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002477 ("ERROR: HDD vos wait for single_event failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002478 VOS_ASSERT(0);
2479 }
2480 }
2481 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2482 }
2483 mutex_unlock(&pHddCtx->sap_lock);
2484
2485 if(status != VOS_STATUS_SUCCESS)
2486 {
2487 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002488 "%s:Error!!! Stopping the BSS",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002489 return -EINVAL;
2490 }
2491
Jeff Johnson4416a782013-03-25 14:17:50 -07002492 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002493 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2494 ==eHAL_STATUS_FAILURE)
2495 {
2496 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002497 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07002498 }
2499
Jeff Johnson4416a782013-03-25 14:17:50 -07002500 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002501 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2502 eANI_BOOLEAN_FALSE) )
2503 {
2504 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002505 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07002506 }
2507
2508 // Reset WNI_CFG_PROBE_RSP Flags
2509 wlan_hdd_reset_prob_rspies(pAdapter);
2510
2511 pAdapter->sessionCtx.ap.beacon = NULL;
2512 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002513#ifdef WLAN_FEATURE_P2P_DEBUG
2514 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2515 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2516 {
2517 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2518 "GO got removed");
2519 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2520 }
2521#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002522 }
2523 EXIT();
2524 return status;
2525}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002526
2527#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2528
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302529static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2530 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002531 struct cfg80211_ap_settings *params)
2532{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302533 hdd_adapter_t *pAdapter;
2534 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302535 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002536
2537 ENTER();
2538
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302539 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002540 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302542 "%s: Device is Null", __func__);
2543 return -ENODEV;
2544 }
2545
2546 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2547 if (NULL == pAdapter)
2548 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302550 "%s: HDD adapter is Null", __func__);
2551 return -ENODEV;
2552 }
2553
2554 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2555 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302557 "%s: HDD adapter magic is invalid", __func__);
2558 return -ENODEV;
2559 }
2560
2561 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302562 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302563
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302564 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302565 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2567 "%s: HDD context is not valid", __func__);
2568 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302569 }
2570
2571 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2572 __func__, pAdapter->device_mode);
2573
2574 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002575 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002576 )
2577 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302578 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002579
2580 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302581
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002582 if (old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302583 {
2584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2585 FL("already beacon info added to session(%d)"),
2586 pAdapter->sessionId);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002587 return -EALREADY;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302588 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002589
2590 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2591
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302592 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002593 {
2594 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302595 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002596 return -EINVAL;
2597 }
2598 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002599#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07002600 wlan_hdd_cfg80211_set_channel(wiphy, dev,
2601#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2602 params->channel, params->channel_type);
2603#else
2604 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
2605#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08002606#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002607 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2608 params->ssid_len, params->hidden_ssid);
2609 }
2610
2611 EXIT();
2612 return status;
2613}
2614
2615
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302616static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002617 struct net_device *dev,
2618 struct cfg80211_beacon_data *params)
2619{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302620 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302621 hdd_context_t *pHddCtx;
2622 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002623
2624 ENTER();
2625
Arif Hussain6d2a3322013-11-17 19:50:10 -08002626 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002627 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302628
2629 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2630 status = wlan_hdd_validate_context(pHddCtx);
2631
2632 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002633 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2635 "%s: HDD context is not valid", __func__);
2636 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002637 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002638
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302639 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002640 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302641 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002642 {
2643 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302644
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002645 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302646
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002647 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302648 {
2649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2650 FL("session(%d) beacon data points to NULL"),
2651 pAdapter->sessionId);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002652 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302653 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002654
2655 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2656
2657 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302658 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002659 "%s: Error!!! Allocating the new beacon",__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002660 return -EINVAL;
2661 }
2662
2663 pAdapter->sessionCtx.ap.beacon = new;
2664
2665 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2666 }
2667
2668 EXIT();
2669 return status;
2670}
2671
2672#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2673
Jeff Johnson295189b2012-06-20 16:38:30 -07002674
2675static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2676 struct net_device *dev,
2677 struct bss_parameters *params)
2678{
2679 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2680
2681 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302682
Arif Hussain6d2a3322013-11-17 19:50:10 -08002683 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002684 __func__,pAdapter->device_mode);
2685
2686 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002687 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302688 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002689 {
2690 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2691 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302692 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07002693 {
2694 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302695 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002696 }
2697
2698 EXIT();
2699 return 0;
2700}
2701
Kiet Lam10841362013-11-01 11:36:50 +05302702/* FUNCTION: wlan_hdd_change_country_code_cd
2703* to wait for contry code completion
2704*/
2705void* wlan_hdd_change_country_code_cb(void *pAdapter)
2706{
2707 hdd_adapter_t *call_back_pAdapter = pAdapter;
2708 complete(&call_back_pAdapter->change_country_code);
2709 return NULL;
2710}
2711
Jeff Johnson295189b2012-06-20 16:38:30 -07002712/*
2713 * FUNCTION: wlan_hdd_cfg80211_change_iface
2714 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2715 */
2716int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2717 struct net_device *ndev,
2718 enum nl80211_iftype type,
2719 u32 *flags,
2720 struct vif_params *params
2721 )
2722{
2723 struct wireless_dev *wdev;
2724 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Rajesh Chauhana0516c62014-01-30 16:11:18 -08002725 hdd_context_t *pHddCtx;
Mohit Khanna0f232092012-09-11 14:46:08 -07002726 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002727 tCsrRoamProfile *pRoamProfile = NULL;
2728 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302729 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002730 eMib_dot11DesiredBssType connectedBssType;
2731 VOS_STATUS status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302732 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07002733
2734 ENTER();
2735
Rajesh Chauhana0516c62014-01-30 16:11:18 -08002736 if (!pAdapter)
2737 {
2738 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2739 "%s: Adapter context is null", __func__);
2740 return VOS_STATUS_E_FAILURE;
2741 }
2742
2743 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2744 if (!pHddCtx)
2745 {
2746 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2747 "%s: HDD context is null", __func__);
2748 return VOS_STATUS_E_FAILURE;
2749 }
2750
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302751 status = wlan_hdd_validate_context(pHddCtx);
2752
2753 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07002754 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2756 "%s: HDD context is not valid", __func__);
2757 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002758 }
2759
2760 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2761 __func__, pAdapter->device_mode);
2762
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302763 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07002764 wdev = ndev->ieee80211_ptr;
2765
2766#ifdef WLAN_BTAMP_FEATURE
2767 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2768 (NL80211_IFTYPE_ADHOC == type)||
2769 (NL80211_IFTYPE_AP == type)||
2770 (NL80211_IFTYPE_P2P_GO == type))
2771 {
2772 pHddCtx->isAmpAllowed = VOS_FALSE;
2773 // stop AMP traffic
2774 status = WLANBAP_StopAmp();
2775 if(VOS_STATUS_SUCCESS != status )
2776 {
2777 pHddCtx->isAmpAllowed = VOS_TRUE;
2778 hddLog(VOS_TRACE_LEVEL_FATAL,
2779 "%s: Failed to stop AMP", __func__);
2780 return -EINVAL;
2781 }
2782 }
2783#endif //WLAN_BTAMP_FEATURE
2784 /* Reset the current device mode bit mask*/
2785 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2786
2787 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002788 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002789 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002790 )
2791 {
2792 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Rajesh Chauhana0516c62014-01-30 16:11:18 -08002793 if (!pWextState)
2794 {
2795 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2796 "%s: pWextState is null", __func__);
2797 return VOS_STATUS_E_FAILURE;
2798 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002799 pRoamProfile = &pWextState->roamProfile;
2800 LastBSSType = pRoamProfile->BSSType;
2801
2802 switch (type)
2803 {
2804 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002805 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002806 hddLog(VOS_TRACE_LEVEL_INFO,
2807 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2808 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002809#ifdef WLAN_FEATURE_11AC
2810 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2811 {
2812 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2813 }
2814#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302815 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07002816 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002817 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002818 //Check for sub-string p2p to confirm its a p2p interface
2819 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302820 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002821 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2822 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2823 }
2824 else
2825 {
2826 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002827 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002828 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302829#ifdef FEATURE_WLAN_TDLS
2830 /* The open adapter for the p2p shall skip initializations in
2831 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
2832 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
2833 * tdls_init when the change_iface sets the device mode to
2834 * WLAN_HDD_P2P_CLIENT.
2835 */
2836
2837 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2838 {
2839 if (0 != wlan_hdd_tdls_init (pAdapter))
2840 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302841 hddLog(VOS_TRACE_LEVEL_ERROR,
2842 "%s: tdls initialization failed", __func__);
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302843 return -EINVAL;
2844 }
2845 }
2846#endif
2847
Jeff Johnson295189b2012-06-20 16:38:30 -07002848 break;
2849 case NL80211_IFTYPE_ADHOC:
2850 hddLog(VOS_TRACE_LEVEL_INFO,
2851 "%s: setting interface Type to ADHOC", __func__);
2852 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2853 pRoamProfile->phyMode =
2854 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07002855 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002856 wdev->iftype = type;
2857 break;
2858
2859 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002860 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002861 {
2862 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2863 "%s: setting interface Type to %s", __func__,
2864 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2865
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002866 //Cancel any remain on channel for GO mode
2867 if (NL80211_IFTYPE_P2P_GO == type)
2868 {
2869 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2870 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002871 if (NL80211_IFTYPE_AP == type)
2872 {
2873 /* As Loading WLAN Driver one interface being created for p2p device
2874 * address. This will take one HW STA and the max number of clients
2875 * that can connect to softAP will be reduced by one. so while changing
2876 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2877 * interface as it is not required in SoftAP mode.
2878 */
2879
2880 // Get P2P Adapter
2881 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2882
2883 if (pP2pAdapter)
2884 {
2885 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2886 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2887 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2888 }
2889 }
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302890#ifdef FEATURE_WLAN_TDLS
Mohit Khanna0f232092012-09-11 14:46:08 -07002891
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302892 /* A Mutex Lock is introduced while changing the mode to
2893 * protect the concurrent access for the Adapters by TDLS
2894 * module.
2895 */
2896 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
2897 {
2898 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2899 "%s: unable to lock list", __func__);
2900 return -EINVAL;
2901 }
2902#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002903 //De-init the adapter.
2904 hdd_stop_adapter( pHddCtx, pAdapter );
2905 hdd_deinit_adapter( pHddCtx, pAdapter );
2906 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002907 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2908 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302909#ifdef FEATURE_WLAN_TDLS
2910 mutex_unlock(&pHddCtx->tdls_lock);
2911#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002912
2913 //Disable BMPS and IMPS if enabled
2914 //before starting Go
2915 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2916 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302917 if(VOS_STATUS_E_FAILURE ==
Jeff Johnson32d95a32012-09-10 13:15:23 -07002918 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2919 {
2920 //Fail to Exit BMPS
2921 VOS_ASSERT(0);
2922 }
2923 }
2924
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002925 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2926 (pConfig->apRandomBssidEnabled))
2927 {
2928 /* To meet Android requirements create a randomized
2929 MAC address of the form 02:1A:11:Fx:xx:xx */
2930 get_random_bytes(&ndev->dev_addr[3], 3);
2931 ndev->dev_addr[0] = 0x02;
2932 ndev->dev_addr[1] = 0x1A;
2933 ndev->dev_addr[2] = 0x11;
2934 ndev->dev_addr[3] |= 0xF0;
2935 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2936 VOS_MAC_ADDR_SIZE);
Arif Hussain24bafea2013-11-15 15:10:03 -08002937 pr_info("wlan: Generated HotSpot BSSID " MAC_ADDRESS_STR"\n",
2938 MAC_ADDR_ARRAY(ndev->dev_addr));
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002939 }
2940
Jeff Johnson295189b2012-06-20 16:38:30 -07002941 hdd_set_ap_ops( pAdapter->dev );
2942
Kiet Lam10841362013-11-01 11:36:50 +05302943 /* This is for only SAP mode where users can
2944 * control country through ini.
2945 * P2P GO follows station country code
2946 * acquired during the STA scanning. */
2947 if((NL80211_IFTYPE_AP == type) &&
2948 (memcmp(pConfig->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0))
2949 {
2950 int status = 0;
2951 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
2952 "%s: setting country code from INI ", __func__);
2953 init_completion(&pAdapter->change_country_code);
2954 status = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2955 (void *)(tSmeChangeCountryCallback)
2956 wlan_hdd_change_country_code_cb,
2957 pConfig->apCntryCode, pAdapter,
2958 pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05302959 eSIR_FALSE,
2960 eSIR_TRUE);
Kiet Lam10841362013-11-01 11:36:50 +05302961 if (eHAL_STATUS_SUCCESS == status)
2962 {
2963 /* Wait for completion */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302964 ret = wait_for_completion_interruptible_timeout(
Kiet Lam10841362013-11-01 11:36:50 +05302965 &pAdapter->change_country_code,
2966 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302967 if (ret <= 0)
Kiet Lam10841362013-11-01 11:36:50 +05302968 {
2969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302970 FL("SME Timed out while setting country code %ld"),
2971 ret);
Yue Ma4f55ef32014-01-23 16:45:33 -08002972
2973 if (pHddCtx->isLogpInProgress)
2974 {
2975 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2976 "%s: LOGP in Progress. Ignore!!!", __func__);
2977 return -EAGAIN;
2978 }
Kiet Lam10841362013-11-01 11:36:50 +05302979 }
2980 }
2981 else
2982 {
2983 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002984 "%s: SME Change Country code failed",__func__);
Kiet Lam10841362013-11-01 11:36:50 +05302985 return -EINVAL;
2986 }
2987 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002988 status = hdd_init_ap_mode(pAdapter);
2989 if(status != VOS_STATUS_SUCCESS)
2990 {
2991 hddLog(VOS_TRACE_LEVEL_FATAL,
2992 "%s: Error initializing the ap mode", __func__);
2993 return -EINVAL;
2994 }
2995 hdd_set_conparam(1);
2996
Jeff Johnson295189b2012-06-20 16:38:30 -07002997 /*interface type changed update in wiphy structure*/
2998 if(wdev)
2999 {
3000 wdev->iftype = type;
3001 pHddCtx->change_iface = type;
3002 }
3003 else
3004 {
3005 hddLog(VOS_TRACE_LEVEL_ERROR,
3006 "%s: ERROR !!!! Wireless dev is NULL", __func__);
3007 return -EINVAL;
3008 }
3009 goto done;
3010 }
3011
3012 default:
3013 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
3014 __func__);
3015 return -EOPNOTSUPP;
3016 }
3017 }
3018 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003019 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003020 )
3021 {
3022 switch(type)
3023 {
3024 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003025 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07003026 case NL80211_IFTYPE_ADHOC:
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303027#ifdef FEATURE_WLAN_TDLS
3028
3029 /* A Mutex Lock is introduced while changing the mode to
3030 * protect the concurrent access for the Adapters by TDLS
3031 * module.
3032 */
3033 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
3034 {
3035 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3036 "%s: unable to lock list", __func__);
3037 return -EINVAL;
3038 }
3039#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07003040 hdd_stop_adapter( pHddCtx, pAdapter );
3041 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07003042 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08003043 //Check for sub-string p2p to confirm its a p2p interface
3044 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08003045 {
3046 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
3047 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
3048 }
3049 else
3050 {
3051 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07003052 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08003053 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003054 hdd_set_conparam(0);
3055 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07003056 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
3057 hdd_set_station_ops( pAdapter->dev );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303058#ifdef FEATURE_WLAN_TDLS
3059 mutex_unlock(&pHddCtx->tdls_lock);
3060#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05303061 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07003062 if( VOS_STATUS_SUCCESS != status )
3063 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07003064 /* In case of JB, for P2P-GO, only change interface will be called,
3065 * This is the right place to enable back bmps_imps()
3066 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303067 if (pHddCtx->hdd_wlan_suspended)
3068 {
3069 hdd_set_pwrparams(pHddCtx);
3070 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003071 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003072 goto done;
3073 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003074 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003075 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07003076 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
3077 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003078 goto done;
3079 default:
3080 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
3081 __func__);
3082 return -EOPNOTSUPP;
3083
3084 }
3085
3086 }
3087 else
3088 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303089 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: unsupported device mode(%d)",
3090 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003091 return -EOPNOTSUPP;
3092 }
3093
3094
3095 if(pRoamProfile)
3096 {
3097 if ( LastBSSType != pRoamProfile->BSSType )
3098 {
3099 /*interface type changed update in wiphy structure*/
3100 wdev->iftype = type;
3101
3102 /*the BSS mode changed, We need to issue disconnect
3103 if connected or in IBSS disconnect state*/
3104 if ( hdd_connGetConnectedBssType(
3105 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
3106 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
3107 {
3108 /*need to issue a disconnect to CSR.*/
3109 INIT_COMPLETION(pAdapter->disconnect_comp_var);
3110 if( eHAL_STATUS_SUCCESS ==
3111 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
3112 pAdapter->sessionId,
3113 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
3114 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303115 ret = wait_for_completion_interruptible_timeout(
3116 &pAdapter->disconnect_comp_var,
3117 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3118 if (ret <= 0)
3119 {
3120 hddLog(VOS_TRACE_LEVEL_ERROR,
3121 FL("wait on disconnect_comp_var failed %ld"), ret);
3122 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003123 }
3124 }
3125 }
3126 }
3127
3128done:
3129 /*set bitmask based on updated value*/
3130 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07003131
3132 /* Only STA mode support TM now
3133 * all other mode, TM feature should be disabled */
3134 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
3135 (~VOS_STA & pHddCtx->concurrency_mode) )
3136 {
3137 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
3138 }
3139
Jeff Johnson295189b2012-06-20 16:38:30 -07003140#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303141 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07003142 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
3143 {
3144 //we are ok to do AMP
3145 pHddCtx->isAmpAllowed = VOS_TRUE;
3146 }
3147#endif //WLAN_BTAMP_FEATURE
3148 EXIT();
3149 return 0;
3150}
3151
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003152#ifdef FEATURE_WLAN_TDLS
3153static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
3154 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
3155{
3156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3157 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3158 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003159 hddTdlsPeer_t *pTdlsPeer;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303160 long ret;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003161
3162 ENTER();
3163
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303164 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003165 {
3166 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3167 "Invalid arguments");
3168 return -EINVAL;
3169 }
Hoonki Lee27511902013-03-14 18:19:06 -07003170
3171 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
3172 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
3173 {
3174 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3175 "%s: TDLS mode is disabled OR not enabled in FW."
3176 MAC_ADDRESS_STR " Request declined.",
3177 __func__, MAC_ADDR_ARRAY(mac));
3178 return -ENOTSUPP;
3179 }
3180
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003181 if (pHddCtx->isLogpInProgress)
3182 {
3183 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3184 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07003185 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003186 return -EBUSY;
3187 }
3188
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303189 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003190
3191 if ( NULL == pTdlsPeer ) {
3192 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3193 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
3194 __func__, MAC_ADDR_ARRAY(mac), update);
3195 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003196 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003197
3198 /* in add station, we accept existing valid staId if there is */
3199 if ((0 == update) &&
3200 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
3201 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003202 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003203 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003204 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003205 " link_status %d. staId %d. add station ignored.",
3206 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
3207 return 0;
3208 }
3209 /* in change station, we accept only when staId is valid */
3210 if ((1 == update) &&
3211 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
3212 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
3213 {
3214 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3215 "%s: " MAC_ADDRESS_STR
3216 " link status %d. staId %d. change station %s.",
3217 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
3218 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
3219 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003220 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003221
3222 /* when others are on-going, we want to change link_status to idle */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303223 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003224 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003225 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3226 "%s: " MAC_ADDRESS_STR
3227 " TDLS setup is ongoing. Request declined.",
3228 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07003229 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003230 }
3231
3232 /* first to check if we reached to maximum supported TDLS peer.
3233 TODO: for now, return -EPERM looks working fine,
3234 but need to check if any other errno fit into this category.*/
3235 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
3236 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3238 "%s: " MAC_ADDRESS_STR
3239 " TDLS Max peer already connected. Request declined.",
3240 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07003241 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003242 }
3243 else
3244 {
3245 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303246 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003247 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003248 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003249 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3250 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
3251 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003252 return -EPERM;
3253 }
3254 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003255 if (0 == update)
3256 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003257
Jeff Johnsond75fe012013-04-06 10:53:06 -07003258 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303259 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003260 {
3261 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3262 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003263 if(StaParams->htcap_present)
3264 {
3265 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3266 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
3267 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3268 "ht_capa->extended_capabilities: %0x",
3269 StaParams->HTCap.extendedHtCapInfo);
3270 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003271 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3272 "params->capability: %0x",StaParams->capability);
3273 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003274 "params->ext_capab_len: %0x",StaParams->extn_capability[0]);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003275 if(StaParams->vhtcap_present)
3276 {
3277 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3278 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
3279 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
3280 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
3281 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003282 {
3283 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003285 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
3286 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3287 "[%d]: %x ", i, StaParams->supported_rates[i]);
3288 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07003289 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303290 else if ((1 == update) && (NULL == StaParams))
3291 {
3292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3293 "%s : update is true, but staParams is NULL. Error!", __func__);
3294 return -EPERM;
3295 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003296
3297 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
3298
3299 if (!update)
3300 {
3301 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3302 pAdapter->sessionId, mac);
3303 }
3304 else
3305 {
3306 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3307 pAdapter->sessionId, mac, StaParams);
3308 }
3309
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303310 ret = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003311 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
3312
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303313 if (ret <= 0)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003314 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003315 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303316 "%s: timeout waiting for tdls add station indication %ld",
3317 __func__, ret);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003318 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003319 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303320
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003321 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
3322 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003323 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003324 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003325 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003326 }
3327
3328 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07003329
3330error:
3331 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
3332 return -EPERM;
3333
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003334}
3335#endif
3336
Jeff Johnson295189b2012-06-20 16:38:30 -07003337static int wlan_hdd_change_station(struct wiphy *wiphy,
3338 struct net_device *dev,
3339 u8 *mac,
3340 struct station_parameters *params)
3341{
3342 VOS_STATUS status = VOS_STATUS_SUCCESS;
3343 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05303344 hdd_context_t *pHddCtx;
3345 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003346 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003347#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003348 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003349 tANI_U8 isBufSta = 0;
Naresh Jayaram3180aa42014-02-12 21:47:26 +05303350 tANI_U8 isOffChannelSupported = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003351#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003352 ENTER();
3353
Gopichand Nakkala29149562013-05-10 21:43:41 +05303354 if ((NULL == pAdapter))
3355 {
3356 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3357 "invalid adapter ");
3358 return -EINVAL;
3359 }
3360
3361 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3362 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3363
3364 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
3365 {
3366 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3367 "invalid HDD state or HDD station context");
3368 return -EINVAL;
3369 }
3370
3371 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003372 {
3373 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3374 "%s:LOGP in Progress. Ignore!!!", __func__);
3375 return -EAGAIN;
3376 }
3377
Jeff Johnson295189b2012-06-20 16:38:30 -07003378 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
3379
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003380 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3381 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07003382 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003383 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07003384 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303385 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07003386 WLANTL_STA_AUTHENTICATED);
3387
Gopichand Nakkala29149562013-05-10 21:43:41 +05303388 if (status != VOS_STATUS_SUCCESS)
3389 {
3390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3391 "%s: Not able to change TL state to AUTHENTICATED", __func__);
3392 return -EINVAL;
3393 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003394 }
3395 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07003396 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3397 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303398#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003399 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
3400 StaParams.capability = params->capability;
3401 StaParams.uapsd_queues = params->uapsd_queues;
3402 StaParams.max_sp = params->max_sp;
3403
Naresh Jayaram3180aa42014-02-12 21:47:26 +05303404 /* Convert (first channel , number of channels) tuple to
3405 * the total list of channels. This goes with the assumption
3406 * that if the first channel is < 14, then the next channels
3407 * are an incremental of 1 else an incremental of 4 till the number
3408 * of channels.
3409 */
3410 if (0 != params->supported_channels_len) {
3411 int i = 0,j = 0,k = 0, no_of_channels = 0 ;
3412 for ( i = 0 ; i < params->supported_channels_len ; i+=2)
3413 {
3414 int wifi_chan_index;
3415 StaParams.supported_channels[j] = params->supported_channels[i];
3416 wifi_chan_index =
3417 ((StaParams.supported_channels[j] <= HDD_CHANNEL_14 ) ? 1 : 4 );
3418 no_of_channels = params->supported_channels[i+1];
3419 for(k=1; k <= no_of_channels; k++)
3420 {
3421 StaParams.supported_channels[j+1] =
3422 StaParams.supported_channels[j] + wifi_chan_index;
3423 j+=1;
3424 }
3425 }
3426 StaParams.supported_channels_len = j;
3427 }
3428 vos_mem_copy(StaParams.supported_oper_classes,
3429 params->supported_oper_classes,
3430 params->supported_oper_classes_len);
3431 StaParams.supported_oper_classes_len =
3432 params->supported_oper_classes_len;
3433
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003434 if (0 != params->ext_capab_len)
3435 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
3436 sizeof(StaParams.extn_capability));
3437
3438 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003439 {
3440 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003441 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003442 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003443
3444 StaParams.supported_rates_len = params->supported_rates_len;
3445
3446 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
3447 * The supported_rates array , for all the structures propogating till Add Sta
3448 * to the firmware has to be modified , if the supplicant (ieee80211) is
3449 * modified to send more rates.
3450 */
3451
3452 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3453 */
3454 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3455 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3456
3457 if (0 != StaParams.supported_rates_len) {
3458 int i = 0;
3459 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3460 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003462 "Supported Rates with Length %d", StaParams.supported_rates_len);
3463 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003465 "[%d]: %0x", i, StaParams.supported_rates[i]);
3466 }
3467
3468 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003469 {
3470 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003471 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003472 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003473
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003474 if (0 != params->ext_capab_len ) {
3475 /*Define A Macro : TODO Sunil*/
3476 if ((1<<4) & StaParams.extn_capability[3]) {
3477 isBufSta = 1;
3478 }
Naresh Jayaram3180aa42014-02-12 21:47:26 +05303479 /* TDLS Channel Switching Support */
3480 if ((1<<6) & StaParams.extn_capability[3]) {
3481 isOffChannelSupported = 1;
3482 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003483 }
Naresh Jayaram3180aa42014-02-12 21:47:26 +05303484 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac,
3485 &StaParams, isBufSta,
3486 isOffChannelSupported);
3487
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303488 if (VOS_STATUS_SUCCESS != status) {
3489 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3490 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3491 return -EINVAL;
3492 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003493 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3494
3495 if (VOS_STATUS_SUCCESS != status) {
3496 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3497 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3498 return -EINVAL;
3499 }
3500 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003501#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05303502 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003503 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003504 return status;
3505}
3506
3507/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003508 * FUNCTION: wlan_hdd_cfg80211_add_key
3509 * This function is used to initialize the key information
3510 */
3511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003512static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003513 struct net_device *ndev,
3514 u8 key_index, bool pairwise,
3515 const u8 *mac_addr,
3516 struct key_params *params
3517 )
3518#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003519static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003520 struct net_device *ndev,
3521 u8 key_index, const u8 *mac_addr,
3522 struct key_params *params
3523 )
3524#endif
3525{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003526 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003527 tCsrRoamSetKey setKey;
3528 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303529 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003530 v_U32_t roamId= 0xFF;
3531 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003532 hdd_hostapd_state_t *pHostapdState;
3533 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003534 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303535 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003536
3537 ENTER();
3538
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303539 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3540 status = wlan_hdd_validate_context(pHddCtx);
3541
3542 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003543 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3545 "%s: HDD context is not valid", __func__);
3546 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003547 }
3548
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003549 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3550 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003551
3552 if (CSR_MAX_NUM_KEY <= key_index)
3553 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003554 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003555 key_index);
3556
3557 return -EINVAL;
3558 }
3559
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003560 if (CSR_MAX_KEY_LEN < params->key_len)
3561 {
3562 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3563 params->key_len);
3564
3565 return -EINVAL;
3566 }
3567
3568 hddLog(VOS_TRACE_LEVEL_INFO,
3569 "%s: called with key index = %d & key length %d",
3570 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003571
3572 /*extract key idx, key len and key*/
3573 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3574 setKey.keyId = key_index;
3575 setKey.keyLength = params->key_len;
3576 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3577
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003578 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003579 {
3580 case WLAN_CIPHER_SUITE_WEP40:
3581 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3582 break;
3583
3584 case WLAN_CIPHER_SUITE_WEP104:
3585 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3586 break;
3587
3588 case WLAN_CIPHER_SUITE_TKIP:
3589 {
3590 u8 *pKey = &setKey.Key[0];
3591 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3592
3593 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3594
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003595 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003596
3597 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003598 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003599 |--------------|----------|----------|
3600 <---16bytes---><--8bytes--><--8bytes-->
3601
3602 */
3603 /*Sme expects the 32 bytes key to be in the below order
3604
3605 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003606 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003607 |--------------|----------|----------|
3608 <---16bytes---><--8bytes--><--8bytes-->
3609 */
3610 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003611 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003612
3613 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003614 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003615
3616 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003617 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003618
3619
3620 break;
3621 }
3622
3623 case WLAN_CIPHER_SUITE_CCMP:
3624 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3625 break;
3626
3627#ifdef FEATURE_WLAN_WAPI
3628 case WLAN_CIPHER_SUITE_SMS4:
3629 {
3630 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3631 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3632 params->key, params->key_len);
3633 return 0;
3634 }
3635#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003636
Jeff Johnson295189b2012-06-20 16:38:30 -07003637#ifdef FEATURE_WLAN_CCX
3638 case WLAN_CIPHER_SUITE_KRK:
3639 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3640 break;
3641#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003642
3643#ifdef WLAN_FEATURE_11W
3644 case WLAN_CIPHER_SUITE_AES_CMAC:
3645 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003646 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003647#endif
3648
Jeff Johnson295189b2012-06-20 16:38:30 -07003649 default:
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003650 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
Jeff Johnson295189b2012-06-20 16:38:30 -07003651 __func__, params->cipher);
3652 return -EOPNOTSUPP;
3653 }
3654
3655 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3656 __func__, setKey.encType);
3657
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003658 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003659#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3660 (!pairwise)
3661#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003662 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003663#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003664 )
3665 {
3666 /* set group key*/
3667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3668 "%s- %d: setting Broadcast key",
3669 __func__, __LINE__);
3670 setKey.keyDirection = eSIR_RX_ONLY;
3671 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3672 }
3673 else
3674 {
3675 /* set pairwise key*/
3676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3677 "%s- %d: setting pairwise key",
3678 __func__, __LINE__);
3679 setKey.keyDirection = eSIR_TX_RX;
3680 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3681 }
3682 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
3683 {
3684 setKey.keyDirection = eSIR_TX_RX;
3685 /*Set the group key*/
3686 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3687 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07003688
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003689 if ( 0 != status )
3690 {
3691 hddLog(VOS_TRACE_LEVEL_ERROR,
3692 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3693 return -EINVAL;
3694 }
3695 /*Save the keys here and call sme_RoamSetKey for setting
3696 the PTK after peer joins the IBSS network*/
3697 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
3698 &setKey, sizeof(tCsrRoamSetKey));
3699 return status;
3700 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05303701 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
3702 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
3703 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003704 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003705 if( pHostapdState->bssState == BSS_START )
3706 {
c_hpothu7c55da62014-01-23 18:34:02 +05303707 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3708 vos_status = wlan_hdd_check_ula_done(pAdapter);
3709
3710 if ( vos_status != VOS_STATUS_SUCCESS )
3711 {
3712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3713 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3714 __LINE__, vos_status );
3715
3716 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3717
3718 return -EINVAL;
3719 }
3720
Jeff Johnson295189b2012-06-20 16:38:30 -07003721 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3722
3723 if ( status != eHAL_STATUS_SUCCESS )
3724 {
3725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3726 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3727 __LINE__, status );
3728 }
3729 }
3730
3731 /* Saving WEP keys */
3732 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3733 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3734 {
3735 //Save the wep key in ap context. Issue setkey after the BSS is started.
3736 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3737 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3738 }
3739 else
3740 {
3741 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003742 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003743 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3744 }
3745 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003746 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3747 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003748 {
3749 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3750 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3751
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303752#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3753 if (!pairwise)
3754#else
3755 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
3756#endif
3757 {
3758 /* set group key*/
3759 if (pHddStaCtx->roam_info.deferKeyComplete)
3760 {
3761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3762 "%s- %d: Perform Set key Complete",
3763 __func__, __LINE__);
3764 hdd_PerformRoamSetKeyComplete(pAdapter);
3765 }
3766 }
3767
Jeff Johnson295189b2012-06-20 16:38:30 -07003768 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3769
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003770 pWextState->roamProfile.Keys.defaultIndex = key_index;
3771
3772
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003773 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003774 params->key, params->key_len);
3775
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303776
Jeff Johnson295189b2012-06-20 16:38:30 -07003777 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3778
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303779 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003780 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303781 __func__, setKey.peerMac[0], setKey.peerMac[1],
3782 setKey.peerMac[2], setKey.peerMac[3],
3783 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003784 setKey.keyDirection);
3785
3786 vos_status = wlan_hdd_check_ula_done(pAdapter);
3787
3788 if ( vos_status != VOS_STATUS_SUCCESS )
3789 {
3790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3791 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3792 __LINE__, vos_status );
3793
3794 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3795
3796 return -EINVAL;
3797
3798 }
3799
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003800#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303801 /* The supplicant may attempt to set the PTK once pre-authentication
3802 is done. Save the key in the UMAC and include it in the ADD BSS
3803 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003804 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303805 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003806 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303807 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3808 "%s: Update PreAuth Key success", __func__);
3809 return 0;
3810 }
3811 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
3812 {
3813 hddLog(VOS_TRACE_LEVEL_ERROR,
3814 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303815 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003816 }
3817#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003818
3819 /* issue set key request to SME*/
3820 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3821 pAdapter->sessionId, &setKey, &roamId );
3822
3823 if ( 0 != status )
3824 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303825 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003826 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3827 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3828 return -EINVAL;
3829 }
3830
3831
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303832 /* in case of IBSS as there was no information available about WEP keys during
3833 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07003834 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303835 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3836 !( ( IW_AUTH_KEY_MGMT_802_1X
3837 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07003838 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3839 )
3840 &&
3841 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3842 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3843 )
3844 )
3845 {
3846 setKey.keyDirection = eSIR_RX_ONLY;
3847 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3848
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303849 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003850 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303851 __func__, setKey.peerMac[0], setKey.peerMac[1],
3852 setKey.peerMac[2], setKey.peerMac[3],
3853 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003854 setKey.keyDirection);
3855
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303856 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003857 pAdapter->sessionId, &setKey, &roamId );
3858
3859 if ( 0 != status )
3860 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303861 hddLog(VOS_TRACE_LEVEL_ERROR,
3862 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003863 __func__, status);
3864 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3865 return -EINVAL;
3866 }
3867 }
3868 }
3869
3870 return 0;
3871}
3872
3873/*
3874 * FUNCTION: wlan_hdd_cfg80211_get_key
3875 * This function is used to get the key information
3876 */
3877#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303878static int wlan_hdd_cfg80211_get_key(
3879 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003880 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303881 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003882 const u8 *mac_addr, void *cookie,
3883 void (*callback)(void *cookie, struct key_params*)
3884 )
3885#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303886static int wlan_hdd_cfg80211_get_key(
3887 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003888 struct net_device *ndev,
3889 u8 key_index, const u8 *mac_addr, void *cookie,
3890 void (*callback)(void *cookie, struct key_params*)
3891 )
3892#endif
3893{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303894 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3896 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3897 struct key_params params;
3898
3899 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303900
Arif Hussain6d2a3322013-11-17 19:50:10 -08003901 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003902 __func__,pAdapter->device_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303903
Jeff Johnson295189b2012-06-20 16:38:30 -07003904 memset(&params, 0, sizeof(params));
3905
3906 if (CSR_MAX_NUM_KEY <= key_index)
3907 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303908 hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid key index %d"), key_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07003909 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303910 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003911
3912 switch(pRoamProfile->EncryptionType.encryptionType[0])
3913 {
3914 case eCSR_ENCRYPT_TYPE_NONE:
3915 params.cipher = IW_AUTH_CIPHER_NONE;
3916 break;
3917
3918 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3919 case eCSR_ENCRYPT_TYPE_WEP40:
3920 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3921 break;
3922
3923 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3924 case eCSR_ENCRYPT_TYPE_WEP104:
3925 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3926 break;
3927
3928 case eCSR_ENCRYPT_TYPE_TKIP:
3929 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3930 break;
3931
3932 case eCSR_ENCRYPT_TYPE_AES:
3933 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3934 break;
3935
3936 default:
3937 params.cipher = IW_AUTH_CIPHER_NONE;
3938 break;
3939 }
3940
3941 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3942 params.seq_len = 0;
3943 params.seq = NULL;
3944 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3945 callback(cookie, &params);
3946 return 0;
3947}
3948
3949/*
3950 * FUNCTION: wlan_hdd_cfg80211_del_key
3951 * This function is used to delete the key information
3952 */
3953#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303954static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003955 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303956 u8 key_index,
3957 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003958 const u8 *mac_addr
3959 )
3960#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303961static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003962 struct net_device *ndev,
3963 u8 key_index,
3964 const u8 *mac_addr
3965 )
3966#endif
3967{
3968 int status = 0;
3969
3970 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303971 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07003972 //it is observed that this is invalidating peer
3973 //key index whenever re-key is done. This is affecting data link.
3974 //It should be ok to ignore del_key.
3975#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303976 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3977 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003978 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3979 tCsrRoamSetKey setKey;
3980 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303981
Jeff Johnson295189b2012-06-20 16:38:30 -07003982 ENTER();
3983
3984 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3985 __func__,pAdapter->device_mode);
3986
3987 if (CSR_MAX_NUM_KEY <= key_index)
3988 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303989 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003990 key_index);
3991
3992 return -EINVAL;
3993 }
3994
3995 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3996 setKey.keyId = key_index;
3997
3998 if (mac_addr)
3999 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
4000 else
4001 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
4002
4003 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
4004
4005 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004006 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304007 )
4008 {
4009
4010 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07004011 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4012 if( pHostapdState->bssState == BSS_START)
4013 {
4014 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304015
Jeff Johnson295189b2012-06-20 16:38:30 -07004016 if ( status != eHAL_STATUS_SUCCESS )
4017 {
4018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4019 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
4020 __LINE__, status );
4021 }
4022 }
4023 }
4024 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304025 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07004026 )
4027 {
4028 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4029
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304030 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
4031
4032 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07004033 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304034 __func__, setKey.peerMac[0], setKey.peerMac[1],
4035 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07004036 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304037 if(pAdapter->sessionCtx.station.conn_info.connState ==
4038 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07004039 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304040 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004041 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304042
Jeff Johnson295189b2012-06-20 16:38:30 -07004043 if ( 0 != status )
4044 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304045 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004046 "%s: sme_RoamSetKey failure, returned %d",
4047 __func__, status);
4048 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
4049 return -EINVAL;
4050 }
4051 }
4052 }
4053#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004054 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004055 return status;
4056}
4057
4058/*
4059 * FUNCTION: wlan_hdd_cfg80211_set_default_key
4060 * This function is used to set the default tx key index
4061 */
4062#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4063static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
4064 struct net_device *ndev,
4065 u8 key_index,
4066 bool unicast, bool multicast)
4067#else
4068static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
4069 struct net_device *ndev,
4070 u8 key_index)
4071#endif
4072{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304074 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05304075 hdd_wext_state_t *pWextState;
4076 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304077 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004078
4079 ENTER();
4080
Gopichand Nakkala29149562013-05-10 21:43:41 +05304081 if ((NULL == pAdapter))
4082 {
4083 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4084 "invalid adapter");
4085 return -EINVAL;
4086 }
4087
4088 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4089 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4090
4091 if ((NULL == pWextState) || (NULL == pHddStaCtx))
4092 {
4093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4094 "invalid Wext state or HDD context");
4095 return -EINVAL;
4096 }
4097
Arif Hussain6d2a3322013-11-17 19:50:10 -08004098 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004099 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304100
Jeff Johnson295189b2012-06-20 16:38:30 -07004101 if (CSR_MAX_NUM_KEY <= key_index)
4102 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304103 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004104 key_index);
4105
4106 return -EINVAL;
4107 }
4108
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304109 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4110 status = wlan_hdd_validate_context(pHddCtx);
4111
4112 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004113 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4115 "%s: HDD context is not valid", __func__);
4116 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004117 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304118
Jeff Johnson295189b2012-06-20 16:38:30 -07004119 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07004120 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304121 )
Jeff Johnson295189b2012-06-20 16:38:30 -07004122 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05304123 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Arif Hussain6943f522013-11-04 20:10:10 -08004124 pHddStaCtx->conn_info.ucEncryptionType) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304125 (eCSR_ENCRYPT_TYPE_AES !=
Arif Hussain6943f522013-11-04 20:10:10 -08004126 pHddStaCtx->conn_info.ucEncryptionType)
Jeff Johnson295189b2012-06-20 16:38:30 -07004127 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304128 {
4129 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07004130 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304131
Jeff Johnson295189b2012-06-20 16:38:30 -07004132 tCsrRoamSetKey setKey;
4133 v_U32_t roamId= 0xFF;
4134 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304135
4136 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004137 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304138
Jeff Johnson295189b2012-06-20 16:38:30 -07004139 Keys->defaultIndex = (u8)key_index;
4140 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
4141 setKey.keyId = key_index;
4142 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304143
4144 vos_mem_copy(&setKey.Key[0],
4145 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07004146 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304147
Gopichand Nakkala29149562013-05-10 21:43:41 +05304148 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304149
4150 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07004151 &pHddStaCtx->conn_info.bssId[0],
4152 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304153
Gopichand Nakkala29149562013-05-10 21:43:41 +05304154 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
4155 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4156 eCSR_ENCRYPT_TYPE_WEP104)
4157 {
4158 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
4159 even though ap is configured for WEP-40 encryption. In this canse the key length
4160 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
4161 type(104) and switching encryption type to 40*/
4162 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4163 eCSR_ENCRYPT_TYPE_WEP40;
4164 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
4165 eCSR_ENCRYPT_TYPE_WEP40;
4166 }
4167
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304168 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07004169 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304170
Jeff Johnson295189b2012-06-20 16:38:30 -07004171 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304172 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004173 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304174
Jeff Johnson295189b2012-06-20 16:38:30 -07004175 if ( 0 != status )
4176 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304177 hddLog(VOS_TRACE_LEVEL_ERROR,
4178 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004179 status);
4180 return -EINVAL;
4181 }
4182 }
4183 }
4184
4185 /* In SoftAp mode setting key direction for default mode */
4186 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
4187 {
4188 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
4189 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
4190 (eCSR_ENCRYPT_TYPE_AES !=
4191 pWextState->roamProfile.EncryptionType.encryptionType[0])
4192 )
4193 {
4194 /* Saving key direction for default key index to TX default */
4195 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4196 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
4197 }
4198 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304199
Jeff Johnson295189b2012-06-20 16:38:30 -07004200 return status;
4201}
4202
Jeff Johnson295189b2012-06-20 16:38:30 -07004203/*
4204 * FUNCTION: wlan_hdd_cfg80211_inform_bss
4205 * This function is used to inform the BSS details to nl80211 interface.
4206 */
4207static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
4208 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
4209{
4210 struct net_device *dev = pAdapter->dev;
4211 struct wireless_dev *wdev = dev->ieee80211_ptr;
4212 struct wiphy *wiphy = wdev->wiphy;
4213 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
4214 int chan_no;
4215 int ie_length;
4216 const char *ie;
4217 unsigned int freq;
4218 struct ieee80211_channel *chan;
4219 int rssi = 0;
4220 struct cfg80211_bss *bss = NULL;
4221
4222 ENTER();
4223
4224 if( NULL == pBssDesc )
4225 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004226 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004227 return bss;
4228 }
4229
4230 chan_no = pBssDesc->channelId;
4231 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
4232 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
4233
4234 if( NULL == ie )
4235 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004236 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004237 return bss;
4238 }
4239
4240#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
4241 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
4242 {
4243 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4244 }
4245 else
4246 {
4247 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4248 }
4249#else
4250 freq = ieee80211_channel_to_frequency(chan_no);
4251#endif
4252
4253 chan = __ieee80211_get_channel(wiphy, freq);
4254
4255 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
4256 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
4257 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
4258 if (bss == NULL)
4259 {
4260 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
4261
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304262 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
4263 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07004264 pBssDesc->capabilityInfo,
4265 pBssDesc->beaconInterval, ie, ie_length,
4266 rssi, GFP_KERNEL ));
4267}
4268 else
4269 {
4270 return bss;
4271 }
4272}
4273
4274
4275
4276/*
4277 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
4278 * This function is used to inform the BSS details to nl80211 interface.
4279 */
4280struct cfg80211_bss*
4281wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
4282 tSirBssDescription *bss_desc
4283 )
4284{
4285 /*
4286 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
4287 already exists in bss data base of cfg80211 for that particular BSS ID.
4288 Using cfg80211_inform_bss_frame to update the bss entry instead of
4289 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
4290 now there is no possibility to get the mgmt(probe response) frame from PE,
4291 converting bss_desc to ieee80211_mgmt(probe response) and passing to
4292 cfg80211_inform_bss_frame.
4293 */
4294 struct net_device *dev = pAdapter->dev;
4295 struct wireless_dev *wdev = dev->ieee80211_ptr;
4296 struct wiphy *wiphy = wdev->wiphy;
4297 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004298#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4299 qcom_ie_age *qie_age = NULL;
4300 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
4301#else
Jeff Johnson295189b2012-06-20 16:38:30 -07004302 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004303#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004304 const char *ie =
4305 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
4306 unsigned int freq;
4307 struct ieee80211_channel *chan;
Abhishek Singh1e2bfa32014-01-02 15:44:15 +05304308 struct ieee80211_mgmt *mgmt = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004309 struct cfg80211_bss *bss_status = NULL;
4310 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
4311 int rssi = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07004312 hdd_context_t *pHddCtx;
4313 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07004314#ifdef WLAN_OPEN_SOURCE
4315 struct timespec ts;
4316#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004317
Wilson Yangf80a0542013-10-07 13:02:37 -07004318 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4319 status = wlan_hdd_validate_context(pHddCtx);
4320
4321 /*bss_update is not allowed during wlan driver loading or unloading*/
4322 if (pHddCtx->isLoadUnloadInProgress)
4323 {
4324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4325 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
4326 return NULL;
4327 }
4328
4329
4330 if (0 != status)
4331 {
4332 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4333 "%s: HDD context is not valid", __func__);
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004334 return NULL;
Wilson Yangf80a0542013-10-07 13:02:37 -07004335 }
4336
Abhishek Singh1e2bfa32014-01-02 15:44:15 +05304337 mgmt = kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
Wilson Yangf80a0542013-10-07 13:02:37 -07004338 if (!mgmt)
4339 {
4340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4341 "%s: memory allocation failed ", __func__);
4342 return NULL;
4343 }
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004344
Jeff Johnson295189b2012-06-20 16:38:30 -07004345 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07004346
4347#ifdef WLAN_OPEN_SOURCE
4348 /* Android does not want the timestamp from the frame.
4349 Instead it wants a monotonic increasing value */
4350 get_monotonic_boottime(&ts);
4351 mgmt->u.probe_resp.timestamp =
4352 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
4353#else
4354 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07004355 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
4356 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07004357
4358#endif
4359
Jeff Johnson295189b2012-06-20 16:38:30 -07004360 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
4361 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004362
4363#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4364 /* GPS Requirement: need age ie per entry. Using vendor specific. */
4365 /* Assuming this is the last IE, copy at the end */
4366 ie_length -=sizeof(qcom_ie_age);
4367 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
4368 qie_age->element_id = QCOM_VENDOR_IE_ID;
4369 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
4370 qie_age->oui_1 = QCOM_OUI1;
4371 qie_age->oui_2 = QCOM_OUI2;
4372 qie_age->oui_3 = QCOM_OUI3;
4373 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
4374 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
4375#endif
4376
Jeff Johnson295189b2012-06-20 16:38:30 -07004377 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05304378 if (bss_desc->fProbeRsp)
4379 {
4380 mgmt->frame_control |=
4381 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
4382 }
4383 else
4384 {
4385 mgmt->frame_control |=
4386 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
4387 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004388
4389#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304390 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004391 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
4392 {
4393 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4394 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304395 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004396 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
4397
4398 {
4399 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4400 }
4401 else
4402 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304403 hddLog(VOS_TRACE_LEVEL_ERROR, "%s Invalid chan_no:%d",
4404 __func__, chan_no);
Jeff Johnson295189b2012-06-20 16:38:30 -07004405 kfree(mgmt);
4406 return NULL;
4407 }
4408#else
4409 freq = ieee80211_channel_to_frequency(chan_no);
4410#endif
4411 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004412 /*when the band is changed on the fly using the GUI, three things are done
4413 * 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)
4414 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
4415 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
4416 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
4417 * and discards the channels correponding to previous band and calls back with zero bss results.
4418 * 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
4419 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
4420 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
4421 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
4422 * So drop the bss and continue to next bss.
4423 */
4424 if(chan == NULL)
4425 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304426 hddLog(VOS_TRACE_LEVEL_ERROR, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07004427 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004428 return NULL;
4429 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004430 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304431 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07004432 * */
4433 if (( eConnectionState_Associated ==
4434 pAdapter->sessionCtx.station.conn_info.connState ) &&
4435 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
4436 pAdapter->sessionCtx.station.conn_info.bssId,
4437 WNI_CFG_BSSID_LEN)))
4438 {
4439 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
4440 rssi = (pAdapter->rssi * 100);
4441 }
4442 else
4443 {
4444 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
4445 }
4446
Nirav Shah20ac06f2013-12-12 18:14:06 +05304447 hddLog(VOS_TRACE_LEVEL_INFO, "%s: BSSID:" MAC_ADDRESS_STR " Channel:%d"
4448 "RSSI:%d", __func__, MAC_ADDR_ARRAY(mgmt->bssid),
4449 chan->center_freq, (int)(rssi/100));
4450
Jeff Johnson295189b2012-06-20 16:38:30 -07004451 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4452 frame_len, rssi, GFP_KERNEL);
4453 kfree(mgmt);
4454 return bss_status;
4455}
4456
4457/*
4458 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4459 * This function is used to update the BSS data base of CFG8011
4460 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304461struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004462 tCsrRoamInfo *pRoamInfo
4463 )
4464{
4465 tCsrRoamConnectedProfile roamProfile;
4466 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4467 struct cfg80211_bss *bss = NULL;
4468
4469 ENTER();
4470
4471 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4472 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4473
4474 if (NULL != roamProfile.pBssDesc)
4475 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304476 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004477 &roamProfile);
4478
4479 if (NULL == bss)
4480 {
4481 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4482 __func__);
4483 }
4484
4485 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4486 }
4487 else
4488 {
4489 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4490 __func__);
4491 }
4492 return bss;
4493}
4494
4495/*
4496 * FUNCTION: wlan_hdd_cfg80211_update_bss
4497 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304498static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4499 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07004500 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304501{
Jeff Johnson295189b2012-06-20 16:38:30 -07004502 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4503 tCsrScanResultInfo *pScanResult;
4504 eHalStatus status = 0;
4505 tScanResultHandle pResult;
4506 struct cfg80211_bss *bss_status = NULL;
Wilson Yangf80a0542013-10-07 13:02:37 -07004507 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004508
4509 ENTER();
4510
Wilson Yangf80a0542013-10-07 13:02:37 -07004511 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4512
4513 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004514 {
Wilson Yangf80a0542013-10-07 13:02:37 -07004515 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4516 "%s:LOGP in Progress. Ignore!!!",__func__);
4517 return -EAGAIN;
Jeff Johnson295189b2012-06-20 16:38:30 -07004518 }
4519
Wilson Yangf80a0542013-10-07 13:02:37 -07004520
4521 /*bss_update is not allowed during wlan driver loading or unloading*/
4522 if (pHddCtx->isLoadUnloadInProgress)
4523 {
4524 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4525 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
4526 return VOS_STATUS_E_PERM;
4527 }
4528
4529
Jeff Johnson295189b2012-06-20 16:38:30 -07004530 /*
4531 * start getting scan results and populate cgf80211 BSS database
4532 */
4533 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4534
4535 /* no scan results */
4536 if (NULL == pResult)
4537 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304538 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result Status %d",
4539 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004540 return status;
4541 }
4542
4543 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4544
4545 while (pScanResult)
4546 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304547 /*
4548 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4549 * entry already exists in bss data base of cfg80211 for that
4550 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4551 * bss entry instead of cfg80211_inform_bss, But this call expects
4552 * mgmt packet as input. As of now there is no possibility to get
4553 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07004554 * ieee80211_mgmt(probe response) and passing to c
4555 * fg80211_inform_bss_frame.
4556 * */
4557
4558 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4559 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304560
Jeff Johnson295189b2012-06-20 16:38:30 -07004561
4562 if (NULL == bss_status)
4563 {
4564 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08004565 "%s: NULL returned by cfg80211_inform_bss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004566 }
4567 else
4568 {
Yue Maf49ba872013-08-19 12:04:25 -07004569 cfg80211_put_bss(
4570#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
4571 wiphy,
4572#endif
4573 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004574 }
4575
4576 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4577 }
4578
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304579 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07004580
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304581 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004582}
4583
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004584void
4585hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4586{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304587 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Arif Hussaina7c8e412013-11-20 11:06:42 -08004588 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(macAddr));
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004589} /****** end hddPrintMacAddr() ******/
4590
4591void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004592hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004593{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304594 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Arif Hussain6d2a3322013-11-17 19:50:10 -08004595 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004596 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4597 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4598 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004599} /****** end hddPrintPmkId() ******/
4600
4601//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4602//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4603
4604//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4605//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4606
4607#define dump_bssid(bssid) \
4608 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004609 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4610 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004611 }
4612
4613#define dump_pmkid(pMac, pmkid) \
4614 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004615 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4616 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004617 }
4618
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004619#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004620/*
4621 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4622 * This function is used to notify the supplicant of a new PMKSA candidate.
4623 */
4624int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304625 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004626 int index, bool preauth )
4627{
Jeff Johnsone7245742012-09-05 17:12:55 -07004628#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004629 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004630 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004631
4632 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004633 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004634
4635 if( NULL == pRoamInfo )
4636 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004637 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004638 return -EINVAL;
4639 }
4640
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004641 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4642 {
4643 dump_bssid(pRoamInfo->bssid);
4644 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004645 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004646 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004647#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304648 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004649}
4650#endif //FEATURE_WLAN_LFR
4651
Yue Maef608272013-04-08 23:09:17 -07004652#ifdef FEATURE_WLAN_LFR_METRICS
4653/*
4654 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth
4655 * 802.11r/LFR metrics reporting function to report preauth initiation
4656 *
4657 */
4658#define MAX_LFR_METRICS_EVENT_LENGTH 100
4659VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
4660 tCsrRoamInfo *pRoamInfo)
4661{
4662 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4663 union iwreq_data wrqu;
4664
4665 ENTER();
4666
4667 if (NULL == pAdapter)
4668 {
4669 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4670 return VOS_STATUS_E_FAILURE;
4671 }
4672
4673 /* create the event */
4674 memset(&wrqu, 0, sizeof(wrqu));
4675 memset(metrics_notification, 0, sizeof(metrics_notification));
4676
4677 wrqu.data.pointer = metrics_notification;
4678 wrqu.data.length = scnprintf(metrics_notification,
4679 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_INIT "
4680 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
4681
4682 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4683
4684 EXIT();
4685
4686 return VOS_STATUS_SUCCESS;
4687}
4688
4689/*
4690 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth_status
4691 * 802.11r/LFR metrics reporting function to report preauth completion
4692 * or failure
4693 */
4694VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status(
4695 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, bool preauth_status)
4696{
4697 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4698 union iwreq_data wrqu;
4699
4700 ENTER();
4701
4702 if (NULL == pAdapter)
4703 {
4704 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4705 return VOS_STATUS_E_FAILURE;
4706 }
4707
4708 /* create the event */
4709 memset(&wrqu, 0, sizeof(wrqu));
4710 memset(metrics_notification, 0, sizeof(metrics_notification));
4711
4712 scnprintf(metrics_notification, sizeof(metrics_notification),
4713 "QCOM: LFR_PREAUTH_STATUS "MAC_ADDRESS_STR,
4714 MAC_ADDR_ARRAY(pRoamInfo->bssid));
4715
4716 if (1 == preauth_status)
4717 strncat(metrics_notification, " TRUE", 5);
4718 else
4719 strncat(metrics_notification, " FALSE", 6);
4720
4721 wrqu.data.pointer = metrics_notification;
4722 wrqu.data.length = strlen(metrics_notification);
4723
4724 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4725
4726 EXIT();
4727
4728 return VOS_STATUS_SUCCESS;
4729}
4730
4731/*
4732 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_handover
4733 * 802.11r/LFR metrics reporting function to report handover initiation
4734 *
4735 */
4736VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t * pAdapter,
4737 tCsrRoamInfo *pRoamInfo)
4738{
4739 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4740 union iwreq_data wrqu;
4741
4742 ENTER();
4743
4744 if (NULL == pAdapter)
4745 {
4746 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4747 return VOS_STATUS_E_FAILURE;
4748 }
4749
4750 /* create the event */
4751 memset(&wrqu, 0, sizeof(wrqu));
4752 memset(metrics_notification, 0, sizeof(metrics_notification));
4753
4754 wrqu.data.pointer = metrics_notification;
4755 wrqu.data.length = scnprintf(metrics_notification,
4756 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_HANDOVER "
4757 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
4758
4759 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4760
4761 EXIT();
4762
4763 return VOS_STATUS_SUCCESS;
4764}
4765#endif
4766
Jeff Johnson295189b2012-06-20 16:38:30 -07004767/*
4768 * FUNCTION: hdd_cfg80211_scan_done_callback
4769 * scanning callback function, called after finishing scan
4770 *
4771 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304772static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07004773 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4774{
4775 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304776 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07004777 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004778 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4779 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004780 struct cfg80211_scan_request *req = NULL;
4781 int ret = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304782 long waitRet = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004783
4784 ENTER();
4785
4786 hddLog(VOS_TRACE_LEVEL_INFO,
4787 "%s called with halHandle = %p, pContext = %p,"
Arif Hussain6d2a3322013-11-17 19:50:10 -08004788 "scanID = %d, returned status = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004789 __func__, halHandle, pContext, (int) scanId, (int) status);
4790
Kiet Lamac06e2c2013-10-23 16:25:07 +05304791 pScanInfo->mScanPendingCounter = 0;
4792
Jeff Johnson295189b2012-06-20 16:38:30 -07004793 //Block on scan req completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304794 waitRet = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004795 &pScanInfo->scan_req_completion_event,
4796 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304797 if (waitRet <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07004798 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304799 hddLog(VOS_TRACE_LEVEL_ERROR,
4800 "%s wait on scan_req_completion_event failed %ld",__func__, waitRet);
Jeff Johnson295189b2012-06-20 16:38:30 -07004801 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004802 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004803 }
4804
Yue Maef608272013-04-08 23:09:17 -07004805 if (pScanInfo->mScanPending != VOS_TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -07004806 {
4807 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004808 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004809 }
4810
4811 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304812 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07004813 {
4814 hddLog(VOS_TRACE_LEVEL_INFO,
4815 "%s called with mismatched scanId pScanInfo->scanId = %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08004816 "scanId = %d", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07004817 (int) scanId);
4818 }
4819
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304820 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 pAdapter);
4822
4823 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304824 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004825
4826
4827 /* If any client wait scan result through WEXT
4828 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004829 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004830 {
4831 /* The other scan request waiting for current scan finish
4832 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004833 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004834 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004835 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004836 }
4837 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004838 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004839 {
4840 struct net_device *dev = pAdapter->dev;
4841 union iwreq_data wrqu;
4842 int we_event;
4843 char *msg;
4844
4845 memset(&wrqu, '\0', sizeof(wrqu));
4846 we_event = SIOCGIWSCAN;
4847 msg = NULL;
4848 wireless_send_event(dev, we_event, &wrqu, msg);
4849 }
4850 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004851 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004852
4853 /* Get the Scan Req */
4854 req = pAdapter->request;
4855
4856 if (!req)
4857 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004858 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004859 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004860 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004861 }
4862
4863 /*
4864 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304865 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 req->n_ssids = 0;
4867 req->n_channels = 0;
4868 req->ie = 0;
4869
Jeff Johnson295189b2012-06-20 16:38:30 -07004870 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004871 /* Scan is no longer pending */
4872 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004873
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004874 /*
4875 * cfg80211_scan_done informing NL80211 about completion
4876 * of scanning
4877 */
4878 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004879 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004880
Jeff Johnsone7245742012-09-05 17:12:55 -07004881allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004882 /* release the wake lock at the end of the scan*/
4883 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004884
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004885 /* Acquire wakelock to handle the case where APP's tries to suspend
4886 * immediatly after the driver gets connect request(i.e after scan)
4887 * from supplicant, this result in app's is suspending and not able
4888 * to process the connect request to AP */
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05304889 hdd_prevent_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004890
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004891#ifdef FEATURE_WLAN_TDLS
4892 wlan_hdd_tdls_scan_done_callback(pAdapter);
4893#endif
4894
Jeff Johnson295189b2012-06-20 16:38:30 -07004895 EXIT();
4896 return 0;
4897}
4898
4899/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004900 * FUNCTION: hdd_isScanAllowed
4901 * Go through each adapter and check if scan allowed
4902 *
4903 */
4904v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4905{
4906 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4907 hdd_station_ctx_t *pHddStaCtx = NULL;
4908 hdd_adapter_t *pAdapter = NULL;
4909 VOS_STATUS status = 0;
4910 v_U8_t staId = 0;
4911 v_U8_t *staMac = NULL;
4912
c_hpothu9b781ba2013-12-30 20:57:45 +05304913 if (TRUE == pHddCtx->btCoexModeSet)
4914 {
4915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4916 FL("BTCoex Mode operation in progress, Do not allow scan"));
4917 return VOS_FALSE;
4918 }
4919
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004920 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4921
4922 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4923 {
4924 pAdapter = pAdapterNode->pAdapter;
4925
4926 if( pAdapter )
4927 {
4928 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304929 "%s: Adapter with device mode %d exists",
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004930 __func__, pAdapter->device_mode);
4931 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4932 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4933 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4934 {
4935 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4936 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4937 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4938 {
4939 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4940 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain24bafea2013-11-15 15:10:03 -08004941 "%s: client " MAC_ADDRESS_STR
4942 " is in the middle of WPS/EAPOL exchange.", __func__,
4943 MAC_ADDR_ARRAY(staMac));
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004944 return VOS_FALSE;
4945 }
4946 }
4947 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4948 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4949 {
4950 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4951 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304952 if ((pAdapter->aStaInfo[staId].isUsed) &&
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004953 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4954 {
4955 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4956
4957 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain24bafea2013-11-15 15:10:03 -08004958 "%s: client " MAC_ADDRESS_STR " of SoftAP/P2P-GO is in the "
4959 "middle of WPS/EAPOL exchange.", __func__,
4960 MAC_ADDR_ARRAY(staMac));
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004961 return VOS_FALSE;
4962 }
4963 }
4964 }
4965 }
4966 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4967 pAdapterNode = pNext;
4968 }
4969 hddLog(VOS_TRACE_LEVEL_INFO,
4970 "%s: Scan allowed", __func__);
4971 return VOS_TRUE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304972}
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004973
4974/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004975 * FUNCTION: wlan_hdd_cfg80211_scan
4976 * this scan respond to scan trigger and update cfg80211 scan database
4977 * later, scan dump command can be used to recieve scan results
4978 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004979int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4980#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4981 struct net_device *dev,
4982#endif
4983 struct cfg80211_scan_request *request)
4984{
4985#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4986 struct net_device *dev = request->wdev->netdev;
4987#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304988 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07004989 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4990 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304991 hdd_config_t *cfg_param = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004992 tCsrScanRequest scanRequest;
4993 tANI_U8 *channelList = NULL, i;
4994 v_U32_t scanId = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304995 int status;
4996 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004997 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004998
4999 ENTER();
5000
Arif Hussain6d2a3322013-11-17 19:50:10 -08005001 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005002 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005003
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305004 status = wlan_hdd_validate_context(pHddCtx);
5005
5006 if (0 != status)
5007 {
5008 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5009 "%s: HDD context is not valid", __func__);
5010 return status;
5011 }
5012
5013 cfg_param = pHddCtx->cfg_ini;
5014 pScanInfo = &pHddCtx->scan_info;
5015
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005016 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005017 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005018 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005019 {
5020 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005021 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
5022 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005023 return -EBUSY;
5024 }
5025
Jeff Johnson295189b2012-06-20 16:38:30 -07005026#ifdef WLAN_BTAMP_FEATURE
5027 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005028 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07005029 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005030 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005031 "%s: No scanning when AMP is on", __func__);
5032 return -EOPNOTSUPP;
5033 }
5034#endif
5035 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005036 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005038 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005039 "%s: Not scanning on device_mode = %d",
5040 __func__, pAdapter->device_mode);
5041 return -EOPNOTSUPP;
5042 }
5043
5044 if (TRUE == pScanInfo->mScanPending)
5045 {
Kiet Lamac06e2c2013-10-23 16:25:07 +05305046 if ( MAX_PENDING_LOG > pScanInfo->mScanPendingCounter++ )
5047 {
5048 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: mScanPending is TRUE", __func__);
5049 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005050 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07005051 }
5052
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305053 //Don't Allow Scan and return busy if Remain On
Jeff Johnson32d95a32012-09-10 13:15:23 -07005054 //Channel and action frame is pending
5055 //Otherwise Cancel Remain On Channel and allow Scan
5056 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005057 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07005058 {
Kiet Lamac06e2c2013-10-23 16:25:07 +05305059 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Remain On Channel Pending", __func__);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005060 return -EBUSY;
5061 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005062#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005063 /* if tdls disagree scan right now, return immediately.
5064 tdls will schedule the scan when scan is allowed. (return SUCCESS)
5065 or will reject the scan if any TDLS is in progress. (return -EBUSY)
5066 */
5067 status = wlan_hdd_tdls_scan_callback (pAdapter,
5068 wiphy,
5069#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
5070 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07005071#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005072 request);
5073 if(status <= 0)
5074 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305075 if(!status)
5076 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS in progress."
5077 "scan rejected %d", __func__, status);
5078 else
5079 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS teardown is ongoing %d",
5080 __func__, status);
5081
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005082 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005083 }
5084#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07005085
Jeff Johnson295189b2012-06-20 16:38:30 -07005086 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
5087 {
5088 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08005089 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005090 return -EAGAIN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305091 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005092 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
5093 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305094 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005095 "%s: MAX TM Level Scan not allowed", __func__);
5096 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305097 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07005098 }
5099 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
5100
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08005101 /* Check if scan is allowed at this point of time.
5102 */
5103 if (!hdd_isScanAllowed(pHddCtx))
5104 {
5105 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
5106 return -EBUSY;
5107 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305108
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 vos_mem_zero( &scanRequest, sizeof(scanRequest));
5110
5111 if (NULL != request)
5112 {
5113 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305114 (int)request->n_ssids);
Jeff Johnson295189b2012-06-20 16:38:30 -07005115
5116 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
5117 * Becasue of this, driver is assuming that this is not wildcard scan and so
5118 * is not aging out the scan results.
5119 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07005120 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 {
5122 request->n_ssids = 0;
5123 }
5124
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005125 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07005126 {
5127 tCsrSSIDInfo *SsidInfo;
5128 int j;
5129 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
5130 /* Allocate num_ssid tCsrSSIDInfo structure */
5131 SsidInfo = scanRequest.SSIDs.SSIDList =
5132 ( tCsrSSIDInfo *)vos_mem_malloc(
5133 request->n_ssids*sizeof(tCsrSSIDInfo));
5134
5135 if(NULL == scanRequest.SSIDs.SSIDList)
5136 {
5137 hddLog(VOS_TRACE_LEVEL_ERROR,
Nirav Shah20ac06f2013-12-12 18:14:06 +05305138 "%s: memory alloc failed SSIDInfo buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005139 return -ENOMEM;
5140 }
5141
5142 /* copy all the ssid's and their length */
5143 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
5144 {
5145 /* get the ssid length */
5146 SsidInfo->SSID.length = request->ssids[j].ssid_len;
5147 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
5148 SsidInfo->SSID.length);
5149 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
Nirav Shah20ac06f2013-12-12 18:14:06 +05305150 hddLog(VOS_TRACE_LEVEL_INFO, "SSID number %d: %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07005151 j, SsidInfo->SSID.ssId);
5152 }
5153 /* set the scan type to active */
5154 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5155 }
5156 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
5157 {
5158 /* set the scan type to active */
5159 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5160 }
5161 else
5162 {
5163 /*Set the scan type to default type, in this case it is ACTIVE*/
5164 scanRequest.scanType = pScanInfo->scan_mode;
5165 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305166 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
5168 }
5169 else
5170 {
5171 /* set the scan type to active */
5172 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5173 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
5174
5175 /* set min and max channel time to zero */
5176 scanRequest.minChnTime = 0;
5177 scanRequest.maxChnTime = 0;
5178 }
5179
5180 /* set BSSType to default type */
5181 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
5182
5183 /*TODO: scan the requested channels only*/
5184
5185 /*Right now scanning all the channels */
5186 if( request )
5187 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305188 hddLog(VOS_TRACE_LEVEL_INFO,
5189 "No of Scan Channels: %d", request->n_channels);
Jeff Johnson295189b2012-06-20 16:38:30 -07005190 if( request->n_channels )
5191 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305192 char chList [(request->n_channels*5)+1];
5193 int len;
Jeff Johnson295189b2012-06-20 16:38:30 -07005194 channelList = vos_mem_malloc( request->n_channels );
5195 if( NULL == channelList )
5196 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305197 hddLog(VOS_TRACE_LEVEL_ERROR,
Nirav Shah20ac06f2013-12-12 18:14:06 +05305198 "%s: memory alloc failed channelList", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005199 status = -ENOMEM;
5200 goto free_mem;
5201 }
5202
Nirav Shah20ac06f2013-12-12 18:14:06 +05305203 for( i = 0, len = 0; i < request->n_channels ; i++ )
5204 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005205 channelList[i] = request->channels[i]->hw_value;
Nirav Shah20ac06f2013-12-12 18:14:06 +05305206 len += snprintf(chList+len, 5, "%d ", channelList[i]);
5207 }
5208
5209 hddLog(VOS_TRACE_LEVEL_INFO,
5210 "Channel-List: %s ", chList);
Jeff Johnson295189b2012-06-20 16:38:30 -07005211 }
5212
5213 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
5214 scanRequest.ChannelInfo.ChannelList = channelList;
5215
5216 /* set requestType to full scan */
5217 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305218
5219 /* Flush the scan results(only p2p beacons) for STA scan and P2P
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005220 * search (Flush on both full scan and social scan but not on single
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305221 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005222 */
5223
5224 /* Supplicant does single channel scan after 8-way handshake
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305225 * and in that case driver shoudnt flush scan results. If
5226 * driver flushes the scan results here and unfortunately if
5227 * the AP doesnt respond to our probe req then association
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005228 * fails which is not desired
5229 */
5230
5231 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
5232 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305233 hddLog(VOS_TRACE_LEVEL_DEBUG, "Flushing P2P Results");
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005234 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
5235 pAdapter->sessionId );
5236 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005237
5238 if( request->ie_len )
5239 {
5240 /* save this for future association (join requires this) */
Agarwal Ashish4f616132013-12-30 23:32:50 +05305241 /*TODO: Array needs to be converted to dynamic allocation,
5242 * as multiple ie.s can be sent in cfg80211_scan_request structure
5243 * CR 597966
5244 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005245 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
5246 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
5247 pScanInfo->scanAddIE.length = request->ie_len;
5248
Agarwal Ashish4f616132013-12-30 23:32:50 +05305249 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07005250 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
Agarwal Ashish4f616132013-12-30 23:32:50 +05305251 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07005252 {
Agarwal Ashish4f616132013-12-30 23:32:50 +05305253 if ( request->ie_len <= SIR_MAC_MAX_IE_LENGTH)
5254 {
5255 pwextBuf->roamProfile.nAddIEScanLength = request->ie_len;
5256 memcpy( pwextBuf->roamProfile.addIEScan,
5257 request->ie, request->ie_len);
5258 }
5259 else
5260 {
5261 hddLog(VOS_TRACE_LEVEL_ERROR, "Scan Ie length is invalid:"
5262 "%d", request->ie_len);
5263 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005264
Agarwal Ashish4f616132013-12-30 23:32:50 +05305265 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005266 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
5267 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
5268
Jeff Johnson295189b2012-06-20 16:38:30 -07005269 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
5270 request->ie_len);
5271 if (pP2pIe != NULL)
5272 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07005273#ifdef WLAN_FEATURE_P2P_DEBUG
5274 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
5275 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
5276 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5277 {
5278 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
5279 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
5280 "Go nego completed to Connection is started");
5281 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
5282 "for 8way Handshake");
5283 }
5284 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
5285 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5286 {
5287 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
5288 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
5289 "Disconnected state to Connection is started");
5290 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
5291 "for 4way Handshake");
5292 }
5293#endif
5294
Jeff Johnsone7245742012-09-05 17:12:55 -07005295 /* no_cck will be set during p2p find to disable 11b rates */
5296 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07005297 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005298 hddLog(VOS_TRACE_LEVEL_INFO,
5299 "%s: This is a P2P Search", __func__);
5300 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07005301
Jeff Johnsone7245742012-09-05 17:12:55 -07005302 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
5303 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07005304 /* set requestType to P2P Discovery */
5305 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07005306 }
5307
5308 /*
5309 Skip Dfs Channel in case of P2P Search
5310 if it is set in ini file
5311 */
5312 if(cfg_param->skipDfsChnlInP2pSearch)
5313 {
5314 scanRequest.skipDfsChnlInP2pSearch = 1;
5315 }
5316 else
5317 {
5318 scanRequest.skipDfsChnlInP2pSearch = 0;
5319 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005320
Jeff Johnson295189b2012-06-20 16:38:30 -07005321 }
5322 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005323 }
5324 }
5325
5326 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
5327
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07005328 /* acquire the wakelock to avoid the apps suspend during the scan. To
5329 * address the following issues.
5330 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
5331 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
5332 * for long time, this result in apps running at full power for long time.
5333 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
5334 * be stuck in full power because of resume BMPS
5335 */
5336 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005337
Nirav Shah20ac06f2013-12-12 18:14:06 +05305338 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
5339 "requestType %d, scanType %d, minChnTime %d, maxChnTime %d,"
5340 "p2pSearch %d, skipDfsChnlInP2pSearch %d", scanRequest.requestType,
5341 scanRequest.scanType, scanRequest.minChnTime, scanRequest.maxChnTime,
5342 scanRequest.p2pSearch, scanRequest.skipDfsChnlInP2pSearch);
5343
Jeff Johnsone7245742012-09-05 17:12:55 -07005344 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005345 pAdapter->sessionId, &scanRequest, &scanId,
5346 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07005347
Jeff Johnson295189b2012-06-20 16:38:30 -07005348 if (eHAL_STATUS_SUCCESS != status)
5349 {
5350 hddLog(VOS_TRACE_LEVEL_ERROR,
5351 "%s: sme_ScanRequest returned error %d", __func__, status);
5352 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07005353 if(eHAL_STATUS_RESOURCES == status)
5354 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305355 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HO is in progress."
5356 "So defer the scan by informing busy",__func__);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07005357 status = -EBUSY;
5358 } else {
5359 status = -EIO;
5360 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07005361 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005362 goto free_mem;
5363 }
5364
5365 pScanInfo->mScanPending = TRUE;
5366 pAdapter->request = request;
5367 pScanInfo->scanId = scanId;
5368
5369 complete(&pScanInfo->scan_req_completion_event);
5370
5371free_mem:
5372 if( scanRequest.SSIDs.SSIDList )
5373 {
5374 vos_mem_free(scanRequest.SSIDs.SSIDList);
5375 }
5376
5377 if( channelList )
5378 vos_mem_free( channelList );
5379
5380 EXIT();
5381
5382 return status;
5383}
5384
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005385
5386void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
5387{
5388 v_U8_t iniDot11Mode =
5389 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
5390 eHddDot11Mode hddDot11Mode = iniDot11Mode;
5391
5392 switch ( iniDot11Mode )
5393 {
5394 case eHDD_DOT11_MODE_AUTO:
5395 case eHDD_DOT11_MODE_11ac:
5396 case eHDD_DOT11_MODE_11ac_ONLY:
5397#ifdef WLAN_FEATURE_11AC
5398 hddDot11Mode = eHDD_DOT11_MODE_11ac;
5399#else
5400 hddDot11Mode = eHDD_DOT11_MODE_11n;
5401#endif
5402 break;
5403 case eHDD_DOT11_MODE_11n:
5404 case eHDD_DOT11_MODE_11n_ONLY:
5405 hddDot11Mode = eHDD_DOT11_MODE_11n;
5406 break;
5407 default:
5408 hddDot11Mode = iniDot11Mode;
5409 break;
5410 }
5411 /* This call decides required channel bonding mode */
5412 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
5413 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
5414 operationChannel);
5415}
5416
Jeff Johnson295189b2012-06-20 16:38:30 -07005417/*
5418 * FUNCTION: wlan_hdd_cfg80211_connect_start
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305419 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -07005420 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305421int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005422 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07005423{
5424 int status = 0;
5425 hdd_wext_state_t *pWextState;
5426 v_U32_t roamId;
5427 tCsrRoamProfile *pRoamProfile;
Jeff Johnson295189b2012-06-20 16:38:30 -07005428 eCsrAuthType RSNAuthType;
5429
5430 ENTER();
5431
5432 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305433
Jeff Johnson295189b2012-06-20 16:38:30 -07005434 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
5435 {
5436 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
5437 return -EINVAL;
5438 }
5439
5440 pRoamProfile = &pWextState->roamProfile;
5441
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305442 if (pRoamProfile)
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005444 hdd_station_ctx_t *pHddStaCtx;
5445 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005446
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305447 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07005448 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
5449 {
5450 /*QoS not enabled in cfg file*/
5451 pRoamProfile->uapsd_mask = 0;
5452 }
5453 else
5454 {
5455 /*QoS enabled, update uapsd mask from cfg file*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305456 pRoamProfile->uapsd_mask =
Jeff Johnson295189b2012-06-20 16:38:30 -07005457 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
5458 }
5459
5460 pRoamProfile->SSIDs.numOfSSIDs = 1;
5461 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
5462 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305463 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
5465 ssid, ssid_len);
5466
5467 if (bssid)
5468 {
5469 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
5470 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
5471 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305472 /* Save BSSID in seperate variable as well, as RoamProfile
5473 BSSID is getting zeroed out in the association process. And in
Jeff Johnson295189b2012-06-20 16:38:30 -07005474 case of join failure we should send valid BSSID to supplicant
5475 */
5476 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
5477 WNI_CFG_BSSID_LEN);
5478 }
Dhanashri Atre51981c62013-06-13 11:47:57 -07005479 else
5480 {
5481 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
5482 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005483
5484 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
5485 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305486 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005487 /*set gen ie*/
5488 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
5489 /*set auth*/
5490 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
5491 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005492#ifdef FEATURE_WLAN_WAPI
5493 if (pAdapter->wapi_info.nWapiMode)
5494 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005495 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005496 switch (pAdapter->wapi_info.wapiAuthMode)
5497 {
5498 case WAPI_AUTH_MODE_PSK:
5499 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005500 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005501 pAdapter->wapi_info.wapiAuthMode);
5502 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
5503 break;
5504 }
5505 case WAPI_AUTH_MODE_CERT:
5506 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005507 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005508 pAdapter->wapi_info.wapiAuthMode);
5509 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
5510 break;
5511 }
5512 } // End of switch
5513 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
5514 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
5515 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005516 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 pRoamProfile->AuthType.numEntries = 1;
5518 pRoamProfile->EncryptionType.numEntries = 1;
5519 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5520 pRoamProfile->mcEncryptionType.numEntries = 1;
5521 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5522 }
5523 }
5524#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305525#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305526 /* Initializing gtkOffloadReqParams */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305527 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5528 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5529 {
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305530 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
5531 sizeof (tSirGtkOffloadParams));
5532 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305533 }
5534#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005535 pRoamProfile->csrPersona = pAdapter->device_mode;
5536
Jeff Johnson32d95a32012-09-10 13:15:23 -07005537 if( operatingChannel )
5538 {
5539 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
5540 pRoamProfile->ChannelInfo.numOfChannels = 1;
5541 }
Chet Lanctot186b5732013-03-18 10:26:30 -07005542 else
5543 {
5544 pRoamProfile->ChannelInfo.ChannelList = NULL;
5545 pRoamProfile->ChannelInfo.numOfChannels = 0;
5546 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005547 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
5548 {
5549 hdd_select_cbmode(pAdapter,operatingChannel);
5550 }
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005551 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
5552 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305553 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005554 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005555 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
5556 */
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305557 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5558 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005559 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
5560 eConnectionState_Connecting);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305561
5562 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005563 pAdapter->sessionId, pRoamProfile, &roamId);
5564
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305565 if ((eHAL_STATUS_SUCCESS != status) &&
5566 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5567 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305568
5569 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005570 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
5571 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
5572 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305573 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005574 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305575 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005576
5577 pRoamProfile->ChannelInfo.ChannelList = NULL;
5578 pRoamProfile->ChannelInfo.numOfChannels = 0;
5579
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 }
5581 else
5582 {
5583 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
5584 return -EINVAL;
5585 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005586 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 return status;
5588}
5589
5590/*
5591 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
5592 * This function is used to set the authentication type (OPEN/SHARED).
5593 *
5594 */
5595static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
5596 enum nl80211_auth_type auth_type)
5597{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305598 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005599 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5600
5601 ENTER();
5602
5603 /*set authentication type*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305604 switch (auth_type)
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005606 case NL80211_AUTHTYPE_AUTOMATIC:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305607 hddLog(VOS_TRACE_LEVEL_INFO,
5608 "%s: set authentication type to AUTOSWITCH", __func__);
5609 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
5610 break;
5611
5612 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07005613#ifdef WLAN_FEATURE_VOWIFI_11R
5614 case NL80211_AUTHTYPE_FT:
5615#endif /* WLAN_FEATURE_VOWIFI_11R */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305616 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005617 "%s: set authentication type to OPEN", __func__);
5618 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5619 break;
5620
5621 case NL80211_AUTHTYPE_SHARED_KEY:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305622 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 "%s: set authentication type to SHARED", __func__);
5624 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
5625 break;
5626#ifdef FEATURE_WLAN_CCX
5627 case NL80211_AUTHTYPE_NETWORK_EAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305628 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005629 "%s: set authentication type to CCKM WPA", __func__);
5630 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
5631 break;
5632#endif
5633
5634
5635 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305636 hddLog(VOS_TRACE_LEVEL_ERROR,
5637 "%s: Unsupported authentication type %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005638 auth_type);
5639 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
5640 return -EINVAL;
5641 }
5642
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305643 pWextState->roamProfile.AuthType.authType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005644 pHddStaCtx->conn_info.authType;
5645 return 0;
5646}
5647
5648/*
5649 * FUNCTION: wlan_hdd_set_akm_suite
5650 * This function is used to set the key mgmt type(PSK/8021x).
5651 *
5652 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305653static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005654 u32 key_mgmt
5655 )
5656{
5657 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5658 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305659
Jeff Johnson295189b2012-06-20 16:38:30 -07005660 /*set key mgmt type*/
5661 switch(key_mgmt)
5662 {
5663 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305664#ifdef WLAN_FEATURE_VOWIFI_11R
5665 case WLAN_AKM_SUITE_FT_PSK:
5666#endif
5667 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005668 __func__);
5669 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5670 break;
5671
5672 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305673#ifdef WLAN_FEATURE_VOWIFI_11R
5674 case WLAN_AKM_SUITE_FT_8021X:
5675#endif
5676 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005677 __func__);
5678 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5679 break;
5680#ifdef FEATURE_WLAN_CCX
5681#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5682#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5683 case WLAN_AKM_SUITE_CCKM:
5684 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5685 __func__);
5686 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5687 break;
5688#endif
5689
5690 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305691 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005692 __func__, key_mgmt);
5693 return -EINVAL;
5694
5695 }
5696 return 0;
5697}
5698
5699/*
5700 * FUNCTION: wlan_hdd_cfg80211_set_cipher
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305701 * This function is used to set the encryption type
Jeff Johnson295189b2012-06-20 16:38:30 -07005702 * (NONE/WEP40/WEP104/TKIP/CCMP).
5703 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305704static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5705 u32 cipher,
Jeff Johnson295189b2012-06-20 16:38:30 -07005706 bool ucast
5707 )
5708{
5709 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305710 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005711 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5712
5713 ENTER();
5714
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305715 if (!cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005716 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305717 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
Jeff Johnson295189b2012-06-20 16:38:30 -07005718 __func__, cipher);
5719 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5720 }
5721 else
5722 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305723
Jeff Johnson295189b2012-06-20 16:38:30 -07005724 /*set encryption method*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305725 switch (cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005726 {
5727 case IW_AUTH_CIPHER_NONE:
5728 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5729 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305730
Jeff Johnson295189b2012-06-20 16:38:30 -07005731 case WLAN_CIPHER_SUITE_WEP40:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305732 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson295189b2012-06-20 16:38:30 -07005733 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305734
Jeff Johnson295189b2012-06-20 16:38:30 -07005735 case WLAN_CIPHER_SUITE_WEP104:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305736 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305738
Jeff Johnson295189b2012-06-20 16:38:30 -07005739 case WLAN_CIPHER_SUITE_TKIP:
5740 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5741 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305742
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 case WLAN_CIPHER_SUITE_CCMP:
5744 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5745 break;
5746#ifdef FEATURE_WLAN_WAPI
5747 case WLAN_CIPHER_SUITE_SMS4:
5748 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5749 break;
5750#endif
5751
5752#ifdef FEATURE_WLAN_CCX
5753 case WLAN_CIPHER_SUITE_KRK:
5754 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5755 break;
5756#endif
5757 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305758 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 __func__, cipher);
5760 return -EOPNOTSUPP;
5761 }
5762 }
5763
5764 if (ucast)
5765 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305766 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005767 __func__, encryptionType);
5768 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5769 pWextState->roamProfile.EncryptionType.numEntries = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305770 pWextState->roamProfile.EncryptionType.encryptionType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005771 encryptionType;
5772 }
5773 else
5774 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305775 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005776 __func__, encryptionType);
5777 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5778 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5779 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5780 }
5781
5782 return 0;
5783}
5784
5785
5786/*
5787 * FUNCTION: wlan_hdd_cfg80211_set_ie
5788 * This function is used to parse WPA/RSN IE's.
5789 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305790int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5791 u8 *ie,
Jeff Johnson295189b2012-06-20 16:38:30 -07005792 size_t ie_len
5793 )
5794{
5795 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5796 u8 *genie = ie;
5797 v_U16_t remLen = ie_len;
5798#ifdef FEATURE_WLAN_WAPI
5799 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5800 u16 *tmp;
5801 v_U16_t akmsuiteCount;
5802 int *akmlist;
5803#endif
5804 ENTER();
5805
5806 /* clear previous assocAddIE */
5807 pWextState->assocAddIE.length = 0;
5808 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5809
5810 while (remLen >= 2)
5811 {
5812 v_U16_t eLen = 0;
5813 v_U8_t elementId;
5814 elementId = *genie++;
5815 eLen = *genie++;
5816 remLen -= 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305817
Arif Hussain6d2a3322013-11-17 19:50:10 -08005818 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005819 __func__, elementId, eLen);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305820
5821 switch ( elementId )
Jeff Johnson295189b2012-06-20 16:38:30 -07005822 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305823 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005824 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 -07005825 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305826 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 "%s: Invalid WPA IE", __func__);
5828 return -EINVAL;
5829 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305830 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 {
5832 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305833 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005834 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305835
Jeff Johnson295189b2012-06-20 16:38:30 -07005836 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5837 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005838 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5839 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 VOS_ASSERT(0);
5841 return -ENOMEM;
5842 }
5843 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5844 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5845 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305846
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5848 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5849 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5850 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305851 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5852 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5854 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5855 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5856 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5857 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5858 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305859 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
Kiet Lam8da98992013-11-21 15:59:07 +05305860 P2P_OUI_TYPE_SIZE)))
Jeff Johnson295189b2012-06-20 16:38:30 -07005861 {
5862 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305863 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005864 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305865
Jeff Johnson295189b2012-06-20 16:38:30 -07005866 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5867 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005868 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5869 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005870 VOS_ASSERT(0);
5871 return -ENOMEM;
5872 }
5873 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5874 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5875 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305876
Jeff Johnson295189b2012-06-20 16:38:30 -07005877 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5878 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5879 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005880#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305881 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5882 WFD_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005883 /*Consider WFD IE, only for P2P Client */
5884 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5885 {
5886 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305887 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305889
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5891 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005892 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5893 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005894 VOS_ASSERT(0);
5895 return -ENOMEM;
5896 }
5897 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5898 // WPS IE + P2P IE + WFD IE
5899 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5900 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305901
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5903 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5904 }
5905#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005906 /* Appending HS 2.0 Indication Element in Assiciation Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305907 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005908 HS20_OUI_TYPE_SIZE)) )
5909 {
5910 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305911 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005912 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005913
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005914 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5915 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005916 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5917 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005918 VOS_ASSERT(0);
5919 return -ENOMEM;
5920 }
5921 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5922 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005923
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005924 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5925 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5926 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005927
Praveen Kumar Sirisilla7d68b7b2013-09-22 14:01:42 -07005928 if (WLAN_HDD_IBSS == pAdapter->device_mode) {
5929
5930 /* populating as ADDIE in beacon frames */
5931 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5932 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie - 2, eLen + 2,
5933 NULL, eANI_BOOLEAN_FALSE)== eHAL_STATUS_SUCCESS)
5934 {
5935 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5936 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5937 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5938 {
5939 hddLog(LOGE,
5940 "Coldn't pass "
5941 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
5942 }
5943 }/* ccmCfgSetStr(,WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, , )*/
5944 else
5945 hddLog(LOGE,
5946 "Could not pass on "
5947 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
5948
5949 /* IBSS mode doesn't contain params->proberesp_ies still
5950 beaconIE's need to be populated in probe response frames */
5951 if ( (NULL != (genie - 2)) && (0 != eLen + 2) )
5952 {
5953 u16 rem_probe_resp_ie_len = eLen + 2;
5954 u8 probe_rsp_ie_len[3] = {0};
5955 u8 counter = 0;
5956
5957 /* Check Probe Resp Length if it is greater then 255 then
5958 Store Probe Rsp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1
5959 & WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are
5960 not able Store More then 255 bytes into One Variable */
5961
5962 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
5963 {
5964 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
5965 {
5966 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
5967 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
5968 }
5969 else
5970 {
5971 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
5972 rem_probe_resp_ie_len = 0;
5973 }
5974 }
5975
5976 rem_probe_resp_ie_len = 0;
5977
5978 if (probe_rsp_ie_len[0] > 0)
5979 {
5980 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5981 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5982 (tANI_U8*)(genie - 2),
5983 probe_rsp_ie_len[0], NULL,
5984 eANI_BOOLEAN_FALSE)
5985 == eHAL_STATUS_FAILURE)
5986 {
5987 hddLog(LOGE,
5988 "Could not pass"
5989 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
5990 }
5991 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
5992 }
5993
5994 if (probe_rsp_ie_len[1] > 0)
5995 {
5996 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5997 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
5998 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
5999 probe_rsp_ie_len[1], NULL,
6000 eANI_BOOLEAN_FALSE)
6001 == eHAL_STATUS_FAILURE)
6002 {
6003 hddLog(LOGE,
6004 "Could not pass"
6005 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
6006 }
6007 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
6008 }
6009
6010 if (probe_rsp_ie_len[2] > 0)
6011 {
6012 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
6013 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
6014 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
6015 probe_rsp_ie_len[2], NULL,
6016 eANI_BOOLEAN_FALSE)
6017 == eHAL_STATUS_FAILURE)
6018 {
6019 hddLog(LOGE,
6020 "Could not pass"
6021 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
6022 }
6023 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
6024 }
6025
6026 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
6027 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
6028 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
6029 {
6030 hddLog(LOGE,
6031 "Could not pass"
6032 "on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
6033 }
6034 }
6035 else
6036 {
6037 // Reset WNI_CFG_PROBE_RSP Flags
6038 wlan_hdd_reset_prob_rspies(pAdapter);
6039
6040 hddLog(VOS_TRACE_LEVEL_INFO,
6041 "%s: No Probe Response IE received in set beacon",
6042 __func__);
6043 }
6044 } /* end of if (WLAN_HDD_IBSS == pAdapter->device_mode) */
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 break;
6046 case DOT11F_EID_RSN:
6047 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
6048 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
6049 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
6050 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
6051 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
6052 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006053 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
6054 case DOT11F_EID_EXTCAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306055 {
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006056 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306057 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006058 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306059
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006060 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
6061 {
Jeff Johnson902c9832012-12-10 14:28:09 -08006062 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
6063 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006064 VOS_ASSERT(0);
6065 return -ENOMEM;
6066 }
6067 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
6068 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306069
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006070 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
6071 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
6072 break;
6073 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006074#ifdef FEATURE_WLAN_WAPI
6075 case WLAN_EID_WAPI:
6076 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006077 hddLog(VOS_TRACE_LEVEL_INFO, "WAPI MODE IS %u",
Jeff Johnson295189b2012-06-20 16:38:30 -07006078 pAdapter->wapi_info.nWapiMode);
6079 tmp = (u16 *)ie;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306080 tmp = tmp + 2; // Skip element Id and Len, Version
Jeff Johnson295189b2012-06-20 16:38:30 -07006081 akmsuiteCount = WPA_GET_LE16(tmp);
6082 tmp = tmp + 1;
6083 akmlist = (int *)(tmp);
6084 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
6085 {
6086 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
6087 }
6088 else
6089 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006090 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count");
Jeff Johnson295189b2012-06-20 16:38:30 -07006091 VOS_ASSERT(0);
6092 return -EINVAL;
6093 }
6094
6095 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
6096 {
6097 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006098 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006099 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306100 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006101 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306102 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006103 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006104 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006105 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
6106 }
6107 break;
6108#endif
6109 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306110 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006112 /* when Unknown IE is received we should break and continue
6113 * to the next IE in the buffer instead we were returning
6114 * so changing this to break */
6115 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006116 }
6117 genie += eLen;
6118 remLen -= eLen;
6119 }
6120 EXIT();
6121 return 0;
6122}
6123
6124/*
Gopichand Nakkala18f0c262013-05-07 23:25:08 +05306125 * FUNCTION: hdd_isWPAIEPresent
6126 * Parse the received IE to find the WPA IE
6127 *
6128 */
6129static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len)
6130{
6131 v_U8_t eLen = 0;
6132 v_U16_t remLen = ie_len;
6133 v_U8_t elementId = 0;
6134
6135 while (remLen >= 2)
6136 {
6137 elementId = *ie++;
6138 eLen = *ie++;
6139 remLen -= 2;
6140 if (eLen > remLen)
6141 {
6142 hddLog(VOS_TRACE_LEVEL_ERROR,
6143 "%s: IE length is wrong %d", __func__, eLen);
6144 return FALSE;
6145 }
6146 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
6147 {
6148 /* OUI - 0x00 0X50 0XF2
6149 WPA Information Element - 0x01
6150 WPA version - 0x01*/
6151 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
6152 return TRUE;
6153 }
6154 ie += eLen;
6155 remLen -= eLen;
6156 }
6157 return FALSE;
6158}
6159
6160/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006161 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306162 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 * parameters during connect operation.
6164 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306165int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07006166 struct cfg80211_connect_params *req
6167 )
6168{
6169 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306170 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006171 ENTER();
6172
6173 /*set wpa version*/
6174 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
6175
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306176 if (req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07006177 {
Gopichand Nakkala781ded42013-06-28 12:10:45 +05306178 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07006179 {
6180 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
6181 }
6182 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
6183 {
6184 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
6185 }
6186 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306187
6188 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006189 pWextState->wpaVersion);
6190
6191 /*set authentication type*/
6192 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
6193
6194 if (0 > status)
6195 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306196 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006197 "%s: failed to set authentication type ", __func__);
6198 return status;
6199 }
6200
6201 /*set key mgmt type*/
6202 if (req->crypto.n_akm_suites)
6203 {
6204 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
6205 if (0 > status)
6206 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306207 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
Jeff Johnson295189b2012-06-20 16:38:30 -07006208 __func__);
6209 return status;
6210 }
6211 }
6212
6213 /*set pairwise cipher type*/
6214 if (req->crypto.n_ciphers_pairwise)
6215 {
6216 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
6217 req->crypto.ciphers_pairwise[0], true);
6218 if (0 > status)
6219 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306220 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006221 "%s: failed to set unicast cipher type", __func__);
6222 return status;
6223 }
6224 }
6225 else
6226 {
6227 /*Reset previous cipher suite to none*/
6228 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
6229 if (0 > status)
6230 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306231 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006232 "%s: failed to set unicast cipher type", __func__);
6233 return status;
6234 }
6235 }
6236
6237 /*set group cipher type*/
6238 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
6239 false);
6240
6241 if (0 > status)
6242 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306243 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
Jeff Johnson295189b2012-06-20 16:38:30 -07006244 __func__);
6245 return status;
6246 }
6247
Chet Lanctot186b5732013-03-18 10:26:30 -07006248#ifdef WLAN_FEATURE_11W
6249 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
6250#endif
6251
Jeff Johnson295189b2012-06-20 16:38:30 -07006252 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
6253 if (req->ie_len)
6254 {
6255 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
6256 if ( 0 > status)
6257 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306258 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006259 __func__);
6260 return status;
6261 }
6262 }
6263
6264 /*incase of WEP set default key information*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306265 if (req->key && req->key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07006266 {
6267 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
6268 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
6269 )
6270 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306271 if ( IW_AUTH_KEY_MGMT_802_1X
Jeff Johnson295189b2012-06-20 16:38:30 -07006272 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
6273 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306274 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07006275 __func__);
6276 return -EOPNOTSUPP;
6277 }
6278 else
6279 {
6280 u8 key_len = req->key_len;
6281 u8 key_idx = req->key_idx;
6282
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306283 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07006284 && (CSR_MAX_NUM_KEY > key_idx)
6285 )
6286 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306287 hddLog(VOS_TRACE_LEVEL_INFO,
6288 "%s: setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006289 __func__, key_idx, key_len);
6290 vos_mem_copy(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306291 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07006292 req->key, key_len);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306293 pWextState->roamProfile.Keys.KeyLength[key_idx] =
Jeff Johnson295189b2012-06-20 16:38:30 -07006294 (u8)key_len;
6295 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
6296 }
6297 }
6298 }
6299 }
6300
6301 return status;
6302}
6303
6304/*
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306305 * FUNCTION: wlan_hdd_try_disconnect
6306 * This function is used to disconnect from previous
6307 * connection
6308 */
6309static int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter )
6310{
6311 long ret = 0;
6312 hdd_station_ctx_t *pHddStaCtx;
6313 eMib_dot11DesiredBssType connectedBssType;
6314
6315 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6316
6317 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
6318
6319 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
6320 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
6321 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
6322 {
6323 /* Issue disconnect to CSR */
6324 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6325 if( eHAL_STATUS_SUCCESS ==
6326 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
6327 pAdapter->sessionId,
6328 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
6329 {
6330 ret = wait_for_completion_interruptible_timeout(
6331 &pAdapter->disconnect_comp_var,
6332 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6333 if (0 >= ret)
6334 {
6335 hddLog(LOGE, FL("Failed to receive disconnect event"));
6336 return -EALREADY;
6337 }
6338 }
6339 }
6340 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
6341 {
6342 ret = wait_for_completion_interruptible_timeout(
6343 &pAdapter->disconnect_comp_var,
6344 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6345 if (0 >= ret)
6346 {
6347 hddLog(LOGE, FL("Failed to receive disconnect event"));
6348 return -EALREADY;
6349 }
6350 }
6351
6352 return 0;
6353}
6354
6355/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006356 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306357 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006358 * parameters during connect operation.
6359 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306360static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006361 struct net_device *ndev,
6362 struct cfg80211_connect_params *req
6363 )
6364{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306365 int status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306366 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006367 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006368 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006369
6370 ENTER();
6371
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006372 if (!pAdapter)
6373 {
6374 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6375 "%s: Adapter context is null", __func__);
6376 return VOS_STATUS_E_FAILURE;
6377 }
6378
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306379 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006380 "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006381
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306382 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006383 if (!pHddCtx)
6384 {
6385 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6386 "%s: HDD context is null", __func__);
6387 return VOS_STATUS_E_FAILURE;
6388 }
6389
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306390 status = wlan_hdd_validate_context(pHddCtx);
6391
6392 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006393 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306394 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6395 "%s: HDD context is not valid", __func__);
6396 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006397 }
6398
6399#ifdef WLAN_BTAMP_FEATURE
6400 //Infra connect not supported when AMP traffic is on.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306401 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07006402 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306403 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006404 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006405 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07006406 }
6407#endif
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306408
6409 //If Device Mode is Station Concurrent Sessions Exit BMps
6410 //P2P Mode will be taken care in Open/close adapter
6411 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
6412 (vos_concurrent_sessions_running()))
6413 {
6414 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
6415 }
6416
6417 /*Try disconnecting if already in connected state*/
6418 status = wlan_hdd_try_disconnect(pAdapter);
6419 if ( 0 > status)
6420 {
6421 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
6422 " connection"));
6423 return -EALREADY;
6424 }
6425
Jeff Johnson295189b2012-06-20 16:38:30 -07006426 /*initialise security parameters*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306427 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
Jeff Johnson295189b2012-06-20 16:38:30 -07006428
6429 if ( 0 > status)
6430 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306431 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
Jeff Johnson295189b2012-06-20 16:38:30 -07006432 __func__);
6433 return status;
6434 }
6435
Mohit Khanna765234a2012-09-11 15:08:35 -07006436 if ( req->channel )
6437 {
6438 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
6439 req->ssid_len, req->bssid,
6440 req->channel->hw_value);
6441 }
6442 else
6443 {
6444 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306445 req->ssid_len, req->bssid, 0);
Mohit Khanna765234a2012-09-11 15:08:35 -07006446 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006447
6448 if (0 > status)
6449 {
6450 //ReEnable BMPS if disabled
6451 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
6452 (NULL != pHddCtx))
6453 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306454 if (pHddCtx->hdd_wlan_suspended)
6455 {
6456 hdd_set_pwrparams(pHddCtx);
6457 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006458 //ReEnable Bmps and Imps back
6459 hdd_enable_bmps_imps(pHddCtx);
6460 }
6461
6462 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6463 return status;
6464 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306465 pHddCtx->isAmpAllowed = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006466 EXIT();
6467 return status;
6468}
6469
6470
6471/*
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306472 * FUNCTION: wlan_hdd_disconnect
6473 * This function is used to issue a disconnect request to SME
6474 */
6475int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
6476{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306477 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306478 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306479 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306480 long ret;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306481
6482 status = wlan_hdd_validate_context(pHddCtx);
6483
6484 if (0 != status)
6485 {
6486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6487 "%s: HDD context is not valid", __func__);
6488 return status;
6489 }
6490
6491 pHddCtx->isAmpAllowed = VOS_TRUE;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306492 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306493 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306494
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306495 /*issue disconnect*/
6496 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
6497 pAdapter->sessionId, reason);
6498
6499 if ( 0 != status )
6500 {
6501 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006502 "%s csrRoamDisconnect failure, returned %d",
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306503 __func__, (int)status );
6504 return -EINVAL;
6505 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306506 ret = wait_for_completion_interruptible_timeout(
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306507 &pAdapter->disconnect_comp_var,
6508 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306509 if (ret <= 0)
6510 {
6511 hddLog(VOS_TRACE_LEVEL_ERROR,
6512 FL("wait on disconnect_comp_var failed %ld"), ret);
6513 }
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306514 /*stop tx queues*/
6515 netif_tx_disable(pAdapter->dev);
6516 netif_carrier_off(pAdapter->dev);
6517 return status;
6518}
6519
6520
6521/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006522 * FUNCTION: wlan_hdd_cfg80211_disconnect
6523 * This function is used to issue a disconnect request to SME
6524 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306525static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006526 struct net_device *dev,
6527 u16 reason
6528 )
6529{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306530 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6531 tCsrRoamProfile *pRoamProfile =
Jeff Johnson295189b2012-06-20 16:38:30 -07006532 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306533 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006534 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006535 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306536#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006537 tANI_U8 staIdx;
6538#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306539
Jeff Johnson295189b2012-06-20 16:38:30 -07006540 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306541
Arif Hussain6d2a3322013-11-17 19:50:10 -08006542 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006543 __func__,pAdapter->device_mode);
6544
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306545 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
6546 __func__, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07006547
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306548 status = wlan_hdd_validate_context(pHddCtx);
6549
6550 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006551 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6553 "%s: HDD context is not valid", __func__);
6554 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006555 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306556
Jeff Johnson295189b2012-06-20 16:38:30 -07006557 if (NULL != pRoamProfile)
6558 {
6559 /*issue disconnect request to SME, if station is in connected state*/
Mahesh A Saptasagar280fd5a2013-12-05 15:38:31 +05306560 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
6561 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting))
Jeff Johnson295189b2012-06-20 16:38:30 -07006562 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306563 eCsrRoamDisconnectReason reasonCode =
Jeff Johnson295189b2012-06-20 16:38:30 -07006564 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306565 hdd_scaninfo_t *pScanInfo;
Jeff Johnson295189b2012-06-20 16:38:30 -07006566 switch(reason)
6567 {
6568 case WLAN_REASON_MIC_FAILURE:
6569 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
6570 break;
6571
6572 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
6573 case WLAN_REASON_DISASSOC_AP_BUSY:
6574 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
6575 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
6576 break;
6577
6578 case WLAN_REASON_PREV_AUTH_NOT_VALID:
6579 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
6580 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
6581 break;
6582
6583 case WLAN_REASON_DEAUTH_LEAVING:
6584 default:
6585 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
6586 break;
6587 }
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306588 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6589 pScanInfo = &pHddCtx->scan_info;
6590 if (pScanInfo->mScanPending)
6591 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306592 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306593 "Aborting Scan");
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306594 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6595 eCSR_SCAN_ABORT_DEFAULT);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306596 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006597
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006598#ifdef FEATURE_WLAN_TDLS
6599 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006600 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006601 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006602 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
6603 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006604 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006605 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006606 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006607 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006608 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006609 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006610 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006611 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006612 pAdapter->sessionId,
6613 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006614 }
6615 }
6616#endif
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306617 status = wlan_hdd_disconnect(pAdapter, reasonCode);
6618 if ( 0 != status )
Jeff Johnson295189b2012-06-20 16:38:30 -07006619 {
6620 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006621 "%s wlan_hdd_disconnect failure, returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006622 __func__, (int)status );
6623 return -EINVAL;
6624 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006625 }
Mahesh A Saptasagar280fd5a2013-12-05 15:38:31 +05306626 else
6627 {
6628 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unexpected cfg disconnect API"
6629 "called while in %d state", __func__,
6630 pHddStaCtx->conn_info.connState);
6631 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006632 }
6633 else
6634 {
6635 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
6636 }
6637
6638 return status;
6639}
6640
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306641
Jeff Johnson295189b2012-06-20 16:38:30 -07006642/*
6643 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306644 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006645 * settings in IBSS mode.
6646 */
6647static int wlan_hdd_cfg80211_set_privacy_ibss(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306648 hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07006649 struct cfg80211_ibss_params *params
6650 )
6651{
6652 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306653 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006654 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
6655 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306656
Jeff Johnson295189b2012-06-20 16:38:30 -07006657 ENTER();
6658
6659 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Ravi Joshib58ca0d2013-10-29 09:50:23 -07006660 vos_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -07006661
6662 if (params->ie_len && ( NULL != params->ie) )
6663 {
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006664 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6665 params->ie_len, WLAN_EID_RSN ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006666 {
6667 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
6668 encryptionType = eCSR_ENCRYPT_TYPE_AES;
6669 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006670 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006671 {
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006672 tDot11fIEWPA dot11WPAIE;
6673 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006674 u8 *ie;
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006675
Wilson Yang00256342013-10-10 23:13:38 -07006676 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006677 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6678 params->ie_len, DOT11F_EID_WPA);
6679 if ( NULL != ie )
6680 {
6681 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
6682 // Unpack the WPA IE
6683 //Skip past the EID byte and length byte - and four byte WiFi OUI
6684 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
6685 &ie[2+4],
6686 ie[1] - 4,
6687 &dot11WPAIE);
6688 /*Extract the multicast cipher, the encType for unicast
6689 cipher for wpa-none is none*/
6690 encryptionType =
6691 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
6692 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006693 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006694
Jeff Johnson295189b2012-06-20 16:38:30 -07006695 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
6696
6697 if (0 > status)
6698 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306699 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006700 __func__);
6701 return status;
6702 }
6703 }
6704
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306705 pWextState->roamProfile.AuthType.authType[0] =
6706 pHddStaCtx->conn_info.authType =
Jeff Johnson295189b2012-06-20 16:38:30 -07006707 eCSR_AUTH_TYPE_OPEN_SYSTEM;
6708
6709 if (params->privacy)
6710 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306711 /* Security enabled IBSS, At this time there is no information available
6712 * about the security paramters, so initialise the encryption type to
Jeff Johnson295189b2012-06-20 16:38:30 -07006713 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306714 * The correct security parameters will be updated later in
Jeff Johnson295189b2012-06-20 16:38:30 -07006715 * wlan_hdd_cfg80211_add_key */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306716 /* Hal expects encryption type to be set inorder
Jeff Johnson295189b2012-06-20 16:38:30 -07006717 *enable privacy bit in beacons */
6718
6719 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6720 }
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006721 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6722 "encryptionType=%d", encryptionType);
Jeff Johnson295189b2012-06-20 16:38:30 -07006723 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
6724 pWextState->roamProfile.EncryptionType.numEntries = 1;
6725 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
Jeff Johnson295189b2012-06-20 16:38:30 -07006726 return status;
6727}
6728
6729/*
6730 * FUNCTION: wlan_hdd_cfg80211_join_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306731 * This function is used to create/join an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006732 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306733static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006734 struct net_device *dev,
6735 struct cfg80211_ibss_params *params
6736 )
6737{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306738 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006739 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6740 tCsrRoamProfile *pRoamProfile;
6741 int status;
krunal sonie9002db2013-11-25 14:24:17 -08006742 bool alloc_bssid = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006743 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306744 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006745
6746 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306747
6748 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006749 "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006750
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306751 status = wlan_hdd_validate_context(pHddCtx);
6752
6753 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006754 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6756 "%s: HDD context is not valid", __func__);
6757 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006758 }
6759
6760 if (NULL == pWextState)
6761 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006762 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
Jeff Johnson295189b2012-06-20 16:38:30 -07006763 __func__);
6764 return -EIO;
6765 }
6766
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306767 /*Try disconnecting if already in connected state*/
6768 status = wlan_hdd_try_disconnect(pAdapter);
6769 if ( 0 > status)
6770 {
6771 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
6772 " IBSS connection"));
6773 return -EALREADY;
6774 }
6775
Jeff Johnson295189b2012-06-20 16:38:30 -07006776 pRoamProfile = &pWextState->roamProfile;
6777
6778 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
6779 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306780 hddLog (VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006781 "%s Interface type is not set to IBSS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006782 return -EINVAL;
6783 }
6784
Praveen Kumar Sirisillad123d142013-09-24 16:50:13 -07006785 /* BSSID is provided by upper layers hence no need to AUTO generate */
6786 if (NULL != params->bssid) {
6787 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
6788 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) {
6789 hddLog (VOS_TRACE_LEVEL_ERROR,
6790 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
6791 return -EIO;
6792 }
6793 }
krunal sonie9002db2013-11-25 14:24:17 -08006794 else if(pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0)
6795 {
6796 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
6797 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
6798 {
6799 hddLog (VOS_TRACE_LEVEL_ERROR,
6800 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
6801 return -EIO;
6802 }
6803 params->bssid = vos_mem_malloc(sizeof(VOS_MAC_ADDR_SIZE));
6804 if (!params->bssid)
6805 {
6806 hddLog (VOS_TRACE_LEVEL_ERROR,
6807 "%s:Failed memory allocation", __func__);
6808 return -EIO;
6809 }
6810 vos_mem_copy((v_U8_t *)params->bssid,
6811 (v_U8_t *)&pHddCtx->cfg_ini->IbssBssid.bytes[0],
6812 VOS_MAC_ADDR_SIZE);
6813 alloc_bssid = VOS_TRUE;
6814 }
Praveen Kumar Sirisillad123d142013-09-24 16:50:13 -07006815
Jeff Johnson295189b2012-06-20 16:38:30 -07006816 /* Set Channel */
Yue Maf49ba872013-08-19 12:04:25 -07006817 if (NULL !=
6818#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6819 params->chandef.chan)
6820#else
6821 params->channel)
6822#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006823 {
6824 u8 channelNum;
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006825 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6826 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6827 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6828 int indx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006829
6830 /* Get channel number */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306831 channelNum =
Yue Maf49ba872013-08-19 12:04:25 -07006832 ieee80211_frequency_to_channel(
6833#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6834 params->chandef.chan->center_freq);
6835#else
6836 params->channel->center_freq);
6837#endif
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006838
6839 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6840 validChan, &numChans))
Jeff Johnson295189b2012-06-20 16:38:30 -07006841 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006842 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
6843 __func__);
6844 return -EOPNOTSUPP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006845 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006846
6847 for (indx = 0; indx < numChans; indx++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006848 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006849 if (channelNum == validChan[indx])
6850 {
6851 break;
6852 }
6853 }
6854 if (indx >= numChans)
6855 {
6856 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006857 __func__, channelNum);
6858 return -EINVAL;
6859 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006860 /* Set the Operational Channel */
6861 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
6862 channelNum);
6863 pRoamProfile->ChannelInfo.numOfChannels = 1;
6864 pHddStaCtx->conn_info.operationChannel = channelNum;
6865 pRoamProfile->ChannelInfo.ChannelList =
6866 &pHddStaCtx->conn_info.operationChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -07006867 }
6868
6869 /* Initialize security parameters */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306870 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
Jeff Johnson295189b2012-06-20 16:38:30 -07006871 if (status < 0)
6872 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306873 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
Jeff Johnson295189b2012-06-20 16:38:30 -07006874 __func__);
6875 return status;
6876 }
6877
6878 /* Issue connect start */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306879 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006880 params->ssid_len, params->bssid,
6881 pHddStaCtx->conn_info.operationChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07006882
6883 if (0 > status)
6884 {
6885 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6886 return status;
6887 }
6888
krunal sonie9002db2013-11-25 14:24:17 -08006889 if (NULL != params->bssid &&
6890 pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0 &&
6891 alloc_bssid == VOS_TRUE)
6892 {
6893 vos_mem_free(params->bssid);
6894 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006895 return 0;
6896}
6897
6898/*
6899 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306900 * This function is used to leave an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006901 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306902static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006903 struct net_device *dev
6904 )
6905{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306906 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006907 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6908 tCsrRoamProfile *pRoamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306909 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6910 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006911
6912 ENTER();
6913
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306914 status = wlan_hdd_validate_context(pHddCtx);
6915
6916 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006917 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6919 "%s: HDD context is not valid", __func__);
6920 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006921 }
6922
Arif Hussain6d2a3322013-11-17 19:50:10 -08006923 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006924 if (NULL == pWextState)
6925 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006926 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
Jeff Johnson295189b2012-06-20 16:38:30 -07006927 __func__);
6928 return -EIO;
6929 }
6930
6931 pRoamProfile = &pWextState->roamProfile;
6932
6933 /* Issue disconnect only if interface type is set to IBSS */
6934 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
6935 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306936 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
Jeff Johnson295189b2012-06-20 16:38:30 -07006937 __func__);
6938 return -EINVAL;
6939 }
6940
6941 /* Issue Disconnect request */
6942 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6943 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6944 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6945
6946 return 0;
6947}
6948
6949/*
6950 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
6951 * This function is used to set the phy parameters
6952 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
6953 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306954static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006955 u32 changed)
6956{
6957 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6958 tHalHandle hHal = pHddCtx->hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306959 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006960
6961 ENTER();
6962
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306963 status = wlan_hdd_validate_context(pHddCtx);
6964
6965 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006966 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6968 "%s: HDD context is not valid", __func__);
6969 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006970 }
6971
Jeff Johnson295189b2012-06-20 16:38:30 -07006972 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
6973 {
6974 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
6975 WNI_CFG_RTS_THRESHOLD_STAMAX :
6976 wiphy->rts_threshold;
6977
6978 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306979 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
Jeff Johnson295189b2012-06-20 16:38:30 -07006980 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306981 hddLog(VOS_TRACE_LEVEL_ERROR,
6982 "%s: Invalid RTS Threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006983 __func__, rts_threshold);
6984 return -EINVAL;
6985 }
6986
6987 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
6988 rts_threshold, 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 rts_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 __func__, rts_threshold);
6994 return -EIO;
6995 }
6996
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306997 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006998 rts_threshold);
6999 }
7000
7001 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
7002 {
7003 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
7004 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
7005 wiphy->frag_threshold;
7006
7007 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307008 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
Jeff Johnson295189b2012-06-20 16:38:30 -07007009 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307010 hddLog(VOS_TRACE_LEVEL_ERROR,
7011 "%s: Invalid frag_threshold value %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07007012 frag_threshold);
7013 return -EINVAL;
7014 }
7015
7016 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
7017 frag_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307018 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007019 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307020 hddLog(VOS_TRACE_LEVEL_ERROR,
7021 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007022 __func__, frag_threshold);
7023 return -EIO;
7024 }
7025
7026 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
7027 frag_threshold);
7028 }
7029
7030 if ((changed & WIPHY_PARAM_RETRY_SHORT)
7031 || (changed & WIPHY_PARAM_RETRY_LONG))
7032 {
7033 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
7034 wiphy->retry_short :
7035 wiphy->retry_long;
7036
7037 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
7038 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
7039 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307040 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007041 __func__, retry_value);
7042 return -EINVAL;
7043 }
7044
7045 if (changed & WIPHY_PARAM_RETRY_SHORT)
7046 {
7047 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
7048 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307049 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007050 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307051 hddLog(VOS_TRACE_LEVEL_ERROR,
7052 "%s: ccmCfgSetInt failed for long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007053 __func__, retry_value);
7054 return -EIO;
7055 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307056 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007057 __func__, retry_value);
7058 }
7059 else if (changed & WIPHY_PARAM_RETRY_SHORT)
7060 {
7061 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
7062 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307063 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007064 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307065 hddLog(VOS_TRACE_LEVEL_ERROR,
7066 "%s: ccmCfgSetInt failed for short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007067 __func__, retry_value);
7068 return -EIO;
7069 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307070 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007071 __func__, retry_value);
7072 }
7073 }
7074
7075 return 0;
7076}
7077
7078/*
7079 * FUNCTION: wlan_hdd_cfg80211_set_txpower
7080 * This function is used to set the txpower
7081 */
7082static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Yue Maf49ba872013-08-19 12:04:25 -07007083#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
7084 struct wireless_dev *wdev,
7085#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007086#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307087 enum tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07007088#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307089 enum nl80211_tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07007090#endif
7091 int dbm)
7092{
7093 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307094 tHalHandle hHal = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007095 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
7096 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307097 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007098
7099 ENTER();
7100
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307101 status = wlan_hdd_validate_context(pHddCtx);
7102
7103 if (0 != status)
7104 {
7105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7106 "%s: HDD context is not valid", __func__);
7107 return status;
7108 }
7109
7110 hHal = pHddCtx->hHal;
7111
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307112 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
7113 dbm, ccmCfgSetCallback,
7114 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007115 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307116 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007117 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
7118 return -EIO;
7119 }
7120
7121 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
7122 dbm);
7123
7124 switch(type)
7125 {
7126 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
7127 /* Fall through */
7128 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
7129 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
7130 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307131 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
7132 __func__);
7133 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007134 }
7135 break;
7136 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307137 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07007138 __func__);
7139 return -EOPNOTSUPP;
7140 break;
7141 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307142 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
7143 __func__, type);
Jeff Johnson295189b2012-06-20 16:38:30 -07007144 return -EIO;
7145 }
7146
7147 return 0;
7148}
7149
7150/*
7151 * FUNCTION: wlan_hdd_cfg80211_get_txpower
7152 * This function is used to read the txpower
7153 */
Yue Maf49ba872013-08-19 12:04:25 -07007154static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
7155#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
7156 struct wireless_dev *wdev,
7157#endif
7158 int *dbm)
Jeff Johnson295189b2012-06-20 16:38:30 -07007159{
7160
7161 hdd_adapter_t *pAdapter;
7162 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307163 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007164
Jeff Johnsone7245742012-09-05 17:12:55 -07007165 ENTER();
7166
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307167 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007168
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307169 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007170 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7172 "%s: HDD context is not valid", __func__);
7173 *dbm = 0;
7174 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007175 }
7176
Jeff Johnson295189b2012-06-20 16:38:30 -07007177 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
7178 if (NULL == pAdapter)
7179 {
7180 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
7181 return -ENOENT;
7182 }
7183
7184 wlan_hdd_get_classAstats(pAdapter);
7185 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
7186
Jeff Johnsone7245742012-09-05 17:12:55 -07007187 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007188 return 0;
7189}
7190
7191static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
7192 u8* mac, struct station_info *sinfo)
7193{
7194 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
7195 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7196 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
7197 tANI_U8 rate_flags;
7198
7199 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
7200 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07007201
7202 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
7203 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
7204 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
7205 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
7206 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
7207 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
7208 tANI_U16 maxRate = 0;
7209 tANI_U16 myRate;
7210 tANI_U16 currentRate = 0;
7211 tANI_U8 maxSpeedMCS = 0;
7212 tANI_U8 maxMCSIdx = 0;
7213 tANI_U8 rateFlag = 1;
7214 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07007215 tANI_U16 temp;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307216 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007217
Leo Chang6f8870f2013-03-26 18:11:36 -07007218#ifdef WLAN_FEATURE_11AC
7219 tANI_U32 vht_mcs_map;
7220 eDataRate11ACMaxMcs vhtMaxMcs;
7221#endif /* WLAN_FEATURE_11AC */
7222
Jeff Johnsone7245742012-09-05 17:12:55 -07007223 ENTER();
7224
Jeff Johnson295189b2012-06-20 16:38:30 -07007225 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
7226 (0 == ssidlen))
7227 {
7228 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
7229 " Invalid ssidlen, %d", __func__, ssidlen);
7230 /*To keep GUI happy*/
7231 return 0;
7232 }
7233
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307234 status = wlan_hdd_validate_context(pHddCtx);
7235
7236 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007237 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7239 "%s: HDD context is not valid", __func__);
7240 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007241 }
7242
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07007243 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007244 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
7245
Kiet Lam3b17fc82013-09-27 05:24:08 +05307246 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
7247 sinfo->filled |= STATION_INFO_SIGNAL;
7248
Jeff Johnson295189b2012-06-20 16:38:30 -07007249 //convert to the UI units of 100kbps
7250 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
7251
7252#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07007253 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 -07007254 sinfo->signal,
7255 pCfg->reportMaxLinkSpeed,
7256 myRate,
7257 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007258 (int) pCfg->linkSpeedRssiMid,
7259 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07007260 (int) rate_flags,
7261 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07007262#endif //LINKSPEED_DEBUG_ENABLED
7263
7264 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
7265 {
7266 // we do not want to necessarily report the current speed
7267 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
7268 {
7269 // report the max possible speed
7270 rssidx = 0;
7271 }
7272 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
7273 {
7274 // report the max possible speed with RSSI scaling
7275 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
7276 {
7277 // report the max possible speed
7278 rssidx = 0;
7279 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007280 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07007281 {
7282 // report middle speed
7283 rssidx = 1;
7284 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007285 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
7286 {
7287 // report middle speed
7288 rssidx = 2;
7289 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007290 else
7291 {
7292 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007293 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07007294 }
7295 }
7296 else
7297 {
7298 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
7299 hddLog(VOS_TRACE_LEVEL_ERROR,
7300 "%s: Invalid value for reportMaxLinkSpeed: %u",
7301 __func__, pCfg->reportMaxLinkSpeed);
7302 rssidx = 0;
7303 }
7304
7305 maxRate = 0;
7306
7307 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307308 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
7309 OperationalRates, &ORLeng))
7310 {
7311 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7312 /*To keep GUI happy*/
7313 return 0;
7314 }
7315
Jeff Johnson295189b2012-06-20 16:38:30 -07007316 for (i = 0; i < ORLeng; i++)
7317 {
Jeff Johnsone7245742012-09-05 17:12:55 -07007318 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07007319 {
7320 /* Validate Rate Set */
7321 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
7322 {
7323 currentRate = supported_data_rate[j].supported_rate[rssidx];
7324 break;
7325 }
7326 }
7327 /* Update MAX rate */
7328 maxRate = (currentRate > maxRate)?currentRate:maxRate;
7329 }
7330
7331 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307332 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
7333 ExtendedRates, &ERLeng))
7334 {
7335 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7336 /*To keep GUI happy*/
7337 return 0;
7338 }
7339
Jeff Johnson295189b2012-06-20 16:38:30 -07007340 for (i = 0; i < ERLeng; i++)
7341 {
Jeff Johnsone7245742012-09-05 17:12:55 -07007342 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07007343 {
7344 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
7345 {
7346 currentRate = supported_data_rate[j].supported_rate[rssidx];
7347 break;
7348 }
7349 }
7350 /* Update MAX rate */
7351 maxRate = (currentRate > maxRate)?currentRate:maxRate;
7352 }
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307353 /* Get MCS Rate Set --
Kaushik, Sushantdc304d82014-01-22 10:58:37 +05307354 Only if we are always reporting max speed (or)
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307355 if we have good rssi */
Kaushik, Sushantdc304d82014-01-22 10:58:37 +05307356 if ((0 == rssidx) ||
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307357 (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed))
Jeff Johnson295189b2012-06-20 16:38:30 -07007358 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307359 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
7360 MCSRates, &MCSLeng))
7361 {
7362 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7363 /*To keep GUI happy*/
7364 return 0;
7365 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007366 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07007367#ifdef WLAN_FEATURE_11AC
7368 /* VHT80 rate has seperate rate table */
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307369 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
Jeff Johnson295189b2012-06-20 16:38:30 -07007370 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007371 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307372 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
Leo Chang6f8870f2013-03-26 18:11:36 -07007373 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07007374 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007375 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07007376 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007377 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07007378 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007379 maxMCSIdx = 7;
7380 }
7381 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
7382 {
7383 maxMCSIdx = 8;
7384 }
7385 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
7386 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307387 //VHT20 is supporting 0~8
7388 if (rate_flags & eHAL_TX_RATE_VHT20)
7389 maxMCSIdx = 8;
7390 else
7391 maxMCSIdx = 9;
Leo Chang6f8870f2013-03-26 18:11:36 -07007392 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307393
7394 if (rate_flags & eHAL_TX_RATE_VHT80)
7395 {
7396 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
7397 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
7398 }
7399 else if (rate_flags & eHAL_TX_RATE_VHT40)
7400 {
7401 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
7402 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
7403 }
7404 else if (rate_flags & eHAL_TX_RATE_VHT20)
7405 {
7406 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
7407 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
7408 }
7409
Leo Chang6f8870f2013-03-26 18:11:36 -07007410 maxSpeedMCS = 1;
7411 if (currentRate > maxRate)
7412 {
7413 maxRate = currentRate;
7414 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307415
Leo Chang6f8870f2013-03-26 18:11:36 -07007416 }
7417 else
7418#endif /* WLAN_FEATURE_11AC */
7419 {
7420 if (rate_flags & eHAL_TX_RATE_HT40)
7421 {
7422 rateFlag |= 1;
7423 }
7424 if (rate_flags & eHAL_TX_RATE_SGI)
7425 {
7426 rateFlag |= 2;
7427 }
7428
7429 for (i = 0; i < MCSLeng; i++)
7430 {
7431 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
7432 for (j = 0; j < temp; j++)
7433 {
7434 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
7435 {
7436 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
7437 break;
7438 }
7439 }
7440 if ((j < temp) && (currentRate > maxRate))
7441 {
7442 maxRate = currentRate;
7443 maxSpeedMCS = 1;
7444 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
7445 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007446 }
7447 }
7448 }
7449
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307450 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
7451 {
7452 maxRate = myRate;
7453 maxSpeedMCS = 1;
7454 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
7455 }
7456
Jeff Johnson295189b2012-06-20 16:38:30 -07007457 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007458 if (((maxRate < myRate) && (0 == rssidx)) ||
7459 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07007460 {
7461 maxRate = myRate;
7462 if (rate_flags & eHAL_TX_RATE_LEGACY)
7463 {
7464 maxSpeedMCS = 0;
7465 }
7466 else
7467 {
7468 maxSpeedMCS = 1;
7469 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
7470 }
7471 }
7472
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307473 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson295189b2012-06-20 16:38:30 -07007474 {
7475 sinfo->txrate.legacy = maxRate;
7476#ifdef LINKSPEED_DEBUG_ENABLED
7477 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
7478#endif //LINKSPEED_DEBUG_ENABLED
7479 }
7480 else
7481 {
7482 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07007483#ifdef WLAN_FEATURE_11AC
7484 sinfo->txrate.nss = 1;
7485 if (rate_flags & eHAL_TX_RATE_VHT80)
7486 {
7487 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307488 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Leo Chang6f8870f2013-03-26 18:11:36 -07007489 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307490 else if (rate_flags & eHAL_TX_RATE_VHT40)
Leo Chang6f8870f2013-03-26 18:11:36 -07007491 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307492 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7493 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7494 }
7495 else if (rate_flags & eHAL_TX_RATE_VHT20)
7496 {
7497 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7498 }
7499#endif /* WLAN_FEATURE_11AC */
7500 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
7501 {
7502 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
7503 if (rate_flags & eHAL_TX_RATE_HT40)
7504 {
7505 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7506 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007507 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007508 if (rate_flags & eHAL_TX_RATE_SGI)
7509 {
7510 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
7511 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307512
Jeff Johnson295189b2012-06-20 16:38:30 -07007513#ifdef LINKSPEED_DEBUG_ENABLED
7514 pr_info("Reporting MCS rate %d flags %x\n",
7515 sinfo->txrate.mcs,
7516 sinfo->txrate.flags );
7517#endif //LINKSPEED_DEBUG_ENABLED
7518 }
7519 }
7520 else
7521 {
7522 // report current rate instead of max rate
7523
7524 if (rate_flags & eHAL_TX_RATE_LEGACY)
7525 {
7526 //provide to the UI in units of 100kbps
7527 sinfo->txrate.legacy = myRate;
7528#ifdef LINKSPEED_DEBUG_ENABLED
7529 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
7530#endif //LINKSPEED_DEBUG_ENABLED
7531 }
7532 else
7533 {
7534 //must be MCS
7535 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07007536#ifdef WLAN_FEATURE_11AC
7537 sinfo->txrate.nss = 1;
7538 if (rate_flags & eHAL_TX_RATE_VHT80)
7539 {
7540 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7541 }
7542 else
7543#endif /* WLAN_FEATURE_11AC */
7544 {
7545 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
7546 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007547 if (rate_flags & eHAL_TX_RATE_SGI)
7548 {
7549 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
7550 }
7551 if (rate_flags & eHAL_TX_RATE_HT40)
7552 {
7553 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7554 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007555#ifdef WLAN_FEATURE_11AC
7556 else if (rate_flags & eHAL_TX_RATE_VHT80)
7557 {
7558 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
7559 }
7560#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007561#ifdef LINKSPEED_DEBUG_ENABLED
7562 pr_info("Reporting actual MCS rate %d flags %x\n",
7563 sinfo->txrate.mcs,
7564 sinfo->txrate.flags );
7565#endif //LINKSPEED_DEBUG_ENABLED
7566 }
7567 }
7568 sinfo->filled |= STATION_INFO_TX_BITRATE;
7569
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07007570 sinfo->tx_packets =
7571 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
7572 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
7573 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
7574 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
7575
7576 sinfo->tx_retries =
7577 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
7578 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
7579 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
7580 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
7581
7582 sinfo->tx_failed =
7583 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
7584 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
7585 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
7586 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
7587
7588 sinfo->filled |=
7589 STATION_INFO_TX_PACKETS |
7590 STATION_INFO_TX_RETRIES |
7591 STATION_INFO_TX_FAILED;
7592
7593 EXIT();
7594 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007595}
7596
7597static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Sameer Thalappilc9f26e92013-06-07 10:11:06 -07007598 struct net_device *dev, bool mode, int timeout)
Jeff Johnson295189b2012-06-20 16:38:30 -07007599{
7600 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307601 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007602 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307603 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007604
Jeff Johnsone7245742012-09-05 17:12:55 -07007605 ENTER();
7606
Jeff Johnson295189b2012-06-20 16:38:30 -07007607 if (NULL == pAdapter)
7608 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007609 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007610 return -ENODEV;
7611 }
7612
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307613 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307614 status = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307615
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307616 if (0 != status)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307617 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7619 "%s: HDD context is not valid", __func__);
7620 return status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307621 }
7622
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307623 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
7624 (TRUE == pHddCtx->hdd_wlan_suspended) &&
7625 (pHddCtx->cfg_ini->fhostArpOffload) &&
7626 (eConnectionState_Associated ==
7627 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
7628 {
Amar Singhald53568e2013-09-26 11:03:45 -07007629
7630 hddLog(VOS_TRACE_LEVEL_INFO,
7631 "offload: in cfg80211_set_power_mgmt, calling arp offload");
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05307632 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307633 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7634 {
7635 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08007636 "%s:Failed to enable ARPOFFLOAD Feature %d",
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307637 __func__, vos_status);
7638 }
7639 }
7640
Jeff Johnson295189b2012-06-20 16:38:30 -07007641 /**The get power cmd from the supplicant gets updated by the nl only
7642 *on successful execution of the function call
7643 *we are oppositely mapped w.r.t mode in the driver
7644 **/
7645 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
7646
Jeff Johnsone7245742012-09-05 17:12:55 -07007647 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007648 if (VOS_STATUS_E_FAILURE == vos_status)
7649 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7651 "%s: failed to enter bmps mode", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007652 return -EINVAL;
7653 }
7654 return 0;
7655}
7656
7657
7658#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7659static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
7660 struct net_device *netdev,
7661 u8 key_index)
7662{
Jeff Johnsone7245742012-09-05 17:12:55 -07007663 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007664 return 0;
7665}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307666#endif //LINUX_VERSION_CODE
Jeff Johnson295189b2012-06-20 16:38:30 -07007667
7668#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
7669static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7670 struct net_device *dev,
7671 struct ieee80211_txq_params *params)
7672{
Jeff Johnsone7245742012-09-05 17:12:55 -07007673 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007674 return 0;
7675}
7676#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7677static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7678 struct ieee80211_txq_params *params)
7679{
Jeff Johnsone7245742012-09-05 17:12:55 -07007680 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007681 return 0;
7682}
7683#endif //LINUX_VERSION_CODE
7684
7685static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
7686 struct net_device *dev, u8 *mac)
7687{
7688 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307689 hdd_context_t *pHddCtx;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007690 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307691 int status;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007692 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007693
Jeff Johnsone7245742012-09-05 17:12:55 -07007694 ENTER();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307695 if ( NULL == pAdapter )
Jeff Johnson295189b2012-06-20 16:38:30 -07007696 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307697 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007698 return -EINVAL;
7699 }
7700
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307701 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7702 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007703
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307704 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007705 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7707 "%s: HDD context is not valid", __func__);
7708 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007709 }
7710
Jeff Johnson295189b2012-06-20 16:38:30 -07007711 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007712 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007713 )
7714 {
7715 if( NULL == mac )
7716 {
7717 v_U16_t i;
7718 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
7719 {
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007720 if ((pAdapter->aStaInfo[i].isUsed) &&
7721 (!pAdapter->aStaInfo[i].isDeauthInProgress))
Jeff Johnson295189b2012-06-20 16:38:30 -07007722 {
7723 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
7724 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007725 "%s: Delete STA with MAC::"
7726 MAC_ADDRESS_STR,
7727 __func__, MAC_ADDR_ARRAY(macAddr));
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007728 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
7729 if (VOS_IS_STATUS_SUCCESS(vos_status))
7730 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007731 }
7732 }
7733 }
7734 else
7735 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007736
7737 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
7738 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7739 {
7740 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007741 "%s: Skip this DEL STA as this is not used::"
7742 MAC_ADDRESS_STR,
7743 __func__, MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007744 return -ENOENT;
7745 }
7746
7747 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
7748 {
7749 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007750 "%s: Skip this DEL STA as deauth is in progress::"
7751 MAC_ADDRESS_STR,
7752 __func__, MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007753 return -ENOENT;
7754 }
7755
7756 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
7757
Jeff Johnson295189b2012-06-20 16:38:30 -07007758 hddLog(VOS_TRACE_LEVEL_INFO,
7759 "%s: Delete STA with MAC::"
Arif Hussain24bafea2013-11-15 15:10:03 -08007760 MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007761 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08007762 MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007763
7764 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
7765 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7766 {
7767 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
7768 hddLog(VOS_TRACE_LEVEL_INFO,
7769 "%s: STA removal failed for ::"
Arif Hussain24bafea2013-11-15 15:10:03 -08007770 MAC_ADDRESS_STR,
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007771 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08007772 MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007773 return -ENOENT;
7774 }
7775
Jeff Johnson295189b2012-06-20 16:38:30 -07007776 }
7777 }
7778
7779 EXIT();
7780
7781 return 0;
7782}
7783
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007784static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
7785 struct net_device *dev, u8 *mac, struct station_parameters *params)
7786{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007787 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007788#ifdef FEATURE_WLAN_TDLS
7789 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007790 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007791 mask = params->sta_flags_mask;
7792
7793 set = params->sta_flags_set;
7794
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007795#ifdef WLAN_FEATURE_TDLS_DEBUG
7796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7797 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
7798 __func__, mask, set, MAC_ADDR_ARRAY(mac));
7799#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007800
7801 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7802 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007803 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007804 }
7805 }
7806#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007807 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007808}
7809
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007810
7811#ifdef FEATURE_WLAN_LFR
Wilson Yang6507c4e2013-10-01 20:11:19 -07007812#define MAX_PMKSAIDS_IN_CACHE 8
7813
7814static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD local cache
7815static tANI_U32 PMKIDCacheIndex; // HDD local Cache index
7816
7817
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007818static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007819 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007820{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307821 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007822 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7823 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307824 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307825 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007826 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307827 hdd_context_t *pHddCtx;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307828
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007829 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: set PMKSA for " MAC_ADDRESS_STR,
7830 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Jeff Johnsone7245742012-09-05 17:12:55 -07007831
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307832 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307833 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007834 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307835 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007836 return -EINVAL;
7837 }
7838
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307839 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7840 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007841
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307842 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007843 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7845 "%s: HDD context is not valid", __func__);
7846 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007847 }
7848
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307849 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007850 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7851
Wilson Yang6507c4e2013-10-01 20:11:19 -07007852 for (j = 0; j < PMKIDCacheIndex; j++)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007853 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307854 if(vos_mem_compare(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007855 pmksa->bssid, WNI_CFG_BSSID_LEN))
7856 {
7857 /* BSSID matched previous entry. Overwrite it. */
7858 BSSIDMatched = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307859 vos_mem_copy(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007860 pmksa->bssid, WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307861 vos_mem_copy(PMKIDCache[j].PMKID,
7862 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007863 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307864 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007865 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007866 dump_bssid(pmksa->bssid);
7867 dump_pmkid(halHandle, pmksa->pmkid);
7868 break;
7869 }
7870 }
7871
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007872 /* Check we compared all entries,if then take the first slot now */
Wilson Yang6507c4e2013-10-01 20:11:19 -07007873 if(j == MAX_PMKSAIDS_IN_CACHE) PMKIDCacheIndex=0;
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007874
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007875 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307876 {
7877 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
Wilson Yang6507c4e2013-10-01 20:11:19 -07007878 vos_mem_copy(PMKIDCache[PMKIDCacheIndex].BSSID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307879 pmksa->bssid, ETHER_ADDR_LEN);
Wilson Yang6507c4e2013-10-01 20:11:19 -07007880 vos_mem_copy(PMKIDCache[PMKIDCacheIndex].PMKID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307881 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007882 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307883 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Wilson Yang6507c4e2013-10-01 20:11:19 -07007884 __func__, PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007885 dump_bssid(pmksa->bssid);
7886 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307887 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007888 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Wilson Yang6507c4e2013-10-01 20:11:19 -07007889 if (PMKIDCacheIndex <= (MAX_PMKSAIDS_IN_CACHE-1)) PMKIDCacheIndex++; else PMKIDCacheIndex = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007890 }
7891
7892
7893 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307894 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007895 // __func__, i );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307896 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Wilson Yang6507c4e2013-10-01 20:11:19 -07007897 __func__, PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007898 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307899 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
7900 PMKIDCache,
Wilson Yang6507c4e2013-10-01 20:11:19 -07007901 PMKIDCacheIndex);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007902 return 0;
7903}
7904
7905
Wilson Yang6507c4e2013-10-01 20:11:19 -07007906
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007907static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Wilson Yang6507c4e2013-10-01 20:11:19 -07007908 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007909{
Wilson Yang6507c4e2013-10-01 20:11:19 -07007910 tANI_U32 j=0;
7911 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7912 tHalHandle halHandle;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007913 tANI_U8 BSSIDMatched = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007914 hdd_context_t *pHddCtx;
Wilson Yangef657d32014-01-15 19:19:23 -08007915 int status = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007916
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007917 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: deleting PMKSA for " MAC_ADDRESS_STR,
7918 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Wilson Yang6507c4e2013-10-01 20:11:19 -07007919
7920 /* Validate pAdapter */
7921 if (NULL == pAdapter)
7922 {
7923 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
7924 return -EINVAL;
7925 }
7926
7927 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7928 status = wlan_hdd_validate_context(pHddCtx);
7929
7930 if (0 != status)
7931 {
7932 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7933 "%s: HDD context is not valid", __func__);
7934 return status;
7935 }
7936
7937 /*Retrieve halHandle*/
7938 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7939
7940 /*in case index is 0,no entry to delete*/
7941 if (0 == PMKIDCacheIndex)
7942 {
7943 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid entry to delete" ,
7944 __func__);
7945 return -EINVAL;
7946 }
7947
7948 /*find the matching PMKSA entry from j=0 to (index-1),
7949 * and delete the matched one
7950 */
7951 for (j = 0; j<PMKIDCacheIndex; j++)
7952 {
7953 if (vos_mem_compare(PMKIDCache[j].BSSID,
7954 pmksa->bssid,
7955 WNI_CFG_BSSID_LEN))
7956 {
7957 /* BSSID matched entry */
7958 BSSIDMatched = 1;
7959
7960 if (j<PMKIDCacheIndex-1)
7961 {
7962 /*replace the matching entry with the last entry in HDD local cache*/
7963 vos_mem_copy(PMKIDCache[j].BSSID,
7964 PMKIDCache[PMKIDCacheIndex-1].BSSID,
7965 WNI_CFG_BSSID_LEN);
7966 vos_mem_copy(PMKIDCache[j].PMKID,
7967 PMKIDCache[PMKIDCacheIndex-1].PMKID,
7968 CSR_RSN_PMKID_SIZE);
7969 }
7970
7971 /*clear the last entry in HDD cache ---[index-1]*/
Wilson Yang6507c4e2013-10-01 20:11:19 -07007972 vos_mem_zero(PMKIDCache[PMKIDCacheIndex-1].BSSID, WNI_CFG_BSSID_LEN);
7973 vos_mem_zero(PMKIDCache[PMKIDCacheIndex-1].PMKID, CSR_RSN_PMKID_SIZE);
7974
7975 /*reduce the PMKID array index*/
7976 PMKIDCacheIndex--;
7977
7978 /*delete the last PMKID cache in CSR*/
Wilson Yangef657d32014-01-15 19:19:23 -08007979 if (eHAL_STATUS_SUCCESS !=
7980 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pmksa->bssid))
Wilson Yang6507c4e2013-10-01 20:11:19 -07007981 {
7982 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cannot delete PMKSA %d CONTENT.",
7983 __func__,PMKIDCacheIndex);
Wilson Yangef657d32014-01-15 19:19:23 -08007984 status = -EINVAL;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007985 }
7986
7987 dump_bssid(pmksa->bssid);
7988 dump_pmkid(halHandle,pmksa->pmkid);
7989
7990 break;
7991 }
7992 }
7993
7994 /* we compare all entries,but cannot find matching entry */
7995 if (j == MAX_PMKSAIDS_IN_CACHE && !BSSIDMatched)
7996 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007997 hddLog(VOS_TRACE_LEVEL_FATAL,
7998 "%s: No such PMKSA entry existed " MAC_ADDRESS_STR,
7999 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Wilson Yang6507c4e2013-10-01 20:11:19 -07008000 dump_bssid(pmksa->bssid);
8001 dump_pmkid(halHandle, pmksa->pmkid);
8002 return -EINVAL;
8003 }
Wilson Yangef657d32014-01-15 19:19:23 -08008004 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008005}
8006
Wilson Yang6507c4e2013-10-01 20:11:19 -07008007
8008
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008009static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
8010{
Wilson Yang6507c4e2013-10-01 20:11:19 -07008011 tANI_U32 j=0;
8012 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8013 tHalHandle halHandle;
8014 hdd_context_t *pHddCtx;
8015 tANI_U8 *pBSSId;
Wilson Yangef657d32014-01-15 19:19:23 -08008016 int status = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07008017
8018 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: flushing PMKSA ",__func__);
8019
8020 /* Validate pAdapter */
8021 if (NULL == pAdapter)
8022 {
8023 hddLog(VOS_TRACE_LEVEL_ERROR,
8024 "%s: Invalid Adapter" ,__func__);
8025 return -EINVAL;
8026 }
8027
8028 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8029 status = wlan_hdd_validate_context(pHddCtx);
8030
8031 if (0 != status)
8032 {
8033 hddLog(VOS_TRACE_LEVEL_ERROR,
8034 "%s: HDD context is not valid", __func__);
8035 return status;
8036 }
8037
8038 /*Retrieve halHandle*/
8039 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
8040
8041 /*in case index is 0,no entry to delete*/
8042 if (0 == PMKIDCacheIndex)
8043 {
8044 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid entry to delete" ,
8045 __func__);
8046 return -EINVAL;
8047 }
8048
8049 /*delete all the PMKSA one by one */
8050 for (j = 0; j<PMKIDCacheIndex; j++)
8051 {
Wilson Yang6507c4e2013-10-01 20:11:19 -07008052 pBSSId =(tANI_U8 *)(PMKIDCache[j].BSSID);
Wilson Yang6507c4e2013-10-01 20:11:19 -07008053
8054 /*delete the PMKID in CSR*/
Wilson Yangef657d32014-01-15 19:19:23 -08008055 if (eHAL_STATUS_SUCCESS !=
8056 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pBSSId))
Wilson Yang6507c4e2013-10-01 20:11:19 -07008057 {
8058 hddLog(VOS_TRACE_LEVEL_ERROR ,"%s cannot flush PMKIDCache %d.",
8059 __func__,j);
Wilson Yangef657d32014-01-15 19:19:23 -08008060 status = -EINVAL;
Wilson Yang6507c4e2013-10-01 20:11:19 -07008061 }
Kiet Lam8d21d5b2013-10-31 17:18:29 +05308062 /*clear the entry in HDD cache 0--index-1 */
8063 vos_mem_zero(PMKIDCache[j].BSSID, WNI_CFG_BSSID_LEN);
8064 vos_mem_zero(PMKIDCache[j].PMKID, CSR_RSN_PMKID_SIZE);
Wilson Yang6507c4e2013-10-01 20:11:19 -07008065 }
8066
8067 PMKIDCacheIndex = 0;
Wilson Yangef657d32014-01-15 19:19:23 -08008068 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008069}
8070#endif
8071
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008072#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308073static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008074 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
8075{
8076 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8077 hdd_station_ctx_t *pHddStaCtx;
8078
8079 if (NULL == pAdapter)
8080 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008081 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008082 return -ENODEV;
8083 }
8084
8085 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8086
8087 // Added for debug on reception of Re-assoc Req.
8088 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
8089 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008090 hddLog(LOGE, FL("Called with Ie of length = %zu when not associated"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008091 ftie->ie_len);
Arif Hussain6d2a3322013-11-17 19:50:10 -08008092 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008093 }
8094
8095#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Arif Hussain6d2a3322013-11-17 19:50:10 -08008096 hddLog(LOGE, FL("%s called with Ie of length = %zu"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008097 ftie->ie_len);
8098#endif
8099
8100 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05308101 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
8102 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008103 ftie->ie_len);
8104 return 0;
8105}
8106#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008107
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308108#ifdef FEATURE_WLAN_SCAN_PNO
8109
8110void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
8111 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
8112{
8113 int ret;
8114 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
8115 hdd_context_t *pHddCtx;
8116
Nirav Shah80830bf2013-12-31 16:35:12 +05308117 ENTER();
8118
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308119 if (NULL == pAdapter)
8120 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308122 "%s: HDD adapter is Null", __func__);
8123 return ;
8124 }
8125
8126 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8127 if (NULL == pHddCtx)
8128 {
8129 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8130 "%s: HDD context is Null!!!", __func__);
8131 return ;
8132 }
8133
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308134 spin_lock(&pHddCtx->schedScan_lock);
8135 if (TRUE == pHddCtx->isWiphySuspended)
8136 {
8137 pHddCtx->isSchedScanUpdatePending = TRUE;
8138 spin_unlock(&pHddCtx->schedScan_lock);
8139 hddLog(VOS_TRACE_LEVEL_INFO,
8140 "%s: Update cfg80211 scan database after it resume", __func__);
8141 return ;
8142 }
8143 spin_unlock(&pHddCtx->schedScan_lock);
8144
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308145 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
8146
8147 if (0 > ret)
8148 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
8149
8150 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8152 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308153}
8154
8155/*
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308156 * FUNCTION: wlan_hdd_is_pno_allowed
8157 * To check is there any P2P GO/SAP or P2P Client/STA
8158 * session is active
8159 */
8160static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter)
8161{
8162 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8163 hdd_adapter_t *pTempAdapter = NULL;
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308164 hdd_station_ctx_t *pStaCtx;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308165 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8166 int status = 0;
8167 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
8168
8169 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status))
8170 {
8171 pTempAdapter = pAdapterNode->pAdapter;
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308172 pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pTempAdapter);
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308173
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308174 if (((WLAN_HDD_INFRA_STATION == pTempAdapter->device_mode)
8175 && (eConnectionState_NotConnected != pStaCtx->conn_info.connState))
8176 || (WLAN_HDD_P2P_CLIENT == pTempAdapter->device_mode)
8177 || (WLAN_HDD_P2P_GO == pTempAdapter->device_mode)
8178 || (WLAN_HDD_SOFTAP == pTempAdapter->device_mode)
8179 )
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308180 {
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308181 return eHAL_STATUS_FAILURE;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308182 }
8183 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8184 pAdapterNode = pNext;
8185 }
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308186 return eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308187}
8188
8189/*
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308190 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
8191 * NL interface to enable PNO
8192 */
8193static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
8194 struct net_device *dev, struct cfg80211_sched_scan_request *request)
8195{
8196 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8197 tpSirPNOScanReq pPnoRequest = NULL;
8198 hdd_context_t *pHddCtx;
8199 tHalHandle hHal;
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05308200 v_U32_t i, indx, num_ch, tempInterval;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308201 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
8202 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN];
8203 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
8204 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308205 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308206
8207 if (NULL == pAdapter)
8208 {
8209 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8210 "%s: HDD adapter is Null", __func__);
8211 return -ENODEV;
8212 }
8213
8214 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308215 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308216
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308217 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308218 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8220 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308221 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308222 }
8223
8224 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8225 if (NULL == hHal)
8226 {
8227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8228 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308229 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308230 }
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308231
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308232 /* The current firmware design for PNO does not consider concurrent
8233 * active sessions.Hence , determine the concurrent active sessions
8234 * and return a failure to the framework on a request for schedule
8235 * scan.
8236 */
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308237 if (eHAL_STATUS_SUCCESS != wlan_hdd_is_pno_allowed(pAdapter))
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308238 {
8239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308240 FL("Cannot handle sched_scan"));
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308241 return -EBUSY;
8242 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308243
8244 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
8245 if (NULL == pPnoRequest)
8246 {
8247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8248 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308249 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308250 }
8251
Madan Mohan Koyyalamudic3f04352013-09-26 19:21:48 +05308252 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308253 pPnoRequest->enable = 1; /*Enable PNO */
8254 pPnoRequest->ucNetworksCount = request->n_match_sets;
8255
8256 if (( !pPnoRequest->ucNetworksCount ) ||
8257 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
8258 {
8259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308260 "%s: Network input is not correct %d",
8261 __func__, pPnoRequest->ucNetworksCount);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308262 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308263 goto error;
8264 }
8265
8266 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
8267 {
8268 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308269 "%s: Incorrect number of channels %d",
8270 __func__, request->n_channels);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308271 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308272 goto error;
8273 }
8274
8275 /* Framework provides one set of channels(all)
8276 * common for all saved profile */
8277 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
8278 channels_allowed, &num_channels_allowed))
8279 {
8280 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8281 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308282 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308283 goto error;
8284 }
8285 /* Checking each channel against allowed channel list */
8286 num_ch = 0;
Nirav Shah80830bf2013-12-31 16:35:12 +05308287 if (request->n_channels)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308288 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308289 char chList [(request->n_channels*5)+1];
8290 int len;
8291 for (i = 0, len = 0; i < request->n_channels; i++)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308292 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308293 for (indx = 0; indx < num_channels_allowed; indx++)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308294 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308295 if (request->channels[i]->hw_value == channels_allowed[indx])
8296 {
8297 valid_ch[num_ch++] = request->channels[i]->hw_value;
8298 len += snprintf(chList+len, 5, "%d ",
8299 request->channels[i]->hw_value);
8300 break ;
8301 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308302 }
8303 }
Nirav Shah80830bf2013-12-31 16:35:12 +05308304 hddLog(VOS_TRACE_LEVEL_INFO,"Channel-List: %s ", chList);
8305 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308306
8307 /* Filling per profile params */
8308 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
8309 {
8310 pPnoRequest->aNetworks[i].ssId.length =
8311 request->match_sets[i].ssid.ssid_len;
8312
8313 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
8314 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
8315 {
8316 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308317 "%s: SSID Len %d is not correct for network %d",
8318 __func__, pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308319 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308320 goto error;
8321 }
8322
8323 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
8324 request->match_sets[i].ssid.ssid,
8325 request->match_sets[i].ssid.ssid_len);
8326 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
8327 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
8328 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
8329
8330 /*Copying list of valid channel into request */
8331 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
8332 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
8333
8334 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
8335 }
8336
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +05308337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson59a121e2013-11-30 09:46:08 -08008338 "request->ie_len = %zu", request->ie_len);
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +05308339 if ((0 < request->ie_len) && (NULL != request->ie))
8340 {
8341 pPnoRequest->us24GProbeTemplateLen = request->ie_len;
8342 memcpy(&pPnoRequest->p24GProbeTemplate, request->ie,
8343 pPnoRequest->us24GProbeTemplateLen);
8344
8345 pPnoRequest->us5GProbeTemplateLen = request->ie_len;
8346 memcpy(&pPnoRequest->p5GProbeTemplate, request->ie,
8347 pPnoRequest->us5GProbeTemplateLen);
8348 }
8349
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05308350 /* Driver gets only one time interval which is hardcoded in
8351 * supplicant for 10000ms. Taking power consumption into account 6 timers
8352 * will be used, Timervalue is increased exponentially i.e 10,20,40,
8353 * 80,160,320 secs. And number of scan cycle for each timer
8354 * is configurable through INI param gPNOScanTimerRepeatValue.
8355 * If it is set to 0 only one timer will be used and PNO scan cycle
8356 * will be repeated after each interval specified by supplicant
8357 * till PNO is disabled.
8358 */
8359 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
8360 pPnoRequest->scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
8361 else
8362 pPnoRequest->scanTimers.ucScanTimersCount =
8363 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
8364
8365 tempInterval = (request->interval)/1000;
8366 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8367 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
8368 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
8369 for ( i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++)
8370 {
8371 pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat =
8372 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
8373 pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = tempInterval;
8374 tempInterval *= 2;
8375 }
8376 //Repeat last timer until pno disabled.
8377 pPnoRequest->scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
8378
Madan Mohan Koyyalamudid206c7b2013-09-26 22:54:51 +05308379 pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308380
Nirav Shah80830bf2013-12-31 16:35:12 +05308381 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8382 "SessionId %d, enable %d, modePNO %d, ucScanTimersCount %d",
8383 pAdapter->sessionId, pPnoRequest->enable, pPnoRequest->modePNO,
8384 pPnoRequest->scanTimers.ucScanTimersCount);
8385
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308386 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
8387 pPnoRequest, pAdapter->sessionId,
8388 hdd_cfg80211_sched_scan_done_callback, pAdapter);
8389 if (eHAL_STATUS_SUCCESS != status)
8390 {
8391 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308392 "%s: Failed to enable PNO", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308393 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308394 goto error;
8395 }
8396
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8398 "PNO scanRequest offloaded");
8399
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308400error:
8401 vos_mem_free(pPnoRequest);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308402 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308403}
8404
8405/*
8406 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
8407 * NL interface to disable PNO
8408 */
8409static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
8410 struct net_device *dev)
8411{
8412 eHalStatus status = eHAL_STATUS_FAILURE;
8413 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8414 hdd_context_t *pHddCtx;
8415 tHalHandle hHal;
8416 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308417 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308418
8419 ENTER();
8420
8421 if (NULL == pAdapter)
8422 {
8423 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8424 "%s: HDD adapter is Null", __func__);
8425 return -ENODEV;
8426 }
8427
8428 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308429
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308430 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308431 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308433 "%s: HDD context is Null", __func__);
8434 return -ENODEV;
8435 }
8436
8437 /* The return 0 is intentional when isLogpInProgress and
8438 * isLoadUnloadInProgress. We did observe a crash due to a return of
8439 * failure in sched_scan_stop , especially for a case where the unload
8440 * of the happens at the same time. The function __cfg80211_stop_sched_scan
8441 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
8442 * success. If it returns a failure , then its next invocation due to the
8443 * clean up of the second interface will have the dev pointer corresponding
8444 * to the first one leading to a crash.
8445 */
8446 if (pHddCtx->isLogpInProgress)
8447 {
8448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8449 "%s: LOGP in Progress. Ignore!!!", __func__);
8450 return ret;
8451 }
8452
8453 if (pHddCtx->isLoadUnloadInProgress)
8454 {
8455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8456 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
8457 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308458 }
8459
8460 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8461 if (NULL == hHal)
8462 {
8463 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8464 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308465 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308466 }
8467
8468 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
8469 if (NULL == pPnoRequest)
8470 {
8471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8472 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308473 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308474 }
8475
8476 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
8477 pPnoRequest->enable = 0; /* Disable PNO */
8478 pPnoRequest->ucNetworksCount = 0;
8479
8480 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
8481 pAdapter->sessionId,
8482 NULL, pAdapter);
8483 if (eHAL_STATUS_SUCCESS != status)
8484 {
8485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8486 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308487 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308488 }
8489
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8491 "%s: PNO scan disabled", __func__);
8492
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308493 vos_mem_free(pPnoRequest);
8494
8495 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308496 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308497}
8498
8499#endif /*FEATURE_WLAN_SCAN_PNO*/
8500
8501
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008502#ifdef FEATURE_WLAN_TDLS
8503static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
8504 u8 *peer, u8 action_code, u8 dialog_token,
8505 u16 status_code, const u8 *buf, size_t len)
8506{
8507
8508 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8509 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008510 u8 peerMac[6];
8511 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07008512 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08008513 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -07008514 long rc;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008515
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008516 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008517 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008519 "Invalid arguments");
8520 return -EINVAL;
8521 }
8522
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008523 if (pHddCtx->isLogpInProgress)
8524 {
8525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8526 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008527 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008528 return -EBUSY;
8529 }
8530
Hoonki Lee27511902013-03-14 18:19:06 -07008531 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008532 {
Hoonki Lee27511902013-03-14 18:19:06 -07008533 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
8534 "%s: TDLS mode is disabled OR not enabled in FW."
8535 MAC_ADDRESS_STR " action %d declined.",
8536 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008537 return -ENOTSUPP;
8538 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008539
Hoonki Lee27511902013-03-14 18:19:06 -07008540 /* other than teardown frame, other mgmt frames are not sent if disabled */
8541 if (SIR_MAC_TDLS_TEARDOWN != action_code)
8542 {
8543 /* if tdls_mode is disabled to respond to peer's request */
8544 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
8545 {
8546 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
8547 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008548 " TDLS mode is disabled. action %d declined.",
8549 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07008550
8551 return -ENOTSUPP;
8552 }
8553 }
8554
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008555 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
8556 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308557 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008558 {
8559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008560 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008561 " TDLS setup is ongoing. action %d declined.",
8562 __func__, MAC_ADDR_ARRAY(peer), action_code);
8563 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008564 }
8565 }
8566
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008567 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
8568 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08008569 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008570 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008571 {
8572 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
8573 we return error code at 'add_station()'. Hence we have this
8574 check again in addtion to add_station().
8575 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008576 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08008577 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8579 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008580 " TDLS Max peer already connected. action %d declined.",
8581 __func__, MAC_ADDR_ARRAY(peer), action_code);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308582 return -EINVAL;
Lee Hoonkic1262f22013-01-24 21:59:00 -08008583 }
8584 else
8585 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008586 /* maximum reached. tweak to send error code to peer and return
8587 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08008588 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8590 "%s: " MAC_ADDRESS_STR
8591 " TDLS Max peer already connected send response status %d",
8592 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008593 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008594 /* fall through to send setup resp with failure status
8595 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08008596 }
8597 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008598 else
8599 {
8600 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308601 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008602 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008603 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008605 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
8606 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008607 return -EPERM;
8608 }
8609 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008610 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008611 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008612
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008613#ifdef WLAN_FEATURE_TDLS_DEBUG
8614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008615 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
8616 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
8617 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008618#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008619
Hoonki Leea34dd892013-02-05 22:56:02 -08008620 /*Except teardown responder will not be used so just make 0*/
8621 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008622 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08008623 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008624
8625 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308626 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac, TRUE);
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008627
8628 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
8629 responder = pTdlsPeer->is_responder;
8630 else
Hoonki Leea34dd892013-02-05 22:56:02 -08008631 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8633 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
8634 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
8635 dialog_token, status_code, len);
8636 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08008637 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008638 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008639
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308640 /* For explicit trigger of DIS_REQ come out of BMPS for
8641 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -07008642 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308643 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
8644 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -07008645 {
8646 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
8647 {
8648 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308649 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -07008650 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
8651 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308652 if (SIR_MAC_TDLS_DIS_REQ != action_code)
8653 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -07008654 }
8655
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008656 /* make sure doesn't call send_mgmt() while it is pending */
8657 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
8658 {
8659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008660 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY",
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008661 __func__, MAC_ADDR_ARRAY(peer), action_code);
8662 return -EBUSY;
8663 }
8664
8665 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008666 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
8667
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008668 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08008669 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008670
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008671 if (VOS_STATUS_SUCCESS != status)
8672 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008673 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8674 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008675 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -07008676 wlan_hdd_tdls_check_bmps(pAdapter);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308677 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008678 }
8679
Hoonki Leed37cbb32013-04-20 00:31:14 -07008680 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
8681 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
8682
8683 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008684 {
Hoonki Leed37cbb32013-04-20 00:31:14 -07008685 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008686 "%s: Mgmt Tx Completion failed status %ld TxCompletion %u",
Hoonki Leed37cbb32013-04-20 00:31:14 -07008687 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008688 pAdapter->mgmtTxCompletionStatus = FALSE;
Yue Ma4f55ef32014-01-23 16:45:33 -08008689
8690 if (pHddCtx->isLogpInProgress)
8691 {
8692 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8693 "%s: LOGP in Progress. Ignore!!!", __func__);
8694 return -EAGAIN;
8695 }
8696
Hoonki Leed37cbb32013-04-20 00:31:14 -07008697 wlan_hdd_tdls_check_bmps(pAdapter);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308698 return -EINVAL;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008699 }
8700
Gopichand Nakkala05922802013-03-14 12:23:19 -07008701 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07008702 {
8703 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008704 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07008705 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008706
Hoonki Leea34dd892013-02-05 22:56:02 -08008707 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
8708 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008709 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08008710 }
8711 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
8712 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008713 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08008714 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008715
8716 return 0;
8717}
8718
8719static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
8720 u8 *peer, enum nl80211_tdls_operation oper)
8721{
8722 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8723 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308724 int status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008725 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008726
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308727 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008728 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07008730 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008731 return -EINVAL;
8732 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008733
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308734 status = wlan_hdd_validate_context(pHddCtx);
8735
8736 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008737 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8739 "%s: HDD context is not valid", __func__);
8740 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008741 }
8742
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008743
8744 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008745 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008746 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07008748 "TDLS Disabled in INI OR not enabled in FW. "
8749 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008750 return -ENOTSUPP;
8751 }
8752
8753 switch (oper) {
8754 case NL80211_TDLS_ENABLE_LINK:
8755 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008756 VOS_STATUS status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308757 long ret;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308758 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008759
Sunil Dutt41de4e22013-11-14 18:09:02 +05308760 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8761
8762 if ( NULL == pTdlsPeer ) {
8763 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
8764 " (oper %d) not exsting. ignored",
8765 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
8766 return -EINVAL;
8767 }
8768
8769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8770 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
8771 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
8772 "NL80211_TDLS_ENABLE_LINK");
8773
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -07008774 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
8775 {
8776 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
8777 MAC_ADDRESS_STR " failed",
8778 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
8779 return -EINVAL;
8780 }
8781
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008782 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008783 {
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308784 if (IS_ADVANCE_TDLS_ENABLE) {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05308785
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308786 if (0 != wlan_hdd_tdls_get_link_establish_params(
8787 pAdapter, peer,&tdlsLinkEstablishParams)) {
8788 return -EINVAL;
8789 }
8790 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308791
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308792 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
8793 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
8794 /* Send TDLS peer UAPSD capabilities to the firmware and
8795 * register with the TL on after the response for this operation
8796 * is received .
8797 */
8798 ret = wait_for_completion_interruptible_timeout(
8799 &pAdapter->tdls_link_establish_req_comp,
8800 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
8801 if (ret <= 0)
8802 {
8803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8804 "%s: Link Establish Request Faled Status %ld",
8805 __func__, ret);
8806 return -EINVAL;
8807 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308808 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008809 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +05308810 /* Mark TDLS client Authenticated .*/
8811 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
8812 pTdlsPeer->staId,
8813 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008814 if (VOS_STATUS_SUCCESS == status)
8815 {
Hoonki Lee14621352013-04-16 17:51:19 -07008816 if (pTdlsPeer->is_responder == 0)
8817 {
8818 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
8819
8820 wlan_hdd_tdls_timer_restart(pAdapter,
8821 &pTdlsPeer->initiatorWaitTimeoutTimer,
8822 WAIT_TIME_TDLS_INITIATOR);
8823 /* suspend initiator TX until it receives direct packet from the
8824 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
8825 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8826 &staId, NULL);
8827 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008828 wlan_hdd_tdls_increment_peer_count(pAdapter);
8829 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008830 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308831
8832 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308833 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
8834 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308835 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308836 int ac;
8837 uint8 ucAc[4] = { WLANTL_AC_VO,
8838 WLANTL_AC_VI,
8839 WLANTL_AC_BK,
8840 WLANTL_AC_BE };
8841 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
8842 for(ac=0; ac < 4; ac++)
8843 {
8844 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8845 pTdlsPeer->staId, ucAc[ac],
8846 tlTid[ac], tlTid[ac], 0, 0,
8847 WLANTL_BI_DIR );
8848 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308849 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008850 }
8851
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008852 }
8853 break;
8854 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08008855 {
Sunil Dutt41de4e22013-11-14 18:09:02 +05308856 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8857
8858 if ( NULL == pTdlsPeer ) {
8859 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
8860 " (oper %d) not exsting. ignored",
8861 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
8862 return -EINVAL;
8863 }
8864
8865 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8866 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
8867 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
8868 "NL80211_TDLS_DISABLE_LINK");
8869
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008870 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008871 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008872 long status;
8873
8874 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
8875
Lee Hoonkic1262f22013-01-24 21:59:00 -08008876 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
8877 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008878
8879 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
8880 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
8881 if (status <= 0)
8882 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008883 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008884 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8885 "%s: Del station failed status %ld",
8886 __func__, status);
8887 return -EPERM;
8888 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008889 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008890 }
8891 else
8892 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008893 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8894 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008895 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008896 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008897 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008898 case NL80211_TDLS_TEARDOWN:
Sunil Dutt41de4e22013-11-14 18:09:02 +05308899 {
8900 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8901 " %s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR,
8902 __func__, MAC_ADDR_ARRAY(peer));
8903
8904 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
8905 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
8906
8907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8908 " %s TDLS External control and Implicit Trigger not enabled ",
8909 __func__);
8910 return -ENOTSUPP;
8911 }
8912
Sunil Dutt41de4e22013-11-14 18:09:02 +05308913
8914 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8915
8916 if ( NULL == pTdlsPeer ) {
8917 hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR
8918 " peer not exsting",
8919 __func__, MAC_ADDR_ARRAY(peer));
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308920 return -EINVAL;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308921 }
8922 else {
8923 wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer,
8924 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
8925 }
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308926
8927 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE) )
8928 return -EINVAL;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308929 break;
8930 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008931 case NL80211_TDLS_SETUP:
Sunil Dutt41de4e22013-11-14 18:09:02 +05308932 {
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308933 hddTdlsPeer_t *pTdlsPeer;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308934 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8935 " %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR,
8936 __func__, MAC_ADDR_ARRAY(peer));
8937
8938 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
8939 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
8940
8941 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8942 " %s TDLS External control and Implicit Trigger not enabled ",
8943 __func__);
8944 return -ENOTSUPP;
8945 }
8946
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308947 /* To cater the requirement of establishing the TDLS link
8948 * irrespective of the data traffic , get an entry of TDLS peer.
8949 */
8950 pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer);
8951 if (pTdlsPeer == NULL) {
8952 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8953 "%s: peer " MAC_ADDRESS_STR " not existing",
8954 __func__, MAC_ADDR_ARRAY(peer));
8955 return -EINVAL;
8956 }
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308957
8958 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) {
8959
8960 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8961 " %s TDLS Add Force Peer Failed",
8962 __func__);
8963 return -EINVAL;
8964 }
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308965 break;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308966 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008967 case NL80211_TDLS_DISCOVERY_REQ:
8968 /* We don't support in-driver setup/teardown/discovery */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308969 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8970 "%s: We don't support in-driver setup/teardown/discovery "
8971 ,__func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008972 return -ENOTSUPP;
8973 default:
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308974 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8975 "%s: unsupported event",__func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008976 return -ENOTSUPP;
8977 }
8978 return 0;
8979}
Chilam NG571c65a2013-01-19 12:27:36 +05308980
8981int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
8982 struct net_device *dev, u8 *peer)
8983{
Arif Hussaina7c8e412013-11-20 11:06:42 -08008984 hddLog(VOS_TRACE_LEVEL_INFO,
8985 "tdls send discover req: "MAC_ADDRESS_STR,
8986 MAC_ADDR_ARRAY(peer));
Chilam NG571c65a2013-01-19 12:27:36 +05308987
8988 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
8989 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
8990}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008991#endif
8992
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05308993#ifdef WLAN_FEATURE_GTK_OFFLOAD
8994/*
8995 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
8996 * Callback rountine called upon receiving response for
8997 * get offload info
8998 */
8999void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
9000 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
9001{
9002
9003 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309004 tANI_U8 tempReplayCounter[8];
9005 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309006
9007 ENTER();
9008
9009 if (NULL == pAdapter)
9010 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05309011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309012 "%s: HDD adapter is Null", __func__);
9013 return ;
9014 }
9015
9016 if (NULL == pGtkOffloadGetInfoRsp)
9017 {
9018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9019 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
9020 return ;
9021 }
9022
9023 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
9024 {
9025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9026 "%s: wlan Failed to get replay counter value",
9027 __func__);
9028 return ;
9029 }
9030
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309031 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9032 /* Update replay counter */
9033 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
9034 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
9035
9036 {
9037 /* changing from little to big endian since supplicant
9038 * works on big endian format
9039 */
9040 int i;
9041 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
9042
9043 for (i = 0; i < 8; i++)
9044 {
9045 tempReplayCounter[7-i] = (tANI_U8)p[i];
9046 }
9047 }
9048
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309049 /* Update replay counter to NL */
9050 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309051 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309052}
9053
9054/*
9055 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
9056 * This function is used to offload GTK rekeying job to the firmware.
9057 */
9058int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
9059 struct cfg80211_gtk_rekey_data *data)
9060{
9061 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9062 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9063 hdd_station_ctx_t *pHddStaCtx;
9064 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309065 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309066 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309067 eHalStatus status = eHAL_STATUS_FAILURE;
9068
9069 ENTER();
9070
9071 if (NULL == pAdapter)
9072 {
9073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9074 "%s: HDD adapter is Null", __func__);
9075 return -ENODEV;
9076 }
9077
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309078 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309079
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309080 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309081 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9083 "%s: HDD context is not valid", __func__);
9084 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309085 }
9086
9087 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9088 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9089 if (NULL == hHal)
9090 {
9091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9092 "%s: HAL context is Null!!!", __func__);
9093 return -EAGAIN;
9094 }
9095
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309096 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
9097 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
9098 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
9099 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309100 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309101 {
9102 /* changing from big to little endian since driver
9103 * works on little endian format
9104 */
9105 tANI_U8 *p =
9106 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
9107 int i;
9108
9109 for (i = 0; i < 8; i++)
9110 {
9111 p[7-i] = data->replay_ctr[i];
9112 }
9113 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309114
9115 if (TRUE == pHddCtx->hdd_wlan_suspended)
9116 {
9117 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309118 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
9119 sizeof (tSirGtkOffloadParams));
9120 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309121 pAdapter->sessionId);
9122
9123 if (eHAL_STATUS_SUCCESS != status)
9124 {
9125 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9126 "%s: sme_SetGTKOffload failed, returned %d",
9127 __func__, status);
9128 return status;
9129 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309130 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9131 "%s: sme_SetGTKOffload successfull", __func__);
9132 }
9133 else
9134 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309135 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9136 "%s: wlan not suspended GTKOffload request is stored",
9137 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309138 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309139
9140 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309141}
9142#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
9143
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05309144/*
9145 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
9146 * This function is used to set access control policy
9147 */
9148static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
9149 struct net_device *dev, const struct cfg80211_acl_data *params)
9150{
9151 int i;
9152 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9153 hdd_hostapd_state_t *pHostapdState;
9154 tsap_Config_t *pConfig;
9155 v_CONTEXT_t pVosContext = NULL;
9156 hdd_context_t *pHddCtx;
9157 int status;
9158
9159 ENTER();
9160
9161 if (NULL == pAdapter)
9162 {
9163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9164 "%s: HDD adapter is Null", __func__);
9165 return -ENODEV;
9166 }
9167
9168 if (NULL == params)
9169 {
9170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9171 "%s: params is Null", __func__);
9172 return -EINVAL;
9173 }
9174
9175 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9176 status = wlan_hdd_validate_context(pHddCtx);
9177
9178 if (0 != status)
9179 {
9180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9181 "%s: HDD context is not valid", __func__);
9182 return status;
9183 }
9184
9185 pVosContext = pHddCtx->pvosContext;
9186 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9187
9188 if (NULL == pHostapdState)
9189 {
9190 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9191 "%s: pHostapdState is Null", __func__);
9192 return -EINVAL;
9193 }
9194
9195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
9196 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
9197
9198 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
9199 {
9200 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
9201
9202 /* default value */
9203 pConfig->num_accept_mac = 0;
9204 pConfig->num_deny_mac = 0;
9205
9206 /**
9207 * access control policy
9208 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
9209 * listed in hostapd.deny file.
9210 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
9211 * listed in hostapd.accept file.
9212 */
9213 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
9214 {
9215 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
9216 }
9217 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
9218 {
9219 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
9220 }
9221 else
9222 {
9223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9224 "%s:Acl Policy : %d is not supported",
9225 __func__, params->acl_policy);
9226 return -ENOTSUPP;
9227 }
9228
9229 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
9230 {
9231 pConfig->num_accept_mac = params->n_acl_entries;
9232 for (i = 0; i < params->n_acl_entries; i++)
9233 {
9234 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9235 "** Add ACL MAC entry %i in WhiletList :"
9236 MAC_ADDRESS_STR, i,
9237 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
9238
9239 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
9240 sizeof(qcmacaddr));
9241 }
9242 }
9243 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
9244 {
9245 pConfig->num_deny_mac = params->n_acl_entries;
9246 for (i = 0; i < params->n_acl_entries; i++)
9247 {
9248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9249 "** Add ACL MAC entry %i in BlackList :"
9250 MAC_ADDRESS_STR, i,
9251 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
9252
9253 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
9254 sizeof(qcmacaddr));
9255 }
9256 }
9257
9258 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
9259 {
9260 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9261 "%s: SAP Set Mac Acl fail", __func__);
9262 return -EINVAL;
9263 }
9264 }
9265 else
9266 {
9267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9268 "%s: Invalid device_mode = %d",
9269 __func__, pAdapter->device_mode);
9270 return -EINVAL;
9271 }
9272
9273 return 0;
9274}
9275
Leo Chang9056f462013-08-01 19:21:11 -07009276#ifdef WLAN_NL80211_TESTMODE
9277#ifdef FEATURE_WLAN_LPHB
Leo Changd9df8aa2013-09-26 13:32:26 -07009278void wlan_hdd_cfg80211_lphb_ind_handler
Leo Chang9056f462013-08-01 19:21:11 -07009279(
9280 void *pAdapter,
9281 void *indCont
9282)
9283{
Leo Changd9df8aa2013-09-26 13:32:26 -07009284 tSirLPHBInd *lphbInd;
9285 struct sk_buff *skb;
Leo Chang9056f462013-08-01 19:21:11 -07009286
9287 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -07009288 "LPHB indication arrived");
Leo Chang9056f462013-08-01 19:21:11 -07009289
9290 if (NULL == indCont)
9291 {
9292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -07009293 "LPHB IND, invalid argument");
Leo Chang9056f462013-08-01 19:21:11 -07009294 return;
9295 }
9296
Leo Changd9df8aa2013-09-26 13:32:26 -07009297 lphbInd = (tSirLPHBInd *)indCont;
Leo Chang9056f462013-08-01 19:21:11 -07009298 skb = cfg80211_testmode_alloc_event_skb(
9299 ((hdd_adapter_t *)pAdapter)->wdev.wiphy,
Leo Changd9df8aa2013-09-26 13:32:26 -07009300 sizeof(tSirLPHBInd),
Leo Chang9056f462013-08-01 19:21:11 -07009301 GFP_ATOMIC);
9302 if (!skb)
9303 {
9304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9305 "LPHB timeout, NL buffer alloc fail");
9306 return;
9307 }
9308
Leo Changac3ba772013-10-07 09:47:04 -07009309 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB))
Leo Changd9df8aa2013-09-26 13:32:26 -07009310 {
9311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9312 "WLAN_HDD_TM_ATTR_CMD put fail");
9313 goto nla_put_failure;
9314 }
Leo Changac3ba772013-10-07 09:47:04 -07009315 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType))
Leo Changd9df8aa2013-09-26 13:32:26 -07009316 {
9317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9318 "WLAN_HDD_TM_ATTR_TYPE put fail");
9319 goto nla_put_failure;
9320 }
Leo Changac3ba772013-10-07 09:47:04 -07009321 if(nla_put(skb, WLAN_HDD_TM_ATTR_DATA,
Leo Changd9df8aa2013-09-26 13:32:26 -07009322 sizeof(tSirLPHBInd), lphbInd))
9323 {
9324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9325 "WLAN_HDD_TM_ATTR_DATA put fail");
9326 goto nla_put_failure;
9327 }
Leo Chang9056f462013-08-01 19:21:11 -07009328 cfg80211_testmode_event(skb, GFP_ATOMIC);
9329 return;
9330
9331nla_put_failure:
9332 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9333 "NLA Put fail");
9334 kfree_skb(skb);
9335
9336 return;
9337}
9338#endif /* FEATURE_WLAN_LPHB */
9339
9340static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
9341{
9342 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
9343 int err = 0;
9344#ifdef FEATURE_WLAN_LPHB
9345 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Leo Changd9df8aa2013-09-26 13:32:26 -07009346 eHalStatus smeStatus;
Leo Chang9056f462013-08-01 19:21:11 -07009347#endif /* FEATURE_WLAN_LPHB */
9348
9349 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
9350 if (err)
9351 {
9352 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9353 "%s Testmode INV ATTR", __func__);
9354 return err;
9355 }
9356
9357 if (!tb[WLAN_HDD_TM_ATTR_CMD])
9358 {
9359 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9360 "%s Testmode INV CMD", __func__);
9361 return -EINVAL;
9362 }
9363
9364 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
9365 {
9366#ifdef FEATURE_WLAN_LPHB
9367 /* Low Power Heartbeat configuration request */
9368 case WLAN_HDD_TM_CMD_WLAN_HB:
9369 {
9370 int buf_len;
9371 void *buf;
9372 tSirLPHBReq *hb_params = NULL;
Amar Singhal05852702014-02-04 14:40:00 -08009373 tSirLPHBReq *hb_params_temp = NULL;
Leo Chang9056f462013-08-01 19:21:11 -07009374
9375 if (!tb[WLAN_HDD_TM_ATTR_DATA])
9376 {
9377 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9378 "%s Testmode INV DATA", __func__);
9379 return -EINVAL;
9380 }
9381
9382 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
9383 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
Amar Singhal05852702014-02-04 14:40:00 -08009384
9385 hb_params_temp =(tSirLPHBReq *)buf;
9386 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID) &&
9387 (hb_params_temp->params.lphbTcpParamReq.timePeriodSec == 0))
9388 return -EINVAL;
9389
Leo Chang9056f462013-08-01 19:21:11 -07009390 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
9391 if (NULL == hb_params)
9392 {
9393 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9394 "%s Request Buffer Alloc Fail", __func__);
9395 return -EINVAL;
9396 }
9397
9398 vos_mem_copy(hb_params, buf, buf_len);
Leo Changd9df8aa2013-09-26 13:32:26 -07009399 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
9400 hb_params,
9401 wlan_hdd_cfg80211_lphb_ind_handler);
9402 if (eHAL_STATUS_SUCCESS != smeStatus)
Leo Chang9056f462013-08-01 19:21:11 -07009403 {
Leo Changd9df8aa2013-09-26 13:32:26 -07009404 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9405 "LPHB Config Fail, disable");
Leo Chang9056f462013-08-01 19:21:11 -07009406 vos_mem_free(hb_params);
9407 }
Leo Chang9056f462013-08-01 19:21:11 -07009408 return 0;
9409 }
9410#endif /* FEATURE_WLAN_LPHB */
9411 default:
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309412 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9413 "%s: unsupported event",__func__);
Leo Chang9056f462013-08-01 19:21:11 -07009414 return -EOPNOTSUPP;
9415 }
9416
9417 return err;
9418}
9419#endif /* CONFIG_NL80211_TESTMODE */
9420
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309421static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
9422 struct net_device *dev,
9423 int idx, struct survey_info *survey)
9424{
9425 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9426 hdd_context_t *pHddCtx;
Mihir Sheted9072e02013-08-21 17:02:29 +05309427 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309428 tHalHandle halHandle;
Mihir Sheted9072e02013-08-21 17:02:29 +05309429 v_U32_t channel = 0, freq = 0; /* Initialization Required */
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309430 v_S7_t snr,rssi;
9431 int status, i, j, filled = 0;
9432
9433 ENTER();
9434
9435
9436 if (NULL == pAdapter)
9437 {
9438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9439 "%s: HDD adapter is Null", __func__);
9440 return -ENODEV;
9441 }
9442
9443 if (NULL == wiphy)
9444 {
9445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9446 "%s: wiphy is Null", __func__);
9447 return -ENODEV;
9448 }
9449
9450 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9451 status = wlan_hdd_validate_context(pHddCtx);
9452
9453 if (0 != status)
9454 {
9455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9456 "%s: HDD context is not valid", __func__);
9457 return status;
9458 }
9459
Mihir Sheted9072e02013-08-21 17:02:29 +05309460 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9461
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309462 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
Mihir Sheted9072e02013-08-21 17:02:29 +05309463 0 != pAdapter->survey_idx ||
9464 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309465 {
9466 /* The survey dump ops when implemented completely is expected to
9467 * return a survey of all channels and the ops is called by the
9468 * kernel with incremental values of the argument 'idx' till it
9469 * returns -ENONET. But we can only support the survey for the
9470 * operating channel for now. survey_idx is used to track
9471 * that the ops is called only once and then return -ENONET for
9472 * the next iteration
9473 */
9474 pAdapter->survey_idx = 0;
9475 return -ENONET;
9476 }
9477
9478 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9479
9480 wlan_hdd_get_snr(pAdapter, &snr);
9481 wlan_hdd_get_rssi(pAdapter, &rssi);
9482
9483 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
9484 hdd_wlan_get_freq(channel, &freq);
9485
9486
9487 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
9488 {
9489 if (NULL == wiphy->bands[i])
9490 {
9491 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
9492 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
9493 continue;
9494 }
9495
9496 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
9497 {
9498 struct ieee80211_supported_band *band = wiphy->bands[i];
9499
9500 if (band->channels[j].center_freq == (v_U16_t)freq)
9501 {
9502 survey->channel = &band->channels[j];
9503 /* The Rx BDs contain SNR values in dB for the received frames
9504 * while the supplicant expects noise. So we calculate and
9505 * return the value of noise (dBm)
9506 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
9507 */
9508 survey->noise = rssi - snr;
9509 survey->filled = SURVEY_INFO_NOISE_DBM;
9510 filled = 1;
9511 }
9512 }
9513 }
9514
9515 if (filled)
9516 pAdapter->survey_idx = 1;
9517 else
9518 {
9519 pAdapter->survey_idx = 0;
9520 return -ENONET;
9521 }
9522
9523 return 0;
9524}
9525
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309526/*
9527 * FUNCTION: wlan_hdd_cfg80211_resume_wlan
9528 * this is called when cfg80211 driver resume
9529 * driver updates latest sched_scan scan result(if any) to cfg80211 database
9530 */
9531int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
9532{
9533 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9534 hdd_adapter_t *pAdapter;
9535 hdd_adapter_list_node_t *pAdapterNode, *pNext;
9536 VOS_STATUS status = VOS_STATUS_SUCCESS;
9537
9538 ENTER();
9539
9540 if ( NULL == pHddCtx )
9541 {
9542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9543 "%s: HddCtx validation failed", __func__);
9544 return 0;
9545 }
9546
9547 if (pHddCtx->isLogpInProgress)
9548 {
9549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9550 "%s: LOGP in Progress. Ignore!!!", __func__);
9551 return 0;
9552 }
9553
9554 if (pHddCtx->isLoadUnloadInProgress)
9555 {
9556 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9557 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
9558 return 0;
9559 }
9560
9561 spin_lock(&pHddCtx->schedScan_lock);
9562 pHddCtx->isWiphySuspended = FALSE;
9563 if (TRUE != pHddCtx->isSchedScanUpdatePending)
9564 {
9565 spin_unlock(&pHddCtx->schedScan_lock);
9566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9567 "%s: Return resume is not due to PNO indication", __func__);
9568 return 0;
9569 }
9570 // Reset flag to avoid updatating cfg80211 data old results again
9571 pHddCtx->isSchedScanUpdatePending = FALSE;
9572 spin_unlock(&pHddCtx->schedScan_lock);
9573
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309574
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309575 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9576
9577 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9578 {
9579 pAdapter = pAdapterNode->pAdapter;
9580 if ( (NULL != pAdapter) &&
9581 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
9582 {
9583 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309584 {
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9586 "%s: NO SCAN result", __func__);
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309587 }
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309588 else
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309589 {
9590 /* Acquire wakelock to handle the case where APP's tries to
9591 * suspend immediately after updating the scan results. Whis
9592 * results in app's is in suspended state and not able to
9593 * process the connect request to AP
9594 */
9595 hdd_prevent_suspend_timeout(2000);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309596 cfg80211_sched_scan_results(pHddCtx->wiphy);
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309597 }
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309598
9599 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9600 "%s : cfg80211 scan result database updated", __func__);
9601
9602 return 0;
9603
9604 }
9605 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9606 pAdapterNode = pNext;
9607 }
9608
9609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9610 "%s: Failed to find Adapter", __func__);
9611 return 0;
9612}
9613
9614/*
9615 * FUNCTION: wlan_hdd_cfg80211_suspend_wlan
9616 * this is called when cfg80211 driver suspends
9617 */
9618int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
9619 struct cfg80211_wowlan *wow)
9620{
9621 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9622
9623 ENTER();
9624 if (NULL == pHddCtx)
9625 {
9626 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9627 "%s: HddCtx validation failed", __func__);
9628 return 0;
9629 }
9630
9631 pHddCtx->isWiphySuspended = TRUE;
9632
9633 EXIT();
9634
9635 return 0;
9636}
9637
Jeff Johnson295189b2012-06-20 16:38:30 -07009638/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309639static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -07009640{
9641 .add_virtual_intf = wlan_hdd_add_virtual_intf,
9642 .del_virtual_intf = wlan_hdd_del_virtual_intf,
9643 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
9644 .change_station = wlan_hdd_change_station,
9645#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
9646 .add_beacon = wlan_hdd_cfg80211_add_beacon,
9647 .del_beacon = wlan_hdd_cfg80211_del_beacon,
9648 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07009649#else
9650 .start_ap = wlan_hdd_cfg80211_start_ap,
9651 .change_beacon = wlan_hdd_cfg80211_change_beacon,
9652 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07009653#endif
9654 .change_bss = wlan_hdd_cfg80211_change_bss,
9655 .add_key = wlan_hdd_cfg80211_add_key,
9656 .get_key = wlan_hdd_cfg80211_get_key,
9657 .del_key = wlan_hdd_cfg80211_del_key,
9658 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08009659#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07009660 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08009661#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009662 .scan = wlan_hdd_cfg80211_scan,
9663 .connect = wlan_hdd_cfg80211_connect,
9664 .disconnect = wlan_hdd_cfg80211_disconnect,
9665 .join_ibss = wlan_hdd_cfg80211_join_ibss,
9666 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
9667 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
9668 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
9669 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07009670 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
9671 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
9672 .mgmt_tx = wlan_hdd_action,
9673#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9674 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
9675 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
9676 .set_txq_params = wlan_hdd_set_txq_params,
9677#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009678 .get_station = wlan_hdd_cfg80211_get_station,
9679 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
9680 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07009681 .add_station = wlan_hdd_cfg80211_add_station,
9682#ifdef FEATURE_WLAN_LFR
9683 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
9684 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
9685 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
9686#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07009687#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
9688 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
9689#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08009690#ifdef FEATURE_WLAN_TDLS
9691 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
9692 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
9693#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309694#ifdef WLAN_FEATURE_GTK_OFFLOAD
9695 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
9696#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05309697#ifdef FEATURE_WLAN_SCAN_PNO
9698 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
9699 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
9700#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309701 .resume = wlan_hdd_cfg80211_resume_wlan,
9702 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05309703 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -07009704#ifdef WLAN_NL80211_TESTMODE
9705 .testmode_cmd = wlan_hdd_cfg80211_testmode,
9706#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309707 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -07009708};
9709