blob: cb5cb4723652eefc98f3bc3307dcc3e51e984e73 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
Kiet Lamaa8e15a2014-02-11 23:30:06 -080023 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
24 * All Rights Reserved.
25 * Qualcomm Atheros Confidential and Proprietary.
Kiet Lam842dad02014-02-18 18:44:02 -080026 *
Kiet Lamaa8e15a2014-02-11 23:30:06 -080027 */
Kiet Lam842dad02014-02-18 18:44:02 -080028
29
Jeff Johnson295189b2012-06-20 16:38:30 -070030/**========================================================================
31
32 \file wlan_hdd_cfg80211.c
33
34 \brief WLAN Host Device Driver implementation
35
Jeff Johnson295189b2012-06-20 16:38:30 -070036 ========================================================================*/
37
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070038/**=========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -070039
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070040 EDIT HISTORY FOR FILE
Jeff Johnson295189b2012-06-20 16:38:30 -070041
42
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070043 This section contains comments describing changes made to the module.
44 Notice that changes are listed in reverse chronological order.
Jeff Johnson295189b2012-06-20 16:38:30 -070045
46
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070047 $Header:$ $DateTime: $ $Author: $
Jeff Johnson295189b2012-06-20 16:38:30 -070048
49
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070050 when who what, where, why
Jeff Johnson295189b2012-06-20 16:38:30 -070051 -------- --- --------------------------------------------------------
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070052 21/12/09 Ashwani Created module.
Jeff Johnson295189b2012-06-20 16:38:30 -070053
54 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070055 Ganesh K
Jeff Johnson295189b2012-06-20 16:38:30 -070056 ==========================================================================*/
57
Jeff Johnson295189b2012-06-20 16:38:30 -070058
59#include <linux/version.h>
60#include <linux/module.h>
61#include <linux/kernel.h>
62#include <linux/init.h>
63#include <linux/wireless.h>
64#include <wlan_hdd_includes.h>
65#include <net/arp.h>
66#include <net/cfg80211.h>
67#include <linux/wireless.h>
68#include <wlan_hdd_wowl.h>
69#include <aniGlobal.h>
70#include "ccmApi.h"
71#include "sirParams.h"
72#include "dot11f.h"
73#include "wlan_hdd_assoc.h"
74#include "wlan_hdd_wext.h"
75#include "sme_Api.h"
76#include "wlan_hdd_p2p.h"
77#include "wlan_hdd_cfg80211.h"
78#include "wlan_hdd_hostapd.h"
79#include "sapInternal.h"
80#include "wlan_hdd_softap_tx_rx.h"
81#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053082#include "wlan_hdd_assoc.h"
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053083#include "wlan_hdd_power.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070084#ifdef WLAN_BTAMP_FEATURE
85#include "bap_hdd_misc.h"
86#endif
87#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -080088#ifdef FEATURE_WLAN_TDLS
89#include "wlan_hdd_tdls.h"
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053090#include "wlan_hdd_wmm.h"
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +053091#include "wlan_qct_wda.h"
Mohit Khanna698ba2a2012-12-04 15:08:18 -080092#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +053093#include "wlan_nv.h"
Leo Chang6fe1f922013-06-07 19:21:24 -070094#include "wlan_hdd_dev_pwr.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070095
96#define g_mode_rates_size (12)
97#define a_mode_rates_size (8)
98#define FREQ_BASE_80211G (2407)
99#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700100#define MAX_SCAN_SSID 9
Kiet Lamac06e2c2013-10-23 16:25:07 +0530101#define MAX_PENDING_LOG 5
Jeff Johnson295189b2012-06-20 16:38:30 -0700102#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
103 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
104
105#define HDD2GHZCHAN(freq, chan, flag) { \
106 .band = IEEE80211_BAND_2GHZ, \
107 .center_freq = (freq), \
108 .hw_value = (chan),\
109 .flags = (flag), \
110 .max_antenna_gain = 0 ,\
111 .max_power = 30, \
112}
113
114#define HDD5GHZCHAN(freq, chan, flag) { \
115 .band = IEEE80211_BAND_5GHZ, \
116 .center_freq = (freq), \
117 .hw_value = (chan),\
118 .flags = (flag), \
119 .max_antenna_gain = 0 ,\
120 .max_power = 30, \
121}
122
123#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
124{\
125 .bitrate = rate, \
126 .hw_value = rate_id, \
127 .flags = flag, \
128}
129
Lee Hoonkic1262f22013-01-24 21:59:00 -0800130#ifndef WLAN_FEATURE_TDLS_DEBUG
131#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
132#else
133#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
134#endif
135
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530136#ifdef WLAN_FEATURE_VOWIFI_11R
137#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
138#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
139#endif
140
Naresh Jayaram3180aa42014-02-12 21:47:26 +0530141#define HDD_CHANNEL_14 14
142
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530143static const u32 hdd_cipher_suites[] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700144{
145 WLAN_CIPHER_SUITE_WEP40,
146 WLAN_CIPHER_SUITE_WEP104,
147 WLAN_CIPHER_SUITE_TKIP,
148#ifdef FEATURE_WLAN_CCX
149#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
150 WLAN_CIPHER_SUITE_KRK,
151 WLAN_CIPHER_SUITE_CCMP,
152#else
153 WLAN_CIPHER_SUITE_CCMP,
154#endif
155#ifdef FEATURE_WLAN_WAPI
156 WLAN_CIPHER_SUITE_SMS4,
157#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700158#ifdef WLAN_FEATURE_11W
159 WLAN_CIPHER_SUITE_AES_CMAC,
160#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700161};
162
163static inline int is_broadcast_ether_addr(const u8 *addr)
164{
165 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
166 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
167}
168
169static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530170{
Jeff Johnson295189b2012-06-20 16:38:30 -0700171 HDD2GHZCHAN(2412, 1, 0) ,
172 HDD2GHZCHAN(2417, 2, 0) ,
173 HDD2GHZCHAN(2422, 3, 0) ,
174 HDD2GHZCHAN(2427, 4, 0) ,
175 HDD2GHZCHAN(2432, 5, 0) ,
176 HDD2GHZCHAN(2437, 6, 0) ,
177 HDD2GHZCHAN(2442, 7, 0) ,
178 HDD2GHZCHAN(2447, 8, 0) ,
179 HDD2GHZCHAN(2452, 9, 0) ,
180 HDD2GHZCHAN(2457, 10, 0) ,
181 HDD2GHZCHAN(2462, 11, 0) ,
182 HDD2GHZCHAN(2467, 12, 0) ,
183 HDD2GHZCHAN(2472, 13, 0) ,
184 HDD2GHZCHAN(2484, 14, 0) ,
185};
186
Jeff Johnson295189b2012-06-20 16:38:30 -0700187static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
188{
189 HDD2GHZCHAN(2412, 1, 0) ,
190 HDD2GHZCHAN(2437, 6, 0) ,
191 HDD2GHZCHAN(2462, 11, 0) ,
192};
Jeff Johnson295189b2012-06-20 16:38:30 -0700193
194static struct ieee80211_channel hdd_channels_5_GHZ[] =
195{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700196 HDD5GHZCHAN(4920, 240, 0) ,
197 HDD5GHZCHAN(4940, 244, 0) ,
198 HDD5GHZCHAN(4960, 248, 0) ,
199 HDD5GHZCHAN(4980, 252, 0) ,
200 HDD5GHZCHAN(5040, 208, 0) ,
201 HDD5GHZCHAN(5060, 212, 0) ,
202 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700203 HDD5GHZCHAN(5180, 36, 0) ,
204 HDD5GHZCHAN(5200, 40, 0) ,
205 HDD5GHZCHAN(5220, 44, 0) ,
206 HDD5GHZCHAN(5240, 48, 0) ,
207 HDD5GHZCHAN(5260, 52, 0) ,
208 HDD5GHZCHAN(5280, 56, 0) ,
209 HDD5GHZCHAN(5300, 60, 0) ,
210 HDD5GHZCHAN(5320, 64, 0) ,
211 HDD5GHZCHAN(5500,100, 0) ,
212 HDD5GHZCHAN(5520,104, 0) ,
213 HDD5GHZCHAN(5540,108, 0) ,
214 HDD5GHZCHAN(5560,112, 0) ,
215 HDD5GHZCHAN(5580,116, 0) ,
216 HDD5GHZCHAN(5600,120, 0) ,
217 HDD5GHZCHAN(5620,124, 0) ,
218 HDD5GHZCHAN(5640,128, 0) ,
219 HDD5GHZCHAN(5660,132, 0) ,
220 HDD5GHZCHAN(5680,136, 0) ,
221 HDD5GHZCHAN(5700,140, 0) ,
Leo Chang80de3c22013-11-26 10:52:12 -0800222#ifdef FEATURE_WLAN_CH144
223 HDD5GHZCHAN(5720,144, 0) ,
224#endif /* FEATURE_WLAN_CH144 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 HDD5GHZCHAN(5745,149, 0) ,
226 HDD5GHZCHAN(5765,153, 0) ,
227 HDD5GHZCHAN(5785,157, 0) ,
228 HDD5GHZCHAN(5805,161, 0) ,
229 HDD5GHZCHAN(5825,165, 0) ,
230};
231
232static struct ieee80211_rate g_mode_rates[] =
233{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530234 HDD_G_MODE_RATETAB(10, 0x1, 0),
235 HDD_G_MODE_RATETAB(20, 0x2, 0),
236 HDD_G_MODE_RATETAB(55, 0x4, 0),
237 HDD_G_MODE_RATETAB(110, 0x8, 0),
238 HDD_G_MODE_RATETAB(60, 0x10, 0),
239 HDD_G_MODE_RATETAB(90, 0x20, 0),
240 HDD_G_MODE_RATETAB(120, 0x40, 0),
241 HDD_G_MODE_RATETAB(180, 0x80, 0),
242 HDD_G_MODE_RATETAB(240, 0x100, 0),
243 HDD_G_MODE_RATETAB(360, 0x200, 0),
244 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700245 HDD_G_MODE_RATETAB(540, 0x800, 0),
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530246};
Jeff Johnson295189b2012-06-20 16:38:30 -0700247
248static struct ieee80211_rate a_mode_rates[] =
249{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530250 HDD_G_MODE_RATETAB(60, 0x10, 0),
251 HDD_G_MODE_RATETAB(90, 0x20, 0),
252 HDD_G_MODE_RATETAB(120, 0x40, 0),
253 HDD_G_MODE_RATETAB(180, 0x80, 0),
254 HDD_G_MODE_RATETAB(240, 0x100, 0),
255 HDD_G_MODE_RATETAB(360, 0x200, 0),
256 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 HDD_G_MODE_RATETAB(540, 0x800, 0),
258};
259
260static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
261{
262 .channels = hdd_channels_2_4_GHZ,
263 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
264 .band = IEEE80211_BAND_2GHZ,
265 .bitrates = g_mode_rates,
266 .n_bitrates = g_mode_rates_size,
267 .ht_cap.ht_supported = 1,
268 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
269 | IEEE80211_HT_CAP_GRN_FLD
270 | IEEE80211_HT_CAP_DSSSCCK40
271 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
272 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
273 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
274 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
275 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
276 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
277};
278
Jeff Johnson295189b2012-06-20 16:38:30 -0700279static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
280{
281 .channels = hdd_social_channels_2_4_GHZ,
282 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
283 .band = IEEE80211_BAND_2GHZ,
284 .bitrates = g_mode_rates,
285 .n_bitrates = g_mode_rates_size,
286 .ht_cap.ht_supported = 1,
287 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
288 | IEEE80211_HT_CAP_GRN_FLD
289 | IEEE80211_HT_CAP_DSSSCCK40
290 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
291 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
292 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
293 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
294 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
295 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
296};
Jeff Johnson295189b2012-06-20 16:38:30 -0700297
298static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
299{
300 .channels = hdd_channels_5_GHZ,
301 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
302 .band = IEEE80211_BAND_5GHZ,
303 .bitrates = a_mode_rates,
304 .n_bitrates = a_mode_rates_size,
305 .ht_cap.ht_supported = 1,
306 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
307 | IEEE80211_HT_CAP_GRN_FLD
308 | IEEE80211_HT_CAP_DSSSCCK40
309 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
310 | IEEE80211_HT_CAP_SGI_40
311 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
312 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
313 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
314 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
315 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
316 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
317};
318
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530319/* This structure contain information what kind of frame are expected in
Jeff Johnson295189b2012-06-20 16:38:30 -0700320 TX/RX direction for each kind of interface */
321static const struct ieee80211_txrx_stypes
322wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
323 [NL80211_IFTYPE_STATION] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ACTION) |
326 BIT(SIR_MAC_MGMT_PROBE_REQ),
327 },
328 [NL80211_IFTYPE_AP] = {
329 .tx = 0xffff,
330 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
331 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
332 BIT(SIR_MAC_MGMT_PROBE_REQ) |
333 BIT(SIR_MAC_MGMT_DISASSOC) |
334 BIT(SIR_MAC_MGMT_AUTH) |
335 BIT(SIR_MAC_MGMT_DEAUTH) |
336 BIT(SIR_MAC_MGMT_ACTION),
337 },
Jeff Johnsonbc006202013-04-29 14:05:30 -0700338 [NL80211_IFTYPE_ADHOC] = {
339 .tx = 0xffff,
340 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
341 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
342 BIT(SIR_MAC_MGMT_PROBE_REQ) |
343 BIT(SIR_MAC_MGMT_DISASSOC) |
344 BIT(SIR_MAC_MGMT_AUTH) |
345 BIT(SIR_MAC_MGMT_DEAUTH) |
346 BIT(SIR_MAC_MGMT_ACTION),
347 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700348 [NL80211_IFTYPE_P2P_CLIENT] = {
349 .tx = 0xffff,
350 .rx = BIT(SIR_MAC_MGMT_ACTION) |
351 BIT(SIR_MAC_MGMT_PROBE_REQ),
352 },
353 [NL80211_IFTYPE_P2P_GO] = {
354 /* This is also same as for SoftAP */
355 .tx = 0xffff,
356 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
357 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
358 BIT(SIR_MAC_MGMT_PROBE_REQ) |
359 BIT(SIR_MAC_MGMT_DISASSOC) |
360 BIT(SIR_MAC_MGMT_AUTH) |
361 BIT(SIR_MAC_MGMT_DEAUTH) |
362 BIT(SIR_MAC_MGMT_ACTION),
363 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700364};
365
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800366#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800367static const struct ieee80211_iface_limit
368wlan_hdd_iface_limit[] = {
369 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800370 /* max = 3 ; Our driver create two interfaces during driver init
371 * wlan0 and p2p0 interfaces. p2p0 is considered as station
372 * interface until a group is formed. In JB architecture, once the
373 * group is formed, interface type of p2p0 is changed to P2P GO or
374 * Client.
375 * When supplicant remove the group, it first issue a set interface
376 * cmd to change the mode back to Station. In JB this works fine as
377 * we advertize two station type interface during driver init.
378 * Some vendors create separate interface for P2P GO/Client,
379 * after group formation(Third one). But while group remove
380 * supplicant first tries to change the mode(3rd interface) to STATION
381 * But as we advertized only two sta type interfaces nl80211 was
382 * returning error for the third one which was leading to failure in
383 * delete interface. Ideally while removing the group, supplicant
384 * should not try to change the 3rd interface mode to Station type.
385 * Till we get a fix in wpa_supplicant, we advertize max STA
386 * interface type to 3
387 */
388 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800389 .types = BIT(NL80211_IFTYPE_STATION),
390 },
391 {
392 .max = 1,
Jeff Johnsonbc006202013-04-29 14:05:30 -0700393 .types = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP),
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800394 },
395 {
396 .max = 1,
397 .types = BIT(NL80211_IFTYPE_P2P_GO) |
398 BIT(NL80211_IFTYPE_P2P_CLIENT),
399 },
400};
401
402/* By default, only single channel concurrency is allowed */
403static struct ieee80211_iface_combination
404wlan_hdd_iface_combination = {
405 .limits = wlan_hdd_iface_limit,
406 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800407 /*
408 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
409 * and p2p0 interfaces during driver init
410 * Some vendors create separate interface for P2P operations.
411 * wlan0: STA interface
412 * p2p0: P2P Device interface, action frames goes
413 * through this interface.
414 * p2p-xx: P2P interface, After GO negotiation this interface is
415 * created for p2p operations(GO/CLIENT interface).
416 */
417 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800418 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
419 .beacon_int_infra_match = false,
420};
421#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800422
Jeff Johnson295189b2012-06-20 16:38:30 -0700423static struct cfg80211_ops wlan_hdd_cfg80211_ops;
424
425/* Data rate 100KBPS based on IE Index */
426struct index_data_rate_type
427{
428 v_U8_t beacon_rate_index;
429 v_U16_t supported_rate[4];
430};
431
432/* 11B, 11G Rate table include Basic rate and Extended rate
433 The IDX field is the rate index
434 The HI field is the rate when RSSI is strong or being ignored
435 (in this case we report actual rate)
436 The MID field is the rate when RSSI is moderate
437 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
438 The LO field is the rate when RSSI is low
439 (in this case we don't report rates, actual current rate used)
440 */
441static const struct
442{
443 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700444 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700445} supported_data_rate[] =
446{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700447/* IDX HI HM LM LO (RSSI-based index */
448 {2, { 10, 10, 10, 0}},
449 {4, { 20, 20, 10, 0}},
450 {11, { 55, 20, 10, 0}},
451 {12, { 60, 55, 20, 0}},
452 {18, { 90, 55, 20, 0}},
453 {22, {110, 55, 20, 0}},
454 {24, {120, 90, 60, 0}},
455 {36, {180, 120, 60, 0}},
456 {44, {220, 180, 60, 0}},
457 {48, {240, 180, 90, 0}},
458 {66, {330, 180, 90, 0}},
459 {72, {360, 240, 90, 0}},
460 {96, {480, 240, 120, 0}},
461 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700462};
463
464/* MCS Based rate table */
465static struct index_data_rate_type supported_mcs_rate[] =
466{
467/* MCS L20 L40 S20 S40 */
468 {0, {65, 135, 72, 150}},
469 {1, {130, 270, 144, 300}},
470 {2, {195, 405, 217, 450}},
471 {3, {260, 540, 289, 600}},
472 {4, {390, 810, 433, 900}},
473 {5, {520, 1080, 578, 1200}},
474 {6, {585, 1215, 650, 1350}},
475 {7, {650, 1350, 722, 1500}}
476};
477
Leo Chang6f8870f2013-03-26 18:11:36 -0700478#ifdef WLAN_FEATURE_11AC
479
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530480#define DATA_RATE_11AC_MCS_MASK 0x03
Leo Chang6f8870f2013-03-26 18:11:36 -0700481
482struct index_vht_data_rate_type
483{
484 v_U8_t beacon_rate_index;
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530485 v_U16_t supported_VHT80_rate[2];
486 v_U16_t supported_VHT40_rate[2];
487 v_U16_t supported_VHT20_rate[2];
Leo Chang6f8870f2013-03-26 18:11:36 -0700488};
489
490typedef enum
491{
492 DATA_RATE_11AC_MAX_MCS_7,
493 DATA_RATE_11AC_MAX_MCS_8,
494 DATA_RATE_11AC_MAX_MCS_9,
495 DATA_RATE_11AC_MAX_MCS_NA
496} eDataRate11ACMaxMcs;
497
498/* MCS Based VHT rate table */
499static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
500{
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530501/* MCS L80 S80 L40 S40 L20 S40*/
502 {0, {293, 325}, {135, 150}, {65, 72}},
503 {1, {585, 650}, {270, 300}, {130, 144}},
504 {2, {878, 975}, {405, 450}, {195, 217}},
505 {3, {1170, 1300}, {540, 600}, {260, 289}},
506 {4, {1755, 1950}, {810, 900}, {390, 433}},
507 {5, {2340, 2600}, {1080, 1200}, {520, 578}},
508 {6, {2633, 2925}, {1215, 1350}, {585, 650}},
509 {7, {2925, 3250}, {1350, 1500}, {650, 722}},
510 {8, {3510, 3900}, {1620, 1800}, {780, 867}},
511 {9, {3900, 4333}, {1800, 2000}, {780, 867}}
Leo Chang6f8870f2013-03-26 18:11:36 -0700512};
513#endif /* WLAN_FEATURE_11AC */
514
Jeff Johnson295189b2012-06-20 16:38:30 -0700515extern struct net_device_ops net_ops_struct;
516
Leo Chang9056f462013-08-01 19:21:11 -0700517#ifdef WLAN_NL80211_TESTMODE
518enum wlan_hdd_tm_attr
519{
520 WLAN_HDD_TM_ATTR_INVALID = 0,
521 WLAN_HDD_TM_ATTR_CMD = 1,
522 WLAN_HDD_TM_ATTR_DATA = 2,
523 WLAN_HDD_TM_ATTR_TYPE = 3,
524 /* keep last */
525 WLAN_HDD_TM_ATTR_AFTER_LAST,
526 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
527};
528
529enum wlan_hdd_tm_cmd
530{
531 WLAN_HDD_TM_CMD_WLAN_HB = 1,
532};
533
534#define WLAN_HDD_TM_DATA_MAX_LEN 5000
535
536static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] =
537{
538 [WLAN_HDD_TM_ATTR_CMD] = { .type = NLA_U32 },
539 [WLAN_HDD_TM_ATTR_DATA] = { .type = NLA_BINARY,
540 .len = WLAN_HDD_TM_DATA_MAX_LEN },
541};
542#endif /* WLAN_NL80211_TESTMODE */
543
Rajesh Chauhan98a31f82014-01-06 20:15:25 -0800544#ifdef FEATURE_WLAN_CH_AVOID
545/*
546 * FUNCTION: wlan_hdd_send_avoid_freq_event
547 * This is called when wlan driver needs to send vendor specific
548 * avoid frequency range event to userspace
549 */
550int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
551 tHddAvoidFreqList *pAvoidFreqList)
552{
553 struct sk_buff *vendor_event;
554
555 ENTER();
556
557 if (!pHddCtx)
558 {
559 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
560 "%s: HDD context is null", __func__);
561 return -1;
562 }
563
564 if (!pAvoidFreqList)
565 {
566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
567 "%s: pAvoidFreqList is null", __func__);
568 return -1;
569 }
570
571 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
572 sizeof(tHddAvoidFreqList),
573 QCOM_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
574 GFP_KERNEL);
575 if (!vendor_event)
576 {
577 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
578 "%s: cfg80211_vendor_event_alloc failed", __func__);
579 return -1;
580 }
581
582 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
583 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
584
585 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
586
587 EXIT();
588 return 0;
589}
590#endif /* FEATURE_WLAN_CH_AVOID */
591
592/* vendor specific events */
593static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
594{
595#ifdef FEATURE_WLAN_CH_AVOID
596 {
597 .vendor_id = QCOM_NL80211_VENDOR_ID,
598 .subcmd = QCOM_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
599 },
600#endif /* FEATURE_WLAN_CH_AVOID */
601};
602
Jeff Johnson295189b2012-06-20 16:38:30 -0700603/*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530604 * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530605 * This function is called by hdd_wlan_startup()
606 * during initialization.
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530607 * This function is used to allocate wiphy structure.
Jeff Johnson295189b2012-06-20 16:38:30 -0700608 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530609struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size)
Jeff Johnson295189b2012-06-20 16:38:30 -0700610{
611 struct wiphy *wiphy;
612 ENTER();
613
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530614 /*
615 * Create wiphy device
Jeff Johnson295189b2012-06-20 16:38:30 -0700616 */
617 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
618
619 if (!wiphy)
620 {
621 /* Print error and jump into err label and free the memory */
622 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
623 return NULL;
624 }
625
626 return wiphy;
627}
628
629/*
630 * FUNCTION: wlan_hdd_cfg80211_update_band
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530631 * This function is called from the supplicant through a
Jeff Johnson295189b2012-06-20 16:38:30 -0700632 * private ioctl to change the band value
633 */
634int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
635{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530636 int i, j;
637 eNVChannelEnabledType channelEnabledState;
638
Jeff Johnsone7245742012-09-05 17:12:55 -0700639 ENTER();
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530640 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
Jeff Johnson295189b2012-06-20 16:38:30 -0700641 {
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530642
643 if (NULL == wiphy->bands[i])
644 {
645 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
646 __func__, i);
647 continue;
648 }
649
650 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
651 {
652 struct ieee80211_supported_band *band = wiphy->bands[i];
653
654 channelEnabledState = vos_nv_getChannelEnabledState(
655 band->channels[j].hw_value);
656
657 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only
658 {
659 // Enable Social channels for P2P
660 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) &&
661 NV_CHANNEL_ENABLE == channelEnabledState)
662 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
663 else
664 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
665 continue;
666 }
667 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only
668 {
669 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
670 continue;
671 }
672
673 if (NV_CHANNEL_DISABLE == channelEnabledState ||
674 NV_CHANNEL_INVALID == channelEnabledState)
675 {
676 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
677 }
678 else if (NV_CHANNEL_DFS == channelEnabledState)
679 {
680 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
681 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
682 }
683 else
684 {
685 band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
686 |IEEE80211_CHAN_RADAR);
687 }
688 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700689 }
690 return 0;
691}
692/*
693 * FUNCTION: wlan_hdd_cfg80211_init
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530694 * This function is called by hdd_wlan_startup()
695 * during initialization.
Jeff Johnson295189b2012-06-20 16:38:30 -0700696 * This function is used to initialize and register wiphy structure.
697 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530698int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700699 struct wiphy *wiphy,
700 hdd_config_t *pCfg
701 )
702{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530703 int i, j;
Jeff Johnsone7245742012-09-05 17:12:55 -0700704 ENTER();
705
Jeff Johnson295189b2012-06-20 16:38:30 -0700706 /* Now bind the underlying wlan device with wiphy */
707 set_wiphy_dev(wiphy, dev);
708
709 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700710
Kiet Lam6c583332013-10-14 05:37:09 +0530711#ifndef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -0700712 /* the flag for the other case would be initialzed in
713 vos_init_wiphy_from_nv_bin */
Amar Singhal0a402232013-10-11 20:57:16 -0700714 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
Kiet Lam6c583332013-10-14 05:37:09 +0530715#endif
Amar Singhala49cbc52013-10-08 18:37:44 -0700716
Amar Singhalfddc28c2013-09-05 13:03:40 -0700717 /* This will disable updating of NL channels from passive to
718 * active if a beacon is received on passive channel. */
719 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhalf0073192013-09-20 12:34:56 -0700720
Amar Singhalfddc28c2013-09-05 13:03:40 -0700721
Amar Singhala49cbc52013-10-08 18:37:44 -0700722
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700723#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700724 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
725 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
726 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700727 | WIPHY_FLAG_OFFCHAN_TX;
Kiet Lam6c583332013-10-14 05:37:09 +0530728 wiphy->country_ie_pref = NL80211_COUNTRY_IE_IGNORE_CORE;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700729#endif
Amar Singhala49cbc52013-10-08 18:37:44 -0700730
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700731#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
732 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -0800733#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -0700734 || pCfg->isFastRoamIniFeatureEnabled
735#endif
736#ifdef FEATURE_WLAN_CCX
737 || pCfg->isCcxIniFeatureEnabled
738#endif
739 )
740 {
741 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
742 }
James Zmuda77fb5ae2013-01-29 08:00:17 -0800743#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800744#ifdef FEATURE_WLAN_TDLS
745 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
746 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
747#endif
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530748#ifdef FEATURE_WLAN_SCAN_PNO
Hardik Kantilal Patel3dfd8792013-11-13 20:34:57 +0530749 if (pCfg->configPNOScanSupport)
750 {
751 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
752 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
753 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
754 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
755 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +0530756#endif/*FEATURE_WLAN_SCAN_PNO*/
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800757
Amar Singhalfddc28c2013-09-05 13:03:40 -0700758#ifdef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700759 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
760 driver can still register regulatory callback and
Amar Singhalfddc28c2013-09-05 13:03:40 -0700761 it will get regulatory settings in wiphy->band[], but
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700762 driver need to determine what to do with both
763 regulatory settings */
Amar Singhalfddc28c2013-09-05 13:03:40 -0700764
765 wiphy->reg_notifier = wlan_hdd_linux_reg_notifier;
Amar Singhala49cbc52013-10-08 18:37:44 -0700766#else
767 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Amar Singhalfddc28c2013-09-05 13:03:40 -0700768#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700769
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530770 wiphy->max_scan_ssids = MAX_SCAN_SSID;
771
Madan Mohan Koyyalamudi6815b162013-07-19 17:17:46 +0530772 wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Jeff Johnson295189b2012-06-20 16:38:30 -0700773
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +0530774 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
775
Jeff Johnson295189b2012-06-20 16:38:30 -0700776 /* Supports STATION & AD-HOC modes right now */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530777 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -0700778 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700779 | BIT(NL80211_IFTYPE_P2P_CLIENT)
780 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700781 | BIT(NL80211_IFTYPE_AP);
782
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800783#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800784 if( pCfg->enableMCC )
785 {
786 /* Currently, supports up to two channels */
787 wlan_hdd_iface_combination.num_different_channels = 2;
788
789 if( !pCfg->allowMCCGODiffBI )
790 wlan_hdd_iface_combination.beacon_int_infra_match = true;
791
792 }
793 wiphy->iface_combinations = &wlan_hdd_iface_combination;
794 wiphy->n_iface_combinations = 1;
795#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800796
Jeff Johnson295189b2012-06-20 16:38:30 -0700797 /* Before registering we need to update the ht capabilitied based
798 * on ini values*/
799 if( !pCfg->ShortGI20MhzEnable )
800 {
801 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
802 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
803 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
804 }
805
806 if( !pCfg->ShortGI40MhzEnable )
807 {
808 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
809 }
810
811 if( !pCfg->nChannelBondingMode5GHz )
812 {
813 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
814 }
815
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +0530816 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
817 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
818
819 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
820 {
821
822 if (NULL == wiphy->bands[i])
823 {
824 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
825 __func__, i);
826 continue;
827 }
828
829 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
830 {
831 struct ieee80211_supported_band *band = wiphy->bands[i];
832
833 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
834 {
835 // Enable social channels for P2P
836 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
837 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
838 else
839 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
840 continue;
841 }
842 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
843 {
844 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
845 continue;
846 }
847 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700848 }
849 /*Initialise the supported cipher suite details*/
850 wiphy->cipher_suites = hdd_cipher_suites;
851 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
852
853 /*signal strength in mBm (100*dBm) */
854 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
855
856#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700857 wiphy->max_remain_on_channel_duration = 1000;
858#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700859
Rajesh Chauhan98a31f82014-01-06 20:15:25 -0800860 wiphy->n_vendor_commands = 0;
861 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
862 wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
863
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530864 EXIT();
865 return 0;
866}
867
868/* In this function we are registering wiphy. */
869int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
870{
871 ENTER();
872 /* Register our wiphy dev with cfg80211 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700873 if (0 > wiphy_register(wiphy))
874 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530875 /* print error */
Jeff Johnson295189b2012-06-20 16:38:30 -0700876 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
877 return -EIO;
878 }
879
880 EXIT();
881 return 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530882}
Jeff Johnson295189b2012-06-20 16:38:30 -0700883
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530884/* In this function we are updating channel list when,
885 regulatory domain is FCC and country code is US.
886 Here In FCC standard 5GHz UNII-1 Bands are indoor only.
887 As per FCC smart phone is not a indoor device.
888 GO should not opeate on indoor channels */
889void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy)
890{
891 int j;
892 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
893 tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE;
894 //Default counrtycode from NV at the time of wiphy initialization.
895 if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal,
896 &defaultCountryCode[0]))
897 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700898 hddLog(LOGE, FL("Failed to get default country code from NV"));
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530899 }
900 if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S'))
901 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +0530902 if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ])
903 {
904 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ );
905 return;
906 }
907 for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
908 {
909 struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ];
910 // Mark UNII -1 band channel as passive
911 if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq))
912 band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
913 }
914 }
915}
916
Jeff Johnson295189b2012-06-20 16:38:30 -0700917/* In this function we will do all post VOS start initialization.
918 In this function we will register for all frame in which supplicant
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530919 is interested.
Jeff Johnson295189b2012-06-20 16:38:30 -0700920*/
921void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
922{
Jeff Johnson295189b2012-06-20 16:38:30 -0700923 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
924 /* Register for all P2P action, public action etc frames */
925 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
926
Jeff Johnsone7245742012-09-05 17:12:55 -0700927 ENTER();
928
Jeff Johnson295189b2012-06-20 16:38:30 -0700929 /* Right now we are registering these frame when driver is getting
930 initialized. Once we will move to 2.6.37 kernel, in which we have
931 frame register ops, we will move this code as a part of that */
932 /* GAS Initial Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530933 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Jeff Johnson295189b2012-06-20 16:38:30 -0700934 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
935
936 /* GAS Initial Response */
937 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
938 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530939
Jeff Johnson295189b2012-06-20 16:38:30 -0700940 /* GAS Comeback Request */
941 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
942 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
943
944 /* GAS Comeback Response */
945 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
946 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
947
948 /* P2P Public Action */
949 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530950 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -0700951 P2P_PUBLIC_ACTION_FRAME_SIZE );
952
953 /* P2P Action */
954 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
955 (v_U8_t*)P2P_ACTION_FRAME,
956 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -0700957
Gopichand Nakkalae3d56e72013-04-21 23:33:32 +0530958 /* WNM BSS Transition Request frame */
959 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
960 (v_U8_t*)WNM_BSS_ACTION_FRAME,
961 WNM_BSS_ACTION_FRAME_SIZE );
962
Chet Lanctot186b5732013-03-18 10:26:30 -0700963#ifdef WLAN_FEATURE_11W
964 /* SA Query Response Action Frame */
965 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
966 (v_U8_t*)SA_QUERY_FRAME_RSP,
967 SA_QUERY_FRAME_RSP_SIZE );
968#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -0700969}
970
971void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
972{
Jeff Johnson295189b2012-06-20 16:38:30 -0700973 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
974 /* Register for all P2P action, public action etc frames */
975 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
976
Jeff Johnsone7245742012-09-05 17:12:55 -0700977 ENTER();
978
Jeff Johnson295189b2012-06-20 16:38:30 -0700979 /* Right now we are registering these frame when driver is getting
980 initialized. Once we will move to 2.6.37 kernel, in which we have
981 frame register ops, we will move this code as a part of that */
982 /* GAS Initial Request */
983
984 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
985 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
986
987 /* GAS Initial Response */
988 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
989 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530990
Jeff Johnson295189b2012-06-20 16:38:30 -0700991 /* GAS Comeback Request */
992 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
993 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
994
995 /* GAS Comeback Response */
996 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
997 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
998
999 /* P2P Public Action */
1000 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301001 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -07001002 P2P_PUBLIC_ACTION_FRAME_SIZE );
1003
1004 /* P2P Action */
1005 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
1006 (v_U8_t*)P2P_ACTION_FRAME,
1007 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -07001008
1009#ifdef WLAN_FEATURE_11W
1010 /* SA Query Response Action Frame */
1011 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
1012 (v_U8_t*)SA_QUERY_FRAME_RSP,
1013 SA_QUERY_FRAME_RSP_SIZE );
1014#endif /* WLAN_FEATURE_11W */
Jeff Johnson295189b2012-06-20 16:38:30 -07001015}
1016
1017#ifdef FEATURE_WLAN_WAPI
1018void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
1019 const u8 *mac_addr, u8 *key , int key_Len)
1020{
1021 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1022 tCsrRoamSetKey setKey;
1023 v_BOOL_t isConnected = TRUE;
1024 int status = 0;
1025 v_U32_t roamId= 0xFF;
1026 tANI_U8 *pKeyPtr = NULL;
1027 int n = 0;
1028
Arif Hussain6d2a3322013-11-17 19:50:10 -08001029 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001030 __func__,pAdapter->device_mode);
1031
Gopichand Nakkalae7480202013-02-11 15:24:22 +05301032 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -07001033 setKey.keyId = key_index; // Store Key ID
1034 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
1035 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
1036 setKey.paeRole = 0 ; // the PAE role
1037 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
1038 {
1039 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
1040 }
1041 else
1042 {
1043 isConnected = hdd_connIsConnected(pHddStaCtx);
1044 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
1045 }
1046 setKey.keyLength = key_Len;
1047 pKeyPtr = setKey.Key;
1048 memcpy( pKeyPtr, key, key_Len);
1049
Arif Hussain6d2a3322013-11-17 19:50:10 -08001050 hddLog(VOS_TRACE_LEVEL_INFO,"%s: WAPI KEY LENGTH:0x%04x",
Jeff Johnson295189b2012-06-20 16:38:30 -07001051 __func__, key_Len);
1052 for (n = 0 ; n < key_Len; n++)
1053 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
1054 __func__,n,setKey.Key[n]);
1055
1056 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
1057 if ( isConnected )
1058 {
1059 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
1060 pAdapter->sessionId, &setKey, &roamId );
1061 }
1062 if ( status != 0 )
1063 {
1064 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1065 "[%4d] sme_RoamSetKey returned ERROR status= %d",
1066 __LINE__, status );
1067 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
1068 }
1069}
1070#endif /* FEATURE_WLAN_WAPI*/
1071
1072#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301073int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07001074 beacon_data_t **ppBeacon,
1075 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001076#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301077int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001078 beacon_data_t **ppBeacon,
1079 struct cfg80211_beacon_data *params,
1080 int dtim_period)
1081#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301082{
Jeff Johnson295189b2012-06-20 16:38:30 -07001083 int size;
1084 beacon_data_t *beacon = NULL;
1085 beacon_data_t *old = NULL;
1086 int head_len,tail_len;
1087
Jeff Johnsone7245742012-09-05 17:12:55 -07001088 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001089 if (params->head && !params->head_len)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301090 {
1091 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1092 FL("head_len is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001093 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301094 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001095
1096 old = pAdapter->sessionCtx.ap.beacon;
1097
1098 if (!params->head && !old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301099 {
1100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1101 FL("session(%d) old and new heads points to NULL"),
1102 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301104 }
1105
1106 if (params->tail && !params->tail_len)
1107 {
1108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1109 FL("tail_len is zero but tail is not NULL"));
1110 return -EINVAL;
1111 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001112
Jeff Johnson295189b2012-06-20 16:38:30 -07001113#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
1114 /* Kernel 3.0 is not updating dtim_period for set beacon */
1115 if (!params->dtim_period)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301116 {
1117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1118 FL("dtim period is 0"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001119 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301120 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001121#endif
1122
1123 if(params->head)
1124 head_len = params->head_len;
1125 else
1126 head_len = old->head_len;
1127
1128 if(params->tail || !old)
1129 tail_len = params->tail_len;
1130 else
1131 tail_len = old->tail_len;
1132
1133 size = sizeof(beacon_data_t) + head_len + tail_len;
1134
1135 beacon = kzalloc(size, GFP_KERNEL);
1136
1137 if( beacon == NULL )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301138 {
1139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1140 FL("Mem allocation for beacon failed"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001141 return -ENOMEM;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301142 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001143
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001144#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001145 if(params->dtim_period || !old )
1146 beacon->dtim_period = params->dtim_period;
1147 else
1148 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001149#else
1150 if(dtim_period || !old )
1151 beacon->dtim_period = dtim_period;
1152 else
1153 beacon->dtim_period = old->dtim_period;
1154#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301155
Jeff Johnson295189b2012-06-20 16:38:30 -07001156 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
1157 beacon->tail = beacon->head + head_len;
1158 beacon->head_len = head_len;
1159 beacon->tail_len = tail_len;
1160
1161 if(params->head) {
1162 memcpy (beacon->head,params->head,beacon->head_len);
1163 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301164 else {
Jeff Johnson295189b2012-06-20 16:38:30 -07001165 if(old)
1166 memcpy (beacon->head,old->head,beacon->head_len);
1167 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301168
Jeff Johnson295189b2012-06-20 16:38:30 -07001169 if(params->tail) {
1170 memcpy (beacon->tail,params->tail,beacon->tail_len);
1171 }
1172 else {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301173 if(old)
Jeff Johnson295189b2012-06-20 16:38:30 -07001174 memcpy (beacon->tail,old->tail,beacon->tail_len);
1175 }
1176
1177 *ppBeacon = beacon;
1178
1179 kfree(old);
1180
1181 return 0;
1182
1183}
Jeff Johnson295189b2012-06-20 16:38:30 -07001184
1185v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
1186{
1187 int left = length;
1188 v_U8_t *ptr = pIes;
1189 v_U8_t elem_id,elem_len;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301190
Jeff Johnson295189b2012-06-20 16:38:30 -07001191 while(left >= 2)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301192 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001193 elem_id = ptr[0];
1194 elem_len = ptr[1];
1195 left -= 2;
1196 if(elem_len > left)
1197 {
1198 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001199 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -07001200 eid,elem_len,left);
1201 return NULL;
1202 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301203 if (elem_id == eid)
Jeff Johnson295189b2012-06-20 16:38:30 -07001204 {
1205 return ptr;
1206 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301207
Jeff Johnson295189b2012-06-20 16:38:30 -07001208 left -= elem_len;
1209 ptr += (elem_len + 2);
1210 }
1211 return NULL;
1212}
1213
Jeff Johnson295189b2012-06-20 16:38:30 -07001214/* Check if rate is 11g rate or not */
1215static int wlan_hdd_rate_is_11g(u8 rate)
1216{
Sanjay Devnani28322e22013-06-21 16:13:40 -07001217 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001218 u8 i;
1219 for (i = 0; i < 8; i++)
1220 {
1221 if(rate == gRateArray[i])
1222 return TRUE;
1223 }
1224 return FALSE;
1225}
1226
1227/* Check for 11g rate and set proper 11g only mode */
1228static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
1229 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
1230{
1231 u8 i, num_rates = pIe[0];
1232
1233 pIe += 1;
1234 for ( i = 0; i < num_rates; i++)
1235 {
1236 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
1237 {
1238 /* If rate set have 11g rate than change the mode to 11G */
1239 *pSapHw_mode = eSAP_DOT11_MODE_11g;
1240 if (pIe[i] & BASIC_RATE_MASK)
1241 {
1242 /* If we have 11g rate as basic rate, it means mode
1243 is 11g only mode.
1244 */
1245 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
1246 *pCheckRatesfor11g = FALSE;
1247 }
1248 }
1249 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
1250 {
1251 *require_ht = TRUE;
1252 }
1253 }
1254 return;
1255}
1256
1257static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
1258{
1259 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1260 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1261 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1262 u8 checkRatesfor11g = TRUE;
1263 u8 require_ht = FALSE;
1264 u8 *pIe=NULL;
1265
1266 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
1267
1268 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
1269 pBeacon->head_len, WLAN_EID_SUPP_RATES);
1270 if (pIe != NULL)
1271 {
1272 pIe += 1;
1273 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1274 &pConfig->SapHw_mode);
1275 }
1276
1277 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1278 WLAN_EID_EXT_SUPP_RATES);
1279 if (pIe != NULL)
1280 {
1281
1282 pIe += 1;
1283 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1284 &pConfig->SapHw_mode);
1285 }
1286
1287 if( pConfig->channel > 14 )
1288 {
1289 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1290 }
1291
1292 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1293 WLAN_EID_HT_CAPABILITY);
1294
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301295 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001296 {
1297 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1298 if(require_ht)
1299 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1300 }
1301}
1302
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301303static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1304 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1305{
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001306 v_U16_t ielen = 0;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301307 v_U8_t *pIe = NULL;
1308 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1309
1310 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1311 pBeacon->tail, pBeacon->tail_len);
1312
1313 if (pIe)
1314 {
1315 ielen = pIe[1] + 2;
1316 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1317 {
1318 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1319 }
1320 else
1321 {
1322 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1323 return -EINVAL;
1324 }
1325 *total_ielen += ielen;
1326 }
1327 return 0;
1328}
1329
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001330static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter,
1331 v_U8_t *genie, v_U8_t *total_ielen)
1332{
1333 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1334 int left = pBeacon->tail_len;
1335 v_U8_t *ptr = pBeacon->tail;
1336 v_U8_t elem_id, elem_len;
1337 v_U16_t ielen = 0;
1338
1339 if ( NULL == ptr || 0 == left )
1340 return;
1341
1342 while (left >= 2)
1343 {
1344 elem_id = ptr[0];
1345 elem_len = ptr[1];
1346 left -= 2;
1347 if (elem_len > left)
1348 {
1349 hddLog( VOS_TRACE_LEVEL_ERROR,
1350 "****Invalid IEs eid = %d elem_len=%d left=%d*****",
1351 elem_id, elem_len, left);
1352 return;
1353 }
1354 if (IE_EID_VENDOR == elem_id)
1355 {
1356 /* skipping the VSIE's which we don't want to include or
1357 * it will be included by existing code
1358 */
1359 if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) &&
1360#ifdef WLAN_FEATURE_WFD
1361 (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) &&
1362#endif
1363 (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1364 (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1365 (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) &&
1366 (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
1367 (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0))
1368 {
1369 ielen = ptr[1] + 2;
1370 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1371 {
1372 vos_mem_copy(&genie[*total_ielen], ptr, ielen);
1373 *total_ielen += ielen;
1374 }
1375 else
1376 {
1377 hddLog( VOS_TRACE_LEVEL_ERROR,
1378 "IE Length is too big "
1379 "IEs eid=%d elem_len=%d total_ie_lent=%d",
1380 elem_id, elem_len, *total_ielen);
1381 }
1382 }
1383 }
1384
1385 left -= elem_len;
1386 ptr += (elem_len + 2);
1387 }
1388 return;
1389}
1390
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001391#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001392static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1393 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001394#else
1395static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1396 struct cfg80211_beacon_data *params)
1397#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001398{
1399 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301400 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001401 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001402 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001403
1404 genie = vos_mem_malloc(MAX_GENIE_LEN);
1405
1406 if(genie == NULL) {
1407
1408 return -ENOMEM;
1409 }
1410
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301411 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1412 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001413 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301414 hddLog(LOGE,
1415 FL("Adding WPS IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301416 ret = -EINVAL;
1417 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001418 }
1419
1420#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301421 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1422 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1423 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301424 hddLog(LOGE,
1425 FL("Adding WFD IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301426 ret = -EINVAL;
1427 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001428 }
1429#endif
1430
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301431 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1432 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001433 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301434 hddLog(LOGE,
1435 FL("Adding P2P IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301436 ret = -EINVAL;
1437 goto done;
1438 }
1439
1440 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1441 {
Arif Hussaine7f3ea52013-09-12 21:56:36 -07001442 wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen);
Jeff Johnson295189b2012-06-20 16:38:30 -07001443 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001444
1445 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1446 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1447 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1448 {
1449 hddLog(LOGE,
1450 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001451 ret = -EINVAL;
1452 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001453 }
1454
1455 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1456 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1457 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1458 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1459 ==eHAL_STATUS_FAILURE)
1460 {
1461 hddLog(LOGE,
1462 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001463 ret = -EINVAL;
1464 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001465 }
1466
1467 // Added for ProResp IE
1468 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1469 {
1470 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1471 u8 probe_rsp_ie_len[3] = {0};
1472 u8 counter = 0;
1473 /* Check Probe Resp Length if it is greater then 255 then Store
1474 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1475 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1476 Store More then 255 bytes into One Variable.
1477 */
1478 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1479 {
1480 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1481 {
1482 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1483 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1484 }
1485 else
1486 {
1487 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1488 rem_probe_resp_ie_len = 0;
1489 }
1490 }
1491
1492 rem_probe_resp_ie_len = 0;
1493
1494 if (probe_rsp_ie_len[0] > 0)
1495 {
1496 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1497 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1498 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1499 probe_rsp_ie_len[0], NULL,
1500 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1501 {
1502 hddLog(LOGE,
1503 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001504 ret = -EINVAL;
1505 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001506 }
1507 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1508 }
1509
1510 if (probe_rsp_ie_len[1] > 0)
1511 {
1512 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1513 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1514 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1515 probe_rsp_ie_len[1], NULL,
1516 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1517 {
1518 hddLog(LOGE,
1519 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001520 ret = -EINVAL;
1521 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 }
1523 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1524 }
1525
1526 if (probe_rsp_ie_len[2] > 0)
1527 {
1528 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1529 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1530 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1531 probe_rsp_ie_len[2], NULL,
1532 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1533 {
1534 hddLog(LOGE,
1535 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001536 ret = -EINVAL;
1537 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001538 }
1539 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1540 }
1541
1542 if (probe_rsp_ie_len[1] == 0 )
1543 {
1544 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1545 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1546 eANI_BOOLEAN_FALSE) )
1547 {
1548 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001549 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001550 }
1551 }
1552
1553 if (probe_rsp_ie_len[2] == 0 )
1554 {
1555 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1556 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1557 eANI_BOOLEAN_FALSE) )
1558 {
1559 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001560 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001561 }
1562 }
1563
1564 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1565 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1566 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1567 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1568 == eHAL_STATUS_FAILURE)
1569 {
1570 hddLog(LOGE,
1571 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001572 ret = -EINVAL;
1573 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 }
1575 }
1576 else
1577 {
1578 // Reset WNI_CFG_PROBE_RSP Flags
1579 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1580
1581 hddLog(VOS_TRACE_LEVEL_INFO,
1582 "%s: No Probe Response IE received in set beacon",
1583 __func__);
1584 }
1585
1586 // Added for AssocResp IE
1587 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1588 {
1589 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1590 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1591 params->assocresp_ies_len, NULL,
1592 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1593 {
1594 hddLog(LOGE,
1595 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001596 ret = -EINVAL;
1597 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001598 }
1599
1600 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1601 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1602 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1603 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1604 == eHAL_STATUS_FAILURE)
1605 {
1606 hddLog(LOGE,
1607 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001608 ret = -EINVAL;
1609 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001610 }
1611 }
1612 else
1613 {
1614 hddLog(VOS_TRACE_LEVEL_INFO,
1615 "%s: No Assoc Response IE received in set beacon",
1616 __func__);
1617
1618 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1619 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1620 eANI_BOOLEAN_FALSE) )
1621 {
1622 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001623 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07001624 }
1625 }
1626
Jeff Johnsone7245742012-09-05 17:12:55 -07001627done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001628 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301629 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001630}
Jeff Johnson295189b2012-06-20 16:38:30 -07001631
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301632/*
Jeff Johnson295189b2012-06-20 16:38:30 -07001633 * FUNCTION: wlan_hdd_validate_operation_channel
1634 * called by wlan_hdd_cfg80211_start_bss() and
1635 * wlan_hdd_cfg80211_set_channel()
1636 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301637 * channel list.
1638 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001639VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001640{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301641
Jeff Johnson295189b2012-06-20 16:38:30 -07001642 v_U32_t num_ch = 0;
1643 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1644 u32 indx = 0;
1645 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301646 v_U8_t fValidChannel = FALSE, count = 0;
1647 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301648
Jeff Johnson295189b2012-06-20 16:38:30 -07001649 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1650
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301651 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001652 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301653 /* Validate the channel */
1654 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301656 if ( channel == rfChannels[count].channelNum )
1657 {
1658 fValidChannel = TRUE;
1659 break;
1660 }
1661 }
1662 if (fValidChannel != TRUE)
1663 {
1664 hddLog(VOS_TRACE_LEVEL_ERROR,
1665 "%s: Invalid Channel [%d]", __func__, channel);
1666 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001667 }
1668 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301669 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301671 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1672 valid_ch, &num_ch))
1673 {
1674 hddLog(VOS_TRACE_LEVEL_ERROR,
1675 "%s: failed to get valid channel list", __func__);
1676 return VOS_STATUS_E_FAILURE;
1677 }
1678 for (indx = 0; indx < num_ch; indx++)
1679 {
1680 if (channel == valid_ch[indx])
1681 {
1682 break;
1683 }
1684 }
1685
1686 if (indx >= num_ch)
1687 {
1688 hddLog(VOS_TRACE_LEVEL_ERROR,
1689 "%s: Invalid Channel [%d]", __func__, channel);
1690 return VOS_STATUS_E_FAILURE;
1691 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001692 }
1693 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301694
Jeff Johnson295189b2012-06-20 16:38:30 -07001695}
1696
Viral Modi3a32cc52013-02-08 11:14:52 -08001697/**
1698 * FUNCTION: wlan_hdd_cfg80211_set_channel
1699 * This function is used to set the channel number
1700 */
1701static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1702 struct ieee80211_channel *chan,
1703 enum nl80211_channel_type channel_type
1704 )
1705{
1706 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07001707 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08001708 hdd_adapter_t *pAdapter = NULL;
1709 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301710 hdd_context_t *pHddCtx;
1711 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001712
1713 ENTER();
1714
1715 if( NULL == dev )
1716 {
1717 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001718 "%s: Called with dev = NULL.", __func__);
Viral Modi3a32cc52013-02-08 11:14:52 -08001719 return -ENODEV;
1720 }
1721 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1722
1723 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001724 "%s: device_mode = %d freq = %d", __func__,
Viral Modi3a32cc52013-02-08 11:14:52 -08001725 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301726
1727 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1728 status = wlan_hdd_validate_context(pHddCtx);
1729
1730 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08001731 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1733 "%s: HDD context is not valid", __func__);
1734 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001735 }
1736
1737 /*
1738 * Do freq to chan conversion
1739 * TODO: for 11a
1740 */
1741
1742 channel = ieee80211_frequency_to_channel(freq);
1743
1744 /* Check freq range */
1745 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1746 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1747 {
1748 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001749 "%s: Channel [%d] is outside valid range from %d to %d",
Viral Modi3a32cc52013-02-08 11:14:52 -08001750 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1751 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1752 return -EINVAL;
1753 }
1754
1755 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1756
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301757 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1758 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001759 {
1760 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1761 {
1762 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001763 "%s: Invalid Channel [%d]", __func__, channel);
Viral Modi3a32cc52013-02-08 11:14:52 -08001764 return -EINVAL;
1765 }
1766 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1767 "%s: set channel to [%d] for device mode =%d",
1768 __func__, channel,pAdapter->device_mode);
1769 }
1770 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001771 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001772 )
1773 {
1774 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1775 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1776 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1777
1778 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1779 {
1780 /* Link is up then return cant set channel*/
1781 hddLog( VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001782 "%s: IBSS Associated, can't set the channel", __func__);
Viral Modi3a32cc52013-02-08 11:14:52 -08001783 return -EINVAL;
1784 }
1785
1786 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1787 pHddStaCtx->conn_info.operationChannel = channel;
1788 pRoamProfile->ChannelInfo.ChannelList =
1789 &pHddStaCtx->conn_info.operationChannel;
1790 }
1791 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001792 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001793 )
1794 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301795 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1796 {
1797 if(VOS_STATUS_SUCCESS !=
1798 wlan_hdd_validate_operation_channel(pAdapter,channel))
1799 {
1800 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001801 "%s: Invalid Channel [%d]", __func__, channel);
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301802 return -EINVAL;
1803 }
1804 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1805 }
1806 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001807 {
1808 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1809
1810 /* If auto channel selection is configured as enable/ 1 then ignore
1811 channel set by supplicant
1812 */
1813 if ( cfg_param->apAutoChannelSelection )
1814 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301815 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1816 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001817 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1818 "%s: set channel to auto channel (0) for device mode =%d",
1819 __func__, pAdapter->device_mode);
1820 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301821 else
1822 {
1823 if(VOS_STATUS_SUCCESS !=
1824 wlan_hdd_validate_operation_channel(pAdapter,channel))
1825 {
1826 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001827 "%s: Invalid Channel [%d]", __func__, channel);
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301828 return -EINVAL;
1829 }
1830 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1831 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001832 }
1833 }
1834 else
1835 {
1836 hddLog(VOS_TRACE_LEVEL_FATAL,
1837 "%s: Invalid device mode failed to set valid channel", __func__);
1838 return -EINVAL;
1839 }
1840 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301841 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08001842}
1843
Jeff Johnson295189b2012-06-20 16:38:30 -07001844#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1845static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1846 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001847#else
1848static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1849 struct cfg80211_beacon_data *params,
1850 const u8 *ssid, size_t ssid_len,
1851 enum nl80211_hidden_ssid hidden_ssid)
1852#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001853{
1854 tsap_Config_t *pConfig;
1855 beacon_data_t *pBeacon = NULL;
1856 struct ieee80211_mgmt *pMgmt_frame;
1857 v_U8_t *pIe=NULL;
1858 v_U16_t capab_info;
1859 eCsrAuthType RSNAuthType;
1860 eCsrEncryptionType RSNEncryptType;
1861 eCsrEncryptionType mcRSNEncryptType;
1862 int status = VOS_STATUS_SUCCESS;
1863 tpWLAN_SAPEventCB pSapEventCallback;
1864 hdd_hostapd_state_t *pHostapdState;
1865 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1866 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301867 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001868 struct qc_mac_acl_entry *acl_entry = NULL;
1869 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001870 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001871
1872 ENTER();
1873
1874 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1875
1876 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1877
1878 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1879
1880 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1881
1882 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1883
1884 //channel is already set in the set_channel Call back
1885 //pConfig->channel = pCommitConfig->channel;
1886
1887 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301888 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07001889 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1890
1891 pConfig->dtim_period = pBeacon->dtim_period;
1892
Arif Hussain6d2a3322013-11-17 19:50:10 -08001893 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***",
Jeff Johnson295189b2012-06-20 16:38:30 -07001894 pConfig->dtim_period);
1895
1896
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001897 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001898 {
1899 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001900 WLAN_EID_COUNTRY);
Kiet Lam083504c2013-11-25 14:17:45 +05301901 if(memcmp(pHddCtx->cfg_ini->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0)
1902 {
1903 tANI_BOOLEAN restartNeeded;
1904 pConfig->ieee80211d = 1;
1905 vos_mem_copy(pConfig->countryCode, pHddCtx->cfg_ini->apCntryCode, 3);
1906 sme_setRegInfo(hHal, pConfig->countryCode);
1907 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1908 }
1909 else if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001910 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001911 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001912 pConfig->ieee80211d = 1;
1913 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1914 sme_setRegInfo(hHal, pConfig->countryCode);
1915 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001916 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001917 else
1918 {
1919 pConfig->ieee80211d = 0;
1920 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301921 /*
1922 * If auto channel is configured i.e. channel is 0,
1923 * so skip channel validation.
1924 */
1925 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1926 {
1927 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1928 {
1929 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001930 "%s: Invalid Channel [%d]", __func__, pConfig->channel);
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301931 return -EINVAL;
1932 }
1933 }
1934 else
1935 {
1936 if(1 != pHddCtx->is_dynamic_channel_range_set)
1937 {
1938 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1939 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1940 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1941 }
1942 pHddCtx->is_dynamic_channel_range_set = 0;
1943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001944 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001945 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001946 {
1947 pConfig->ieee80211d = 0;
1948 }
1949 pConfig->authType = eSAP_AUTO_SWITCH;
1950
1951 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301952
1953 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07001954 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1955
1956 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1957
1958 /*Set wps station to configured*/
1959 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1960
1961 if(pIe)
1962 {
1963 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1964 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08001965 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***");
Jeff Johnson295189b2012-06-20 16:38:30 -07001966 return -EINVAL;
1967 }
1968 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1969 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001970 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001971 /* Check 15 bit of WPS IE as it contain information for wps state
1972 * WPS state
1973 */
1974 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1975 {
1976 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1977 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1978 {
1979 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1980 }
1981 }
1982 }
1983 else
1984 {
1985 pConfig->wps_state = SAP_WPS_DISABLED;
1986 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301987 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07001988
1989 pConfig->RSNWPAReqIELength = 0;
1990 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301991 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001992 WLAN_EID_RSN);
1993 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301994 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001995 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1996 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1997 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05301998 /* The actual processing may eventually be more extensive than
1999 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07002000 * by the app.
2001 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302002 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07002003 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
2004 &RSNEncryptType,
2005 &mcRSNEncryptType,
2006 &RSNAuthType,
2007 pConfig->pRSNWPAReqIE[1]+2,
2008 pConfig->pRSNWPAReqIE );
2009
2010 if( VOS_STATUS_SUCCESS == status )
2011 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302012 /* Now copy over all the security attributes you have
2013 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07002014 * */
2015 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
2016 pConfig->mcRSNEncryptType = mcRSNEncryptType;
2017 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
2018 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302019 hddLog( LOG1, FL("CSR AuthType = %d, "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002020 "EncryptionType = %d mcEncryptionType = %d"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002021 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
2022 }
2023 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302024
Jeff Johnson295189b2012-06-20 16:38:30 -07002025 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2026 pBeacon->tail, pBeacon->tail_len);
2027
2028 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
2029 {
2030 if (pConfig->pRSNWPAReqIE)
2031 {
2032 /*Mixed mode WPA/WPA2*/
2033 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
2034 pConfig->RSNWPAReqIELength += pIe[1] + 2;
2035 }
2036 else
2037 {
2038 pConfig->RSNWPAReqIELength = pIe[1] + 2;
2039 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
2040 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302041 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07002042 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
2043 &RSNEncryptType,
2044 &mcRSNEncryptType,
2045 &RSNAuthType,
2046 pConfig->pRSNWPAReqIE[1]+2,
2047 pConfig->pRSNWPAReqIE );
2048
2049 if( VOS_STATUS_SUCCESS == status )
2050 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302051 /* Now copy over all the security attributes you have
2052 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07002053 * */
2054 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
2055 pConfig->mcRSNEncryptType = mcRSNEncryptType;
2056 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
2057 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302058 hddLog( LOG1, FL("CSR AuthType = %d, "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002059 "EncryptionType = %d mcEncryptionType = %d"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002060 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
2061 }
2062 }
2063 }
2064
Jeff Johnson4416a782013-03-25 14:17:50 -07002065 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
2066 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
2067 return -EINVAL;
2068 }
2069
Jeff Johnson295189b2012-06-20 16:38:30 -07002070 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
2071
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002072#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002073 if (params->ssid != NULL)
2074 {
2075 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
2076 pConfig->SSIDinfo.ssid.length = params->ssid_len;
2077 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2078 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
2079 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002080#else
2081 if (ssid != NULL)
2082 {
2083 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
2084 pConfig->SSIDinfo.ssid.length = ssid_len;
2085 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2086 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
2087 }
2088#endif
2089
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302090 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07002091 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302092
Jeff Johnson295189b2012-06-20 16:38:30 -07002093 /* default value */
2094 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
2095 pConfig->num_accept_mac = 0;
2096 pConfig->num_deny_mac = 0;
2097
2098 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2099 pBeacon->tail, pBeacon->tail_len);
2100
2101 /* pIe for black list is following form:
2102 type : 1 byte
2103 length : 1 byte
2104 OUI : 4 bytes
2105 acl type : 1 byte
2106 no of mac addr in black list: 1 byte
2107 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302108 */
2109 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002110 {
2111 pConfig->SapMacaddr_acl = pIe[6];
2112 pConfig->num_deny_mac = pIe[7];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002113 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002114 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302115 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
2116 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002117 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2118 for (i = 0; i < pConfig->num_deny_mac; i++)
2119 {
2120 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2121 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302122 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002123 }
2124 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
2125 pBeacon->tail, pBeacon->tail_len);
2126
2127 /* pIe for white list is following form:
2128 type : 1 byte
2129 length : 1 byte
2130 OUI : 4 bytes
2131 acl type : 1 byte
2132 no of mac addr in white list: 1 byte
2133 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302134 */
2135 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002136 {
2137 pConfig->SapMacaddr_acl = pIe[6];
2138 pConfig->num_accept_mac = pIe[7];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002139 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002140 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302141 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
2142 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002143 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
2144 for (i = 0; i < pConfig->num_accept_mac; i++)
2145 {
2146 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
2147 acl_entry++;
2148 }
2149 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05302150
Jeff Johnson295189b2012-06-20 16:38:30 -07002151 wlan_hdd_set_sapHwmode(pHostapdAdapter);
2152
Jeff Johnsone7245742012-09-05 17:12:55 -07002153#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002154 /* Overwrite the hostapd setting for HW mode only for 11ac.
Kiet Lam0f320422013-11-21 19:29:17 +05302155 * This is valid only if mode is set to 11n in hostapd, either AUTO or
2156 * 11ac in .ini and 11ac is supported by both host and firmware.
2157 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode)
2158 */
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002159 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
2160 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302161 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08002162 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
Kiet Lam0f320422013-11-21 19:29:17 +05302163 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) &&
2164 (sme_IsFeatureSupportedByDriver(DOT11AC)) && (sme_IsFeatureSupportedByFW(DOT11AC)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07002165 {
2166 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Ravi Joshi83bfaa12013-05-28 22:12:08 -07002167
2168 /* Disable VHT support in 2.4 GHz band */
2169 if (pConfig->channel <= 14 &&
2170 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->enableVhtFor24GHzBand == FALSE)
2171 {
2172 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
2173 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002174 }
2175#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302176
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07002177 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
2178 {
2179 sme_SelectCBMode(hHal,
2180 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
2181 pConfig->channel);
2182 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002183 // ht_capab is not what the name conveys,this is used for protection bitmap
2184 pConfig->ht_capab =
2185 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
2186
2187 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
2188 {
2189 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
2190 return -EINVAL;
2191 }
2192
2193 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302194 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07002195 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
2196 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302197 pConfig->obssProtEnabled =
2198 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07002199
Arif Hussain6d2a3322013-11-17 19:50:10 -08002200 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR),
Jeff Johnson295189b2012-06-20 16:38:30 -07002201 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Arif Hussain6d2a3322013-11-17 19:50:10 -08002202 hddLog(LOGW,FL("ssid =%s, beaconint=%d, channel=%d"),
2203 pConfig->SSIDinfo.ssid.ssId, (int)pConfig->beacon_int,
2204 (int)pConfig->channel);
2205 hddLog(LOGW,FL("hw_mode=%x, privacy=%d, authType=%d"),
2206 pConfig->SapHw_mode, pConfig->privacy,
2207 pConfig->authType);
2208 hddLog(LOGW,FL("RSN/WPALen=%d, Uapsd = %d"),
2209 (int)pConfig->RSNWPAReqIELength, pConfig->UapsdEnable);
2210 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d"),
2211 pConfig->protEnabled, pConfig->obssProtEnabled);
Jeff Johnson295189b2012-06-20 16:38:30 -07002212
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302213 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002214 {
2215 //Bss already started. just return.
2216 //TODO Probably it should update some beacon params.
2217 hddLog( LOGE, "Bss Already started...Ignore the request");
2218 EXIT();
2219 return 0;
2220 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302221
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 pConfig->persona = pHostapdAdapter->device_mode;
2223
2224 pSapEventCallback = hdd_hostapd_SAPEventCB;
2225 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
2226 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
2227 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08002228 hddLog(LOGE,FL("SAP Start Bss fail"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002229 return -EINVAL;
2230 }
2231
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302232 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07002233 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
2234
2235 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302236
Jeff Johnson295189b2012-06-20 16:38:30 -07002237 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302238 {
2239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002240 ("ERROR: HDD vos wait for single_event failed!!"));
Tushnim Bhattacharyyaad37df12013-10-02 12:01:33 -07002241 smeGetCommandQStatus(hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07002242 VOS_ASSERT(0);
2243 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302244
Jeff Johnson295189b2012-06-20 16:38:30 -07002245 //Succesfully started Bss update the state bit.
2246 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
2247
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002248#ifdef WLAN_FEATURE_P2P_DEBUG
2249 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
2250 {
2251 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
2252 {
2253 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2254 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002255 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002256 }
2257 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
2258 {
2259 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
2260 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002261 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002262 }
2263 }
2264#endif
2265
Jeff Johnson295189b2012-06-20 16:38:30 -07002266 pHostapdState->bCommit = TRUE;
2267 EXIT();
2268
2269 return 0;
2270}
2271
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002272#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302273static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
2274 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07002275 struct beacon_parameters *params)
2276{
2277 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302278 hdd_context_t *pHddCtx;
2279 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002280
2281 ENTER();
2282
Arif Hussain6d2a3322013-11-17 19:50:10 -08002283 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d",pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002284
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302285 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2286 status = wlan_hdd_validate_context(pHddCtx);
2287
2288 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002289 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2291 "%s: HDD context is not valid", __func__);
2292 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002293 }
2294
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302295 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002296 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002297 )
2298 {
2299 beacon_data_t *old,*new;
2300
2301 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302302
Jeff Johnson295189b2012-06-20 16:38:30 -07002303 if (old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302304 {
2305 hddLog(VOS_TRACE_LEVEL_WARN,
2306 FL("already beacon info added to session(%d)"),
2307 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002308 return -EALREADY;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302309 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002310
2311 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2312
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302313 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07002314 {
2315 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002316 "%s:Error!!! Allocating the new beacon",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002317 return -EINVAL;
2318 }
2319
2320 pAdapter->sessionCtx.ap.beacon = new;
2321
2322 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2323 }
2324
2325 EXIT();
2326 return status;
2327}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302328
2329static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07002330 struct net_device *dev,
2331 struct beacon_parameters *params)
2332{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302333 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302334 hdd_context_t *pHddCtx;
2335 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002336
2337 ENTER();
2338
Arif Hussain6d2a3322013-11-17 19:50:10 -08002339 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002340 __func__,pAdapter->device_mode);
2341
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302342 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2343 status = wlan_hdd_validate_context(pHddCtx);
2344
2345 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002346 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2348 "%s: HDD context is not valid", __func__);
2349 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002350 }
2351
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302352 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002353 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302354 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002355 {
2356 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302357
Jeff Johnson295189b2012-06-20 16:38:30 -07002358 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302359
Jeff Johnson295189b2012-06-20 16:38:30 -07002360 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302361 {
2362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2363 FL("session(%d) old and new heads points to NULL"),
2364 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002365 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302366 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002367
2368 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2369
2370 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302371 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002372 "%s: Error!!! Allocating the new beacon",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002373 return -EINVAL;
2374 }
2375
2376 pAdapter->sessionCtx.ap.beacon = new;
2377
2378 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2379 }
2380
2381 EXIT();
2382 return status;
2383}
2384
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002385#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2386
2387#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002388static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2389 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002390#else
2391static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2392 struct net_device *dev)
2393#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002394{
2395 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002396 hdd_context_t *pHddCtx = NULL;
2397 hdd_scaninfo_t *pScanInfo = NULL;
2398 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302399 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002400
2401 ENTER();
2402
2403 if (NULL == pAdapter)
2404 {
2405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002406 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002407 return -ENODEV;
2408 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002409
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302410 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2411 status = wlan_hdd_validate_context(pHddCtx);
2412
2413 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002414 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2416 "%s: HDD context is not valid", __func__);
2417 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07002418 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002419
2420 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2421 if (NULL == staAdapter)
2422 {
2423 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2424 if (NULL == staAdapter)
2425 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002426 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2427 "%s: HDD adapter context for STA/P2P-CLI is Null",
2428 __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002429 }
2430 }
2431
2432 pScanInfo = &pHddCtx->scan_info;
2433
Arif Hussain6d2a3322013-11-17 19:50:10 -08002434 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002435 __func__,pAdapter->device_mode);
2436
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002437 if ((pScanInfo != NULL) && pScanInfo->mScanPending && staAdapter)
Jeff Johnsone7245742012-09-05 17:12:55 -07002438 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302439 long ret;
2440
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002441 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05302442 hdd_abort_mac_scan(staAdapter->pHddCtx, pAdapter->sessionId,
2443 eCSR_SCAN_ABORT_DEFAULT);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302444 ret = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002445 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002446 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302447 if (ret <= 0)
Jeff Johnsone7245742012-09-05 17:12:55 -07002448 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07002449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302450 FL("Timeout occurred while waiting for abortscan %ld"),
2451 ret);
Yue Ma4f55ef32014-01-23 16:45:33 -08002452
2453 if (pHddCtx->isLogpInProgress)
2454 {
2455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2456 "%s: LOGP in Progress. Ignore!!!", __func__);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302457
2458 VOS_ASSERT(pScanInfo->mScanPending);
Yue Ma4f55ef32014-01-23 16:45:33 -08002459 return -EAGAIN;
2460 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002461 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07002462 }
2463 }
2464
Arun Kumar Khandavallia3bd8002014-01-17 16:21:19 +05302465 hdd_hostapd_stop(dev);
2466
Jeff Johnson295189b2012-06-20 16:38:30 -07002467 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002468 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002469 )
2470 {
2471 beacon_data_t *old;
2472
2473 old = pAdapter->sessionCtx.ap.beacon;
2474
2475 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302476 {
2477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2478 FL("session(%d) beacon data points to NULL"),
2479 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07002480 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302481 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002482
Jeff Johnson295189b2012-06-20 16:38:30 -07002483 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002484
2485 mutex_lock(&pHddCtx->sap_lock);
2486 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2487 {
Jeff Johnson4416a782013-03-25 14:17:50 -07002488 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002489 {
2490 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2491
2492 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2493
2494 if (!VOS_IS_STATUS_SUCCESS(status))
2495 {
2496 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002497 ("ERROR: HDD vos wait for single_event failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002498 VOS_ASSERT(0);
2499 }
2500 }
2501 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2502 }
2503 mutex_unlock(&pHddCtx->sap_lock);
2504
2505 if(status != VOS_STATUS_SUCCESS)
2506 {
2507 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002508 "%s:Error!!! Stopping the BSS",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002509 return -EINVAL;
2510 }
2511
Jeff Johnson4416a782013-03-25 14:17:50 -07002512 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002513 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2514 ==eHAL_STATUS_FAILURE)
2515 {
2516 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002517 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07002518 }
2519
Jeff Johnson4416a782013-03-25 14:17:50 -07002520 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002521 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2522 eANI_BOOLEAN_FALSE) )
2523 {
2524 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002525 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07002526 }
2527
2528 // Reset WNI_CFG_PROBE_RSP Flags
2529 wlan_hdd_reset_prob_rspies(pAdapter);
2530
2531 pAdapter->sessionCtx.ap.beacon = NULL;
2532 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002533#ifdef WLAN_FEATURE_P2P_DEBUG
2534 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2535 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2536 {
2537 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2538 "GO got removed");
2539 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2540 }
2541#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002542 }
2543 EXIT();
2544 return status;
2545}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002546
2547#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2548
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302549static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2550 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002551 struct cfg80211_ap_settings *params)
2552{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302553 hdd_adapter_t *pAdapter;
2554 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302555 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002556
2557 ENTER();
2558
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302559 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002560 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302562 "%s: Device is Null", __func__);
2563 return -ENODEV;
2564 }
2565
2566 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2567 if (NULL == pAdapter)
2568 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302570 "%s: HDD adapter is Null", __func__);
2571 return -ENODEV;
2572 }
2573
2574 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2575 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302577 "%s: HDD adapter magic is invalid", __func__);
2578 return -ENODEV;
2579 }
2580
2581 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302582 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302583
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302584 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302585 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2587 "%s: HDD context is not valid", __func__);
2588 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302589 }
2590
2591 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2592 __func__, pAdapter->device_mode);
2593
2594 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002595 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002596 )
2597 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302598 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002599
2600 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302601
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002602 if (old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302603 {
2604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2605 FL("already beacon info added to session(%d)"),
2606 pAdapter->sessionId);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002607 return -EALREADY;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302608 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002609
2610 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2611
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302612 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002613 {
2614 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302615 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002616 return -EINVAL;
2617 }
2618 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002619#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07002620 wlan_hdd_cfg80211_set_channel(wiphy, dev,
2621#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2622 params->channel, params->channel_type);
2623#else
2624 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
2625#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08002626#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002627 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2628 params->ssid_len, params->hidden_ssid);
2629 }
2630
2631 EXIT();
2632 return status;
2633}
2634
2635
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302636static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002637 struct net_device *dev,
2638 struct cfg80211_beacon_data *params)
2639{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302640 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302641 hdd_context_t *pHddCtx;
2642 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002643
2644 ENTER();
2645
Arif Hussain6d2a3322013-11-17 19:50:10 -08002646 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002647 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302648
2649 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2650 status = wlan_hdd_validate_context(pHddCtx);
2651
2652 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002653 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2655 "%s: HDD context is not valid", __func__);
2656 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002657 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002658
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302659 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002660 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302661 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002662 {
2663 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302664
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002665 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302666
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002667 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302668 {
2669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2670 FL("session(%d) beacon data points to NULL"),
2671 pAdapter->sessionId);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002672 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302673 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002674
2675 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2676
2677 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302678 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002679 "%s: Error!!! Allocating the new beacon",__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002680 return -EINVAL;
2681 }
2682
2683 pAdapter->sessionCtx.ap.beacon = new;
2684
2685 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2686 }
2687
2688 EXIT();
2689 return status;
2690}
2691
2692#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2693
Jeff Johnson295189b2012-06-20 16:38:30 -07002694
2695static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2696 struct net_device *dev,
2697 struct bss_parameters *params)
2698{
2699 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2700
2701 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302702
Arif Hussain6d2a3322013-11-17 19:50:10 -08002703 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002704 __func__,pAdapter->device_mode);
2705
2706 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002707 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302708 )
Jeff Johnson295189b2012-06-20 16:38:30 -07002709 {
2710 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2711 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302712 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07002713 {
2714 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302715 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002716 }
2717
2718 EXIT();
2719 return 0;
2720}
2721
Kiet Lam10841362013-11-01 11:36:50 +05302722/* FUNCTION: wlan_hdd_change_country_code_cd
2723* to wait for contry code completion
2724*/
2725void* wlan_hdd_change_country_code_cb(void *pAdapter)
2726{
2727 hdd_adapter_t *call_back_pAdapter = pAdapter;
2728 complete(&call_back_pAdapter->change_country_code);
2729 return NULL;
2730}
2731
Jeff Johnson295189b2012-06-20 16:38:30 -07002732/*
2733 * FUNCTION: wlan_hdd_cfg80211_change_iface
2734 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2735 */
2736int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2737 struct net_device *ndev,
2738 enum nl80211_iftype type,
2739 u32 *flags,
2740 struct vif_params *params
2741 )
2742{
2743 struct wireless_dev *wdev;
2744 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Rajesh Chauhana0516c62014-01-30 16:11:18 -08002745 hdd_context_t *pHddCtx;
Mohit Khanna0f232092012-09-11 14:46:08 -07002746 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002747 tCsrRoamProfile *pRoamProfile = NULL;
2748 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302749 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002750 eMib_dot11DesiredBssType connectedBssType;
2751 VOS_STATUS status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302752 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07002753
2754 ENTER();
2755
Rajesh Chauhana0516c62014-01-30 16:11:18 -08002756 if (!pAdapter)
2757 {
2758 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2759 "%s: Adapter context is null", __func__);
2760 return VOS_STATUS_E_FAILURE;
2761 }
2762
2763 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2764 if (!pHddCtx)
2765 {
2766 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2767 "%s: HDD context is null", __func__);
2768 return VOS_STATUS_E_FAILURE;
2769 }
2770
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302771 status = wlan_hdd_validate_context(pHddCtx);
2772
2773 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07002774 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2776 "%s: HDD context is not valid", __func__);
2777 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07002778 }
2779
2780 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2781 __func__, pAdapter->device_mode);
2782
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302783 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07002784 wdev = ndev->ieee80211_ptr;
2785
2786#ifdef WLAN_BTAMP_FEATURE
2787 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2788 (NL80211_IFTYPE_ADHOC == type)||
2789 (NL80211_IFTYPE_AP == type)||
2790 (NL80211_IFTYPE_P2P_GO == type))
2791 {
2792 pHddCtx->isAmpAllowed = VOS_FALSE;
2793 // stop AMP traffic
2794 status = WLANBAP_StopAmp();
2795 if(VOS_STATUS_SUCCESS != status )
2796 {
2797 pHddCtx->isAmpAllowed = VOS_TRUE;
2798 hddLog(VOS_TRACE_LEVEL_FATAL,
2799 "%s: Failed to stop AMP", __func__);
2800 return -EINVAL;
2801 }
2802 }
2803#endif //WLAN_BTAMP_FEATURE
2804 /* Reset the current device mode bit mask*/
2805 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2806
2807 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002808 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002809 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002810 )
2811 {
2812 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Rajesh Chauhana0516c62014-01-30 16:11:18 -08002813 if (!pWextState)
2814 {
2815 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2816 "%s: pWextState is null", __func__);
2817 return VOS_STATUS_E_FAILURE;
2818 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002819 pRoamProfile = &pWextState->roamProfile;
2820 LastBSSType = pRoamProfile->BSSType;
2821
2822 switch (type)
2823 {
2824 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002825 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002826 hddLog(VOS_TRACE_LEVEL_INFO,
2827 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2828 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002829#ifdef WLAN_FEATURE_11AC
2830 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2831 {
2832 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2833 }
2834#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302835 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07002836 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002837 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002838 //Check for sub-string p2p to confirm its a p2p interface
2839 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302840 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002841 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2842 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2843 }
2844 else
2845 {
2846 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002847 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002848 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302849#ifdef FEATURE_WLAN_TDLS
2850 /* The open adapter for the p2p shall skip initializations in
2851 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
2852 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
2853 * tdls_init when the change_iface sets the device mode to
2854 * WLAN_HDD_P2P_CLIENT.
2855 */
2856
2857 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2858 {
2859 if (0 != wlan_hdd_tdls_init (pAdapter))
2860 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302861 hddLog(VOS_TRACE_LEVEL_ERROR,
2862 "%s: tdls initialization failed", __func__);
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05302863 return -EINVAL;
2864 }
2865 }
2866#endif
2867
Jeff Johnson295189b2012-06-20 16:38:30 -07002868 break;
2869 case NL80211_IFTYPE_ADHOC:
2870 hddLog(VOS_TRACE_LEVEL_INFO,
2871 "%s: setting interface Type to ADHOC", __func__);
2872 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2873 pRoamProfile->phyMode =
2874 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07002875 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07002876 wdev->iftype = type;
2877 break;
2878
2879 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002880 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002881 {
2882 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2883 "%s: setting interface Type to %s", __func__,
2884 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2885
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002886 //Cancel any remain on channel for GO mode
2887 if (NL80211_IFTYPE_P2P_GO == type)
2888 {
2889 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2890 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002891 if (NL80211_IFTYPE_AP == type)
2892 {
2893 /* As Loading WLAN Driver one interface being created for p2p device
2894 * address. This will take one HW STA and the max number of clients
2895 * that can connect to softAP will be reduced by one. so while changing
2896 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2897 * interface as it is not required in SoftAP mode.
2898 */
2899
2900 // Get P2P Adapter
2901 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2902
2903 if (pP2pAdapter)
2904 {
2905 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2906 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2907 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2908 }
2909 }
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302910#ifdef FEATURE_WLAN_TDLS
Mohit Khanna0f232092012-09-11 14:46:08 -07002911
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302912 /* A Mutex Lock is introduced while changing the mode to
2913 * protect the concurrent access for the Adapters by TDLS
2914 * module.
2915 */
2916 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
2917 {
2918 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2919 "%s: unable to lock list", __func__);
2920 return -EINVAL;
2921 }
2922#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002923 //De-init the adapter.
2924 hdd_stop_adapter( pHddCtx, pAdapter );
2925 hdd_deinit_adapter( pHddCtx, pAdapter );
2926 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002927 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2928 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05302929#ifdef FEATURE_WLAN_TDLS
2930 mutex_unlock(&pHddCtx->tdls_lock);
2931#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002932
2933 //Disable BMPS and IMPS if enabled
2934 //before starting Go
2935 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2936 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05302937 if(VOS_STATUS_E_FAILURE ==
Jeff Johnson32d95a32012-09-10 13:15:23 -07002938 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2939 {
2940 //Fail to Exit BMPS
2941 VOS_ASSERT(0);
2942 }
2943 }
2944
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002945 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2946 (pConfig->apRandomBssidEnabled))
2947 {
2948 /* To meet Android requirements create a randomized
2949 MAC address of the form 02:1A:11:Fx:xx:xx */
2950 get_random_bytes(&ndev->dev_addr[3], 3);
2951 ndev->dev_addr[0] = 0x02;
2952 ndev->dev_addr[1] = 0x1A;
2953 ndev->dev_addr[2] = 0x11;
2954 ndev->dev_addr[3] |= 0xF0;
2955 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2956 VOS_MAC_ADDR_SIZE);
Arif Hussain24bafea2013-11-15 15:10:03 -08002957 pr_info("wlan: Generated HotSpot BSSID " MAC_ADDRESS_STR"\n",
2958 MAC_ADDR_ARRAY(ndev->dev_addr));
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002959 }
2960
Jeff Johnson295189b2012-06-20 16:38:30 -07002961 hdd_set_ap_ops( pAdapter->dev );
2962
Kiet Lam10841362013-11-01 11:36:50 +05302963 /* This is for only SAP mode where users can
2964 * control country through ini.
2965 * P2P GO follows station country code
2966 * acquired during the STA scanning. */
2967 if((NL80211_IFTYPE_AP == type) &&
2968 (memcmp(pConfig->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0))
2969 {
2970 int status = 0;
2971 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
2972 "%s: setting country code from INI ", __func__);
2973 init_completion(&pAdapter->change_country_code);
2974 status = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2975 (void *)(tSmeChangeCountryCallback)
2976 wlan_hdd_change_country_code_cb,
2977 pConfig->apCntryCode, pAdapter,
2978 pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05302979 eSIR_FALSE,
2980 eSIR_TRUE);
Kiet Lam10841362013-11-01 11:36:50 +05302981 if (eHAL_STATUS_SUCCESS == status)
2982 {
2983 /* Wait for completion */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302984 ret = wait_for_completion_interruptible_timeout(
Kiet Lam10841362013-11-01 11:36:50 +05302985 &pAdapter->change_country_code,
2986 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302987 if (ret <= 0)
Kiet Lam10841362013-11-01 11:36:50 +05302988 {
2989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302990 FL("SME Timed out while setting country code %ld"),
2991 ret);
Yue Ma4f55ef32014-01-23 16:45:33 -08002992
2993 if (pHddCtx->isLogpInProgress)
2994 {
2995 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2996 "%s: LOGP in Progress. Ignore!!!", __func__);
2997 return -EAGAIN;
2998 }
Kiet Lam10841362013-11-01 11:36:50 +05302999 }
3000 }
3001 else
3002 {
3003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003004 "%s: SME Change Country code failed",__func__);
Kiet Lam10841362013-11-01 11:36:50 +05303005 return -EINVAL;
3006 }
3007 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003008 status = hdd_init_ap_mode(pAdapter);
3009 if(status != VOS_STATUS_SUCCESS)
3010 {
3011 hddLog(VOS_TRACE_LEVEL_FATAL,
3012 "%s: Error initializing the ap mode", __func__);
3013 return -EINVAL;
3014 }
3015 hdd_set_conparam(1);
3016
Jeff Johnson295189b2012-06-20 16:38:30 -07003017 /*interface type changed update in wiphy structure*/
3018 if(wdev)
3019 {
3020 wdev->iftype = type;
3021 pHddCtx->change_iface = type;
3022 }
3023 else
3024 {
3025 hddLog(VOS_TRACE_LEVEL_ERROR,
3026 "%s: ERROR !!!! Wireless dev is NULL", __func__);
3027 return -EINVAL;
3028 }
3029 goto done;
3030 }
3031
3032 default:
3033 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
3034 __func__);
3035 return -EOPNOTSUPP;
3036 }
3037 }
3038 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003039 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003040 )
3041 {
3042 switch(type)
3043 {
3044 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003045 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07003046 case NL80211_IFTYPE_ADHOC:
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303047#ifdef FEATURE_WLAN_TDLS
3048
3049 /* A Mutex Lock is introduced while changing the mode to
3050 * protect the concurrent access for the Adapters by TDLS
3051 * module.
3052 */
3053 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
3054 {
3055 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3056 "%s: unable to lock list", __func__);
3057 return -EINVAL;
3058 }
3059#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07003060 hdd_stop_adapter( pHddCtx, pAdapter );
3061 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07003062 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08003063 //Check for sub-string p2p to confirm its a p2p interface
3064 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08003065 {
3066 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
3067 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
3068 }
3069 else
3070 {
3071 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07003072 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08003073 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003074 hdd_set_conparam(0);
3075 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07003076 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
3077 hdd_set_station_ops( pAdapter->dev );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303078#ifdef FEATURE_WLAN_TDLS
3079 mutex_unlock(&pHddCtx->tdls_lock);
3080#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05303081 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07003082 if( VOS_STATUS_SUCCESS != status )
3083 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07003084 /* In case of JB, for P2P-GO, only change interface will be called,
3085 * This is the right place to enable back bmps_imps()
3086 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303087 if (pHddCtx->hdd_wlan_suspended)
3088 {
3089 hdd_set_pwrparams(pHddCtx);
3090 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003091 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003092 goto done;
3093 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003094 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003095 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07003096 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
3097 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003098 goto done;
3099 default:
3100 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
3101 __func__);
3102 return -EOPNOTSUPP;
3103
3104 }
3105
3106 }
3107 else
3108 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303109 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: unsupported device mode(%d)",
3110 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003111 return -EOPNOTSUPP;
3112 }
3113
3114
3115 if(pRoamProfile)
3116 {
3117 if ( LastBSSType != pRoamProfile->BSSType )
3118 {
3119 /*interface type changed update in wiphy structure*/
3120 wdev->iftype = type;
3121
3122 /*the BSS mode changed, We need to issue disconnect
3123 if connected or in IBSS disconnect state*/
3124 if ( hdd_connGetConnectedBssType(
3125 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
3126 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
3127 {
3128 /*need to issue a disconnect to CSR.*/
3129 INIT_COMPLETION(pAdapter->disconnect_comp_var);
3130 if( eHAL_STATUS_SUCCESS ==
3131 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
3132 pAdapter->sessionId,
3133 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
3134 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303135 ret = wait_for_completion_interruptible_timeout(
3136 &pAdapter->disconnect_comp_var,
3137 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3138 if (ret <= 0)
3139 {
3140 hddLog(VOS_TRACE_LEVEL_ERROR,
3141 FL("wait on disconnect_comp_var failed %ld"), ret);
3142 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003143 }
3144 }
3145 }
3146 }
3147
3148done:
3149 /*set bitmask based on updated value*/
3150 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07003151
3152 /* Only STA mode support TM now
3153 * all other mode, TM feature should be disabled */
3154 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
3155 (~VOS_STA & pHddCtx->concurrency_mode) )
3156 {
3157 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
3158 }
3159
Jeff Johnson295189b2012-06-20 16:38:30 -07003160#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303161 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07003162 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
3163 {
3164 //we are ok to do AMP
3165 pHddCtx->isAmpAllowed = VOS_TRUE;
3166 }
3167#endif //WLAN_BTAMP_FEATURE
3168 EXIT();
3169 return 0;
3170}
3171
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003172#ifdef FEATURE_WLAN_TDLS
3173static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
3174 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
3175{
3176 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3177 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3178 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003179 hddTdlsPeer_t *pTdlsPeer;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303180 long ret;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003181
3182 ENTER();
3183
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303184 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003185 {
3186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3187 "Invalid arguments");
3188 return -EINVAL;
3189 }
Hoonki Lee27511902013-03-14 18:19:06 -07003190
3191 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
3192 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
3193 {
3194 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3195 "%s: TDLS mode is disabled OR not enabled in FW."
3196 MAC_ADDRESS_STR " Request declined.",
3197 __func__, MAC_ADDR_ARRAY(mac));
3198 return -ENOTSUPP;
3199 }
3200
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003201 if (pHddCtx->isLogpInProgress)
3202 {
3203 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3204 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07003205 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003206 return -EBUSY;
3207 }
3208
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303209 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003210
3211 if ( NULL == pTdlsPeer ) {
3212 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3213 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
3214 __func__, MAC_ADDR_ARRAY(mac), update);
3215 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003216 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003217
3218 /* in add station, we accept existing valid staId if there is */
3219 if ((0 == update) &&
3220 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
3221 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003222 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003223 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003224 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003225 " link_status %d. staId %d. add station ignored.",
3226 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
3227 return 0;
3228 }
3229 /* in change station, we accept only when staId is valid */
3230 if ((1 == update) &&
3231 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
3232 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
3233 {
3234 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3235 "%s: " MAC_ADDRESS_STR
3236 " link status %d. staId %d. change station %s.",
3237 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
3238 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
3239 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003240 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003241
3242 /* when others are on-going, we want to change link_status to idle */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303243 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003244 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3246 "%s: " MAC_ADDRESS_STR
3247 " TDLS setup is ongoing. Request declined.",
3248 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07003249 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003250 }
3251
3252 /* first to check if we reached to maximum supported TDLS peer.
3253 TODO: for now, return -EPERM looks working fine,
3254 but need to check if any other errno fit into this category.*/
3255 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
3256 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003257 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3258 "%s: " MAC_ADDRESS_STR
3259 " TDLS Max peer already connected. Request declined.",
3260 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07003261 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003262 }
3263 else
3264 {
3265 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05303266 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003267 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003268 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3270 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
3271 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003272 return -EPERM;
3273 }
3274 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003275 if (0 == update)
3276 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003277
Jeff Johnsond75fe012013-04-06 10:53:06 -07003278 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303279 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003280 {
3281 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3282 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003283 if(StaParams->htcap_present)
3284 {
3285 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3286 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
3287 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3288 "ht_capa->extended_capabilities: %0x",
3289 StaParams->HTCap.extendedHtCapInfo);
3290 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003291 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3292 "params->capability: %0x",StaParams->capability);
3293 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003294 "params->ext_capab_len: %0x",StaParams->extn_capability[0]);
Hoonki Lee66b75f32013-04-16 18:30:07 -07003295 if(StaParams->vhtcap_present)
3296 {
3297 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3298 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
3299 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
3300 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
3301 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003302 {
3303 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003305 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
3306 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
3307 "[%d]: %x ", i, StaParams->supported_rates[i]);
3308 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07003309 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05303310 else if ((1 == update) && (NULL == StaParams))
3311 {
3312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3313 "%s : update is true, but staParams is NULL. Error!", __func__);
3314 return -EPERM;
3315 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003316
3317 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
3318
3319 if (!update)
3320 {
3321 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3322 pAdapter->sessionId, mac);
3323 }
3324 else
3325 {
3326 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
3327 pAdapter->sessionId, mac, StaParams);
3328 }
3329
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303330 ret = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003331 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
3332
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303333 if (ret <= 0)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003334 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003335 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303336 "%s: timeout waiting for tdls add station indication %ld",
3337 __func__, ret);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003338 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003339 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303340
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003341 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
3342 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07003343 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003344 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07003345 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003346 }
3347
3348 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07003349
3350error:
3351 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
3352 return -EPERM;
3353
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003354}
3355#endif
3356
Jeff Johnson295189b2012-06-20 16:38:30 -07003357static int wlan_hdd_change_station(struct wiphy *wiphy,
3358 struct net_device *dev,
3359 u8 *mac,
3360 struct station_parameters *params)
3361{
3362 VOS_STATUS status = VOS_STATUS_SUCCESS;
3363 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05303364 hdd_context_t *pHddCtx;
3365 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003366 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003367#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003368 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003369 tANI_U8 isBufSta = 0;
Naresh Jayaram3180aa42014-02-12 21:47:26 +05303370 tANI_U8 isOffChannelSupported = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003371#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003372 ENTER();
3373
Gopichand Nakkala29149562013-05-10 21:43:41 +05303374 if ((NULL == pAdapter))
3375 {
3376 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3377 "invalid adapter ");
3378 return -EINVAL;
3379 }
3380
3381 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3382 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3383
3384 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
3385 {
3386 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3387 "invalid HDD state or HDD station context");
3388 return -EINVAL;
3389 }
3390
3391 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003392 {
3393 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3394 "%s:LOGP in Progress. Ignore!!!", __func__);
3395 return -EAGAIN;
3396 }
3397
Jeff Johnson295189b2012-06-20 16:38:30 -07003398 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
3399
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003400 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3401 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07003402 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003403 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07003404 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303405 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07003406 WLANTL_STA_AUTHENTICATED);
3407
Gopichand Nakkala29149562013-05-10 21:43:41 +05303408 if (status != VOS_STATUS_SUCCESS)
3409 {
3410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3411 "%s: Not able to change TL state to AUTHENTICATED", __func__);
3412 return -EINVAL;
3413 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003414 }
3415 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07003416 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3417 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05303418#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003419 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
3420 StaParams.capability = params->capability;
3421 StaParams.uapsd_queues = params->uapsd_queues;
3422 StaParams.max_sp = params->max_sp;
3423
Naresh Jayaram3180aa42014-02-12 21:47:26 +05303424 /* Convert (first channel , number of channels) tuple to
3425 * the total list of channels. This goes with the assumption
3426 * that if the first channel is < 14, then the next channels
3427 * are an incremental of 1 else an incremental of 4 till the number
3428 * of channels.
3429 */
3430 if (0 != params->supported_channels_len) {
3431 int i = 0,j = 0,k = 0, no_of_channels = 0 ;
3432 for ( i = 0 ; i < params->supported_channels_len ; i+=2)
3433 {
3434 int wifi_chan_index;
3435 StaParams.supported_channels[j] = params->supported_channels[i];
3436 wifi_chan_index =
3437 ((StaParams.supported_channels[j] <= HDD_CHANNEL_14 ) ? 1 : 4 );
3438 no_of_channels = params->supported_channels[i+1];
3439 for(k=1; k <= no_of_channels; k++)
3440 {
3441 StaParams.supported_channels[j+1] =
3442 StaParams.supported_channels[j] + wifi_chan_index;
3443 j+=1;
3444 }
3445 }
3446 StaParams.supported_channels_len = j;
3447 }
3448 vos_mem_copy(StaParams.supported_oper_classes,
3449 params->supported_oper_classes,
3450 params->supported_oper_classes_len);
3451 StaParams.supported_oper_classes_len =
3452 params->supported_oper_classes_len;
3453
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003454 if (0 != params->ext_capab_len)
3455 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
3456 sizeof(StaParams.extn_capability));
3457
3458 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003459 {
3460 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003461 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003462 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003463
3464 StaParams.supported_rates_len = params->supported_rates_len;
3465
3466 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
3467 * The supported_rates array , for all the structures propogating till Add Sta
3468 * to the firmware has to be modified , if the supplicant (ieee80211) is
3469 * modified to send more rates.
3470 */
3471
3472 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
3473 */
3474 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
3475 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
3476
3477 if (0 != StaParams.supported_rates_len) {
3478 int i = 0;
3479 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
3480 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003482 "Supported Rates with Length %d", StaParams.supported_rates_len);
3483 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07003484 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003485 "[%d]: %0x", i, StaParams.supported_rates[i]);
3486 }
3487
3488 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07003489 {
3490 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003491 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07003492 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003493
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003494 if (0 != params->ext_capab_len ) {
3495 /*Define A Macro : TODO Sunil*/
3496 if ((1<<4) & StaParams.extn_capability[3]) {
3497 isBufSta = 1;
3498 }
Naresh Jayaram3180aa42014-02-12 21:47:26 +05303499 /* TDLS Channel Switching Support */
3500 if ((1<<6) & StaParams.extn_capability[3]) {
3501 isOffChannelSupported = 1;
3502 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003503 }
Naresh Jayaram3180aa42014-02-12 21:47:26 +05303504 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac,
3505 &StaParams, isBufSta,
3506 isOffChannelSupported);
3507
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303508 if (VOS_STATUS_SUCCESS != status) {
3509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3510 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
3511 return -EINVAL;
3512 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08003513 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
3514
3515 if (VOS_STATUS_SUCCESS != status) {
3516 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3517 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
3518 return -EINVAL;
3519 }
3520 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07003521#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05303522 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003523 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003524 return status;
3525}
3526
3527/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003528 * FUNCTION: wlan_hdd_cfg80211_add_key
3529 * This function is used to initialize the key information
3530 */
3531#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003532static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003533 struct net_device *ndev,
3534 u8 key_index, bool pairwise,
3535 const u8 *mac_addr,
3536 struct key_params *params
3537 )
3538#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003539static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003540 struct net_device *ndev,
3541 u8 key_index, const u8 *mac_addr,
3542 struct key_params *params
3543 )
3544#endif
3545{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003546 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003547 tCsrRoamSetKey setKey;
3548 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303549 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003550 v_U32_t roamId= 0xFF;
3551 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003552 hdd_hostapd_state_t *pHostapdState;
3553 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003554 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303555 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003556
3557 ENTER();
3558
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303559 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3560 status = wlan_hdd_validate_context(pHddCtx);
3561
3562 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003563 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05303564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3565 "%s: HDD context is not valid", __func__);
3566 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003567 }
3568
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003569 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
3570 __func__, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003571
3572 if (CSR_MAX_NUM_KEY <= key_index)
3573 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003574 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07003575 key_index);
3576
3577 return -EINVAL;
3578 }
3579
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003580 if (CSR_MAX_KEY_LEN < params->key_len)
3581 {
3582 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
3583 params->key_len);
3584
3585 return -EINVAL;
3586 }
3587
3588 hddLog(VOS_TRACE_LEVEL_INFO,
3589 "%s: called with key index = %d & key length %d",
3590 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003591
3592 /*extract key idx, key len and key*/
3593 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3594 setKey.keyId = key_index;
3595 setKey.keyLength = params->key_len;
3596 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3597
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003598 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07003599 {
3600 case WLAN_CIPHER_SUITE_WEP40:
3601 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3602 break;
3603
3604 case WLAN_CIPHER_SUITE_WEP104:
3605 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3606 break;
3607
3608 case WLAN_CIPHER_SUITE_TKIP:
3609 {
3610 u8 *pKey = &setKey.Key[0];
3611 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3612
3613 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3614
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003615 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07003616
3617 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003618 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003619 |--------------|----------|----------|
3620 <---16bytes---><--8bytes--><--8bytes-->
3621
3622 */
3623 /*Sme expects the 32 bytes key to be in the below order
3624
3625 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003626 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07003627 |--------------|----------|----------|
3628 <---16bytes---><--8bytes--><--8bytes-->
3629 */
3630 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003631 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07003632
3633 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003634 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003635
3636 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003637 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07003638
3639
3640 break;
3641 }
3642
3643 case WLAN_CIPHER_SUITE_CCMP:
3644 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3645 break;
3646
3647#ifdef FEATURE_WLAN_WAPI
3648 case WLAN_CIPHER_SUITE_SMS4:
3649 {
3650 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3651 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3652 params->key, params->key_len);
3653 return 0;
3654 }
3655#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003656
Jeff Johnson295189b2012-06-20 16:38:30 -07003657#ifdef FEATURE_WLAN_CCX
3658 case WLAN_CIPHER_SUITE_KRK:
3659 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3660 break;
3661#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07003662
3663#ifdef WLAN_FEATURE_11W
3664 case WLAN_CIPHER_SUITE_AES_CMAC:
3665 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07003666 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07003667#endif
3668
Jeff Johnson295189b2012-06-20 16:38:30 -07003669 default:
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003670 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
Jeff Johnson295189b2012-06-20 16:38:30 -07003671 __func__, params->cipher);
3672 return -EOPNOTSUPP;
3673 }
3674
3675 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3676 __func__, setKey.encType);
3677
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003678 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07003679#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3680 (!pairwise)
3681#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003682 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07003683#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003684 )
3685 {
3686 /* set group key*/
3687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3688 "%s- %d: setting Broadcast key",
3689 __func__, __LINE__);
3690 setKey.keyDirection = eSIR_RX_ONLY;
3691 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3692 }
3693 else
3694 {
3695 /* set pairwise key*/
3696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3697 "%s- %d: setting pairwise key",
3698 __func__, __LINE__);
3699 setKey.keyDirection = eSIR_TX_RX;
3700 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3701 }
3702 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
3703 {
3704 setKey.keyDirection = eSIR_TX_RX;
3705 /*Set the group key*/
3706 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3707 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07003708
Shailender Karmuchi642e9812013-05-30 14:34:49 -07003709 if ( 0 != status )
3710 {
3711 hddLog(VOS_TRACE_LEVEL_ERROR,
3712 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3713 return -EINVAL;
3714 }
3715 /*Save the keys here and call sme_RoamSetKey for setting
3716 the PTK after peer joins the IBSS network*/
3717 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
3718 &setKey, sizeof(tCsrRoamSetKey));
3719 return status;
3720 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05303721 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
3722 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
3723 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003724 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003725 if( pHostapdState->bssState == BSS_START )
3726 {
c_hpothu7c55da62014-01-23 18:34:02 +05303727 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3728 vos_status = wlan_hdd_check_ula_done(pAdapter);
3729
3730 if ( vos_status != VOS_STATUS_SUCCESS )
3731 {
3732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3733 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3734 __LINE__, vos_status );
3735
3736 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3737
3738 return -EINVAL;
3739 }
3740
Jeff Johnson295189b2012-06-20 16:38:30 -07003741 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3742
3743 if ( status != eHAL_STATUS_SUCCESS )
3744 {
3745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3746 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3747 __LINE__, status );
3748 }
3749 }
3750
3751 /* Saving WEP keys */
3752 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3753 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3754 {
3755 //Save the wep key in ap context. Issue setkey after the BSS is started.
3756 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3757 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3758 }
3759 else
3760 {
3761 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003762 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003763 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3764 }
3765 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003766 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3767 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07003768 {
3769 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3770 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3771
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303772#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3773 if (!pairwise)
3774#else
3775 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
3776#endif
3777 {
3778 /* set group key*/
3779 if (pHddStaCtx->roam_info.deferKeyComplete)
3780 {
3781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3782 "%s- %d: Perform Set key Complete",
3783 __func__, __LINE__);
3784 hdd_PerformRoamSetKeyComplete(pAdapter);
3785 }
3786 }
3787
Jeff Johnson295189b2012-06-20 16:38:30 -07003788 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3789
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003790 pWextState->roamProfile.Keys.defaultIndex = key_index;
3791
3792
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07003793 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07003794 params->key, params->key_len);
3795
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303796
Jeff Johnson295189b2012-06-20 16:38:30 -07003797 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3798
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303799 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003800 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303801 __func__, setKey.peerMac[0], setKey.peerMac[1],
3802 setKey.peerMac[2], setKey.peerMac[3],
3803 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 setKey.keyDirection);
3805
3806 vos_status = wlan_hdd_check_ula_done(pAdapter);
3807
3808 if ( vos_status != VOS_STATUS_SUCCESS )
3809 {
3810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3811 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3812 __LINE__, vos_status );
3813
3814 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3815
3816 return -EINVAL;
3817
3818 }
3819
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003820#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303821 /* The supplicant may attempt to set the PTK once pre-authentication
3822 is done. Save the key in the UMAC and include it in the ADD BSS
3823 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003824 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303825 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003826 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05303827 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3828 "%s: Update PreAuth Key success", __func__);
3829 return 0;
3830 }
3831 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
3832 {
3833 hddLog(VOS_TRACE_LEVEL_ERROR,
3834 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303835 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003836 }
3837#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003838
3839 /* issue set key request to SME*/
3840 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3841 pAdapter->sessionId, &setKey, &roamId );
3842
3843 if ( 0 != status )
3844 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303845 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003846 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3847 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3848 return -EINVAL;
3849 }
3850
3851
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303852 /* in case of IBSS as there was no information available about WEP keys during
3853 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07003854 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303855 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3856 !( ( IW_AUTH_KEY_MGMT_802_1X
3857 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07003858 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3859 )
3860 &&
3861 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3862 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3863 )
3864 )
3865 {
3866 setKey.keyDirection = eSIR_RX_ONLY;
3867 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3868
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303869 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07003870 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303871 __func__, setKey.peerMac[0], setKey.peerMac[1],
3872 setKey.peerMac[2], setKey.peerMac[3],
3873 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07003874 setKey.keyDirection);
3875
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303876 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003877 pAdapter->sessionId, &setKey, &roamId );
3878
3879 if ( 0 != status )
3880 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303881 hddLog(VOS_TRACE_LEVEL_ERROR,
3882 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003883 __func__, status);
3884 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3885 return -EINVAL;
3886 }
3887 }
3888 }
3889
3890 return 0;
3891}
3892
3893/*
3894 * FUNCTION: wlan_hdd_cfg80211_get_key
3895 * This function is used to get the key information
3896 */
3897#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303898static int wlan_hdd_cfg80211_get_key(
3899 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003900 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303901 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003902 const u8 *mac_addr, void *cookie,
3903 void (*callback)(void *cookie, struct key_params*)
3904 )
3905#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303906static int wlan_hdd_cfg80211_get_key(
3907 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003908 struct net_device *ndev,
3909 u8 key_index, const u8 *mac_addr, void *cookie,
3910 void (*callback)(void *cookie, struct key_params*)
3911 )
3912#endif
3913{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303914 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003915 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3916 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3917 struct key_params params;
3918
3919 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303920
Arif Hussain6d2a3322013-11-17 19:50:10 -08003921 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 __func__,pAdapter->device_mode);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303923
Jeff Johnson295189b2012-06-20 16:38:30 -07003924 memset(&params, 0, sizeof(params));
3925
3926 if (CSR_MAX_NUM_KEY <= key_index)
3927 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303928 hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid key index %d"), key_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07003929 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303930 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003931
3932 switch(pRoamProfile->EncryptionType.encryptionType[0])
3933 {
3934 case eCSR_ENCRYPT_TYPE_NONE:
3935 params.cipher = IW_AUTH_CIPHER_NONE;
3936 break;
3937
3938 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3939 case eCSR_ENCRYPT_TYPE_WEP40:
3940 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3941 break;
3942
3943 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3944 case eCSR_ENCRYPT_TYPE_WEP104:
3945 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3946 break;
3947
3948 case eCSR_ENCRYPT_TYPE_TKIP:
3949 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3950 break;
3951
3952 case eCSR_ENCRYPT_TYPE_AES:
3953 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3954 break;
3955
3956 default:
3957 params.cipher = IW_AUTH_CIPHER_NONE;
3958 break;
3959 }
3960
3961 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3962 params.seq_len = 0;
3963 params.seq = NULL;
3964 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3965 callback(cookie, &params);
3966 return 0;
3967}
3968
3969/*
3970 * FUNCTION: wlan_hdd_cfg80211_del_key
3971 * This function is used to delete the key information
3972 */
3973#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303974static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003975 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303976 u8 key_index,
3977 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07003978 const u8 *mac_addr
3979 )
3980#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303981static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07003982 struct net_device *ndev,
3983 u8 key_index,
3984 const u8 *mac_addr
3985 )
3986#endif
3987{
3988 int status = 0;
3989
3990 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303991 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07003992 //it is observed that this is invalidating peer
3993 //key index whenever re-key is done. This is affecting data link.
3994 //It should be ok to ignore del_key.
3995#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05303996 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3997 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003998 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3999 tCsrRoamSetKey setKey;
4000 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304001
Jeff Johnson295189b2012-06-20 16:38:30 -07004002 ENTER();
4003
4004 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
4005 __func__,pAdapter->device_mode);
4006
4007 if (CSR_MAX_NUM_KEY <= key_index)
4008 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304009 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004010 key_index);
4011
4012 return -EINVAL;
4013 }
4014
4015 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
4016 setKey.keyId = key_index;
4017
4018 if (mac_addr)
4019 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
4020 else
4021 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
4022
4023 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
4024
4025 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004026 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304027 )
4028 {
4029
4030 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07004031 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4032 if( pHostapdState->bssState == BSS_START)
4033 {
4034 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304035
Jeff Johnson295189b2012-06-20 16:38:30 -07004036 if ( status != eHAL_STATUS_SUCCESS )
4037 {
4038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4039 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
4040 __LINE__, status );
4041 }
4042 }
4043 }
4044 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304045 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07004046 )
4047 {
4048 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4049
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304050 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
4051
4052 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07004053 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304054 __func__, setKey.peerMac[0], setKey.peerMac[1],
4055 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07004056 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304057 if(pAdapter->sessionCtx.station.conn_info.connState ==
4058 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07004059 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304060 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004061 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304062
Jeff Johnson295189b2012-06-20 16:38:30 -07004063 if ( 0 != status )
4064 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304065 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004066 "%s: sme_RoamSetKey failure, returned %d",
4067 __func__, status);
4068 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
4069 return -EINVAL;
4070 }
4071 }
4072 }
4073#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004074 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004075 return status;
4076}
4077
4078/*
4079 * FUNCTION: wlan_hdd_cfg80211_set_default_key
4080 * This function is used to set the default tx key index
4081 */
4082#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4083static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
4084 struct net_device *ndev,
4085 u8 key_index,
4086 bool unicast, bool multicast)
4087#else
4088static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
4089 struct net_device *ndev,
4090 u8 key_index)
4091#endif
4092{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304093 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304094 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05304095 hdd_wext_state_t *pWextState;
4096 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304097 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004098
4099 ENTER();
4100
Gopichand Nakkala29149562013-05-10 21:43:41 +05304101 if ((NULL == pAdapter))
4102 {
4103 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4104 "invalid adapter");
4105 return -EINVAL;
4106 }
4107
4108 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4109 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4110
4111 if ((NULL == pWextState) || (NULL == pHddStaCtx))
4112 {
4113 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4114 "invalid Wext state or HDD context");
4115 return -EINVAL;
4116 }
4117
Arif Hussain6d2a3322013-11-17 19:50:10 -08004118 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004119 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304120
Jeff Johnson295189b2012-06-20 16:38:30 -07004121 if (CSR_MAX_NUM_KEY <= key_index)
4122 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304123 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004124 key_index);
4125
4126 return -EINVAL;
4127 }
4128
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304129 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4130 status = wlan_hdd_validate_context(pHddCtx);
4131
4132 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004133 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05304134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4135 "%s: HDD context is not valid", __func__);
4136 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004137 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304138
Jeff Johnson295189b2012-06-20 16:38:30 -07004139 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304141 )
Jeff Johnson295189b2012-06-20 16:38:30 -07004142 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05304143 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Arif Hussain6943f522013-11-04 20:10:10 -08004144 pHddStaCtx->conn_info.ucEncryptionType) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304145 (eCSR_ENCRYPT_TYPE_AES !=
Arif Hussain6943f522013-11-04 20:10:10 -08004146 pHddStaCtx->conn_info.ucEncryptionType)
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304148 {
4149 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07004150 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304151
Jeff Johnson295189b2012-06-20 16:38:30 -07004152 tCsrRoamSetKey setKey;
4153 v_U32_t roamId= 0xFF;
4154 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304155
4156 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004157 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304158
Jeff Johnson295189b2012-06-20 16:38:30 -07004159 Keys->defaultIndex = (u8)key_index;
4160 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
4161 setKey.keyId = key_index;
4162 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304163
4164 vos_mem_copy(&setKey.Key[0],
4165 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07004166 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304167
Gopichand Nakkala29149562013-05-10 21:43:41 +05304168 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304169
4170 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07004171 &pHddStaCtx->conn_info.bssId[0],
4172 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304173
Gopichand Nakkala29149562013-05-10 21:43:41 +05304174 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
4175 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4176 eCSR_ENCRYPT_TYPE_WEP104)
4177 {
4178 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
4179 even though ap is configured for WEP-40 encryption. In this canse the key length
4180 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
4181 type(104) and switching encryption type to 40*/
4182 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4183 eCSR_ENCRYPT_TYPE_WEP40;
4184 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
4185 eCSR_ENCRYPT_TYPE_WEP40;
4186 }
4187
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304188 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07004189 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304190
Jeff Johnson295189b2012-06-20 16:38:30 -07004191 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304192 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004193 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304194
Jeff Johnson295189b2012-06-20 16:38:30 -07004195 if ( 0 != status )
4196 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304197 hddLog(VOS_TRACE_LEVEL_ERROR,
4198 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004199 status);
4200 return -EINVAL;
4201 }
4202 }
4203 }
4204
4205 /* In SoftAp mode setting key direction for default mode */
4206 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
4207 {
4208 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
4209 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
4210 (eCSR_ENCRYPT_TYPE_AES !=
4211 pWextState->roamProfile.EncryptionType.encryptionType[0])
4212 )
4213 {
4214 /* Saving key direction for default key index to TX default */
4215 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4216 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
4217 }
4218 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304219
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 return status;
4221}
4222
Jeff Johnson295189b2012-06-20 16:38:30 -07004223/*
4224 * FUNCTION: wlan_hdd_cfg80211_inform_bss
4225 * This function is used to inform the BSS details to nl80211 interface.
4226 */
4227static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
4228 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
4229{
4230 struct net_device *dev = pAdapter->dev;
4231 struct wireless_dev *wdev = dev->ieee80211_ptr;
4232 struct wiphy *wiphy = wdev->wiphy;
4233 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
4234 int chan_no;
4235 int ie_length;
4236 const char *ie;
4237 unsigned int freq;
4238 struct ieee80211_channel *chan;
4239 int rssi = 0;
4240 struct cfg80211_bss *bss = NULL;
4241
4242 ENTER();
4243
4244 if( NULL == pBssDesc )
4245 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004246 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004247 return bss;
4248 }
4249
4250 chan_no = pBssDesc->channelId;
4251 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
4252 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
4253
4254 if( NULL == ie )
4255 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004256 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004257 return bss;
4258 }
4259
4260#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
4261 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
4262 {
4263 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4264 }
4265 else
4266 {
4267 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4268 }
4269#else
4270 freq = ieee80211_channel_to_frequency(chan_no);
4271#endif
4272
4273 chan = __ieee80211_get_channel(wiphy, freq);
4274
4275 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
4276 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
4277 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
4278 if (bss == NULL)
4279 {
4280 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
4281
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304282 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
4283 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07004284 pBssDesc->capabilityInfo,
4285 pBssDesc->beaconInterval, ie, ie_length,
4286 rssi, GFP_KERNEL ));
4287}
4288 else
4289 {
4290 return bss;
4291 }
4292}
4293
4294
4295
4296/*
4297 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
4298 * This function is used to inform the BSS details to nl80211 interface.
4299 */
4300struct cfg80211_bss*
4301wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
4302 tSirBssDescription *bss_desc
4303 )
4304{
4305 /*
4306 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
4307 already exists in bss data base of cfg80211 for that particular BSS ID.
4308 Using cfg80211_inform_bss_frame to update the bss entry instead of
4309 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
4310 now there is no possibility to get the mgmt(probe response) frame from PE,
4311 converting bss_desc to ieee80211_mgmt(probe response) and passing to
4312 cfg80211_inform_bss_frame.
4313 */
4314 struct net_device *dev = pAdapter->dev;
4315 struct wireless_dev *wdev = dev->ieee80211_ptr;
4316 struct wiphy *wiphy = wdev->wiphy;
4317 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004318#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4319 qcom_ie_age *qie_age = NULL;
4320 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
4321#else
Jeff Johnson295189b2012-06-20 16:38:30 -07004322 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004323#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004324 const char *ie =
4325 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
4326 unsigned int freq;
4327 struct ieee80211_channel *chan;
Abhishek Singh1e2bfa32014-01-02 15:44:15 +05304328 struct ieee80211_mgmt *mgmt = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004329 struct cfg80211_bss *bss_status = NULL;
4330 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
4331 int rssi = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07004332 hdd_context_t *pHddCtx;
4333 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07004334#ifdef WLAN_OPEN_SOURCE
4335 struct timespec ts;
4336#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004337
Wilson Yangf80a0542013-10-07 13:02:37 -07004338 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4339 status = wlan_hdd_validate_context(pHddCtx);
4340
4341 /*bss_update is not allowed during wlan driver loading or unloading*/
4342 if (pHddCtx->isLoadUnloadInProgress)
4343 {
4344 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4345 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
4346 return NULL;
4347 }
4348
4349
4350 if (0 != status)
4351 {
4352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4353 "%s: HDD context is not valid", __func__);
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004354 return NULL;
Wilson Yangf80a0542013-10-07 13:02:37 -07004355 }
4356
Abhishek Singh1e2bfa32014-01-02 15:44:15 +05304357 mgmt = kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
Wilson Yangf80a0542013-10-07 13:02:37 -07004358 if (!mgmt)
4359 {
4360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4361 "%s: memory allocation failed ", __func__);
4362 return NULL;
4363 }
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07004364
Jeff Johnson295189b2012-06-20 16:38:30 -07004365 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07004366
4367#ifdef WLAN_OPEN_SOURCE
4368 /* Android does not want the timestamp from the frame.
4369 Instead it wants a monotonic increasing value */
4370 get_monotonic_boottime(&ts);
4371 mgmt->u.probe_resp.timestamp =
4372 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
4373#else
4374 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07004375 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
4376 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07004377
4378#endif
4379
Jeff Johnson295189b2012-06-20 16:38:30 -07004380 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
4381 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08004382
4383#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
4384 /* GPS Requirement: need age ie per entry. Using vendor specific. */
4385 /* Assuming this is the last IE, copy at the end */
4386 ie_length -=sizeof(qcom_ie_age);
4387 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
4388 qie_age->element_id = QCOM_VENDOR_IE_ID;
4389 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
4390 qie_age->oui_1 = QCOM_OUI1;
4391 qie_age->oui_2 = QCOM_OUI2;
4392 qie_age->oui_3 = QCOM_OUI3;
4393 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
4394 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
4395#endif
4396
Jeff Johnson295189b2012-06-20 16:38:30 -07004397 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05304398 if (bss_desc->fProbeRsp)
4399 {
4400 mgmt->frame_control |=
4401 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
4402 }
4403 else
4404 {
4405 mgmt->frame_control |=
4406 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
4407 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004408
4409#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304410 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004411 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
4412 {
4413 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
4414 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304415 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07004416 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
4417
4418 {
4419 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
4420 }
4421 else
4422 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304423 hddLog(VOS_TRACE_LEVEL_ERROR, "%s Invalid chan_no:%d",
4424 __func__, chan_no);
Jeff Johnson295189b2012-06-20 16:38:30 -07004425 kfree(mgmt);
4426 return NULL;
4427 }
4428#else
4429 freq = ieee80211_channel_to_frequency(chan_no);
4430#endif
4431 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004432 /*when the band is changed on the fly using the GUI, three things are done
4433 * 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)
4434 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
4435 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
4436 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
4437 * and discards the channels correponding to previous band and calls back with zero bss results.
4438 * 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
4439 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
4440 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
4441 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
4442 * So drop the bss and continue to next bss.
4443 */
4444 if(chan == NULL)
4445 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304446 hddLog(VOS_TRACE_LEVEL_ERROR, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07004447 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08004448 return NULL;
4449 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004450 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304451 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07004452 * */
4453 if (( eConnectionState_Associated ==
4454 pAdapter->sessionCtx.station.conn_info.connState ) &&
4455 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
4456 pAdapter->sessionCtx.station.conn_info.bssId,
4457 WNI_CFG_BSSID_LEN)))
4458 {
4459 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
4460 rssi = (pAdapter->rssi * 100);
4461 }
4462 else
4463 {
4464 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
4465 }
4466
Nirav Shah20ac06f2013-12-12 18:14:06 +05304467 hddLog(VOS_TRACE_LEVEL_INFO, "%s: BSSID:" MAC_ADDRESS_STR " Channel:%d"
4468 "RSSI:%d", __func__, MAC_ADDR_ARRAY(mgmt->bssid),
4469 chan->center_freq, (int)(rssi/100));
4470
Jeff Johnson295189b2012-06-20 16:38:30 -07004471 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
4472 frame_len, rssi, GFP_KERNEL);
4473 kfree(mgmt);
4474 return bss_status;
4475}
4476
4477/*
4478 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
4479 * This function is used to update the BSS data base of CFG8011
4480 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304481struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004482 tCsrRoamInfo *pRoamInfo
4483 )
4484{
4485 tCsrRoamConnectedProfile roamProfile;
4486 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4487 struct cfg80211_bss *bss = NULL;
4488
4489 ENTER();
4490
4491 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
4492 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
4493
4494 if (NULL != roamProfile.pBssDesc)
4495 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304496 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004497 &roamProfile);
4498
4499 if (NULL == bss)
4500 {
4501 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
4502 __func__);
4503 }
4504
4505 sme_RoamFreeConnectProfile(hHal, &roamProfile);
4506 }
4507 else
4508 {
4509 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
4510 __func__);
4511 }
4512 return bss;
4513}
4514
4515/*
4516 * FUNCTION: wlan_hdd_cfg80211_update_bss
4517 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304518static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
4519 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07004520 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304521{
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4523 tCsrScanResultInfo *pScanResult;
4524 eHalStatus status = 0;
4525 tScanResultHandle pResult;
4526 struct cfg80211_bss *bss_status = NULL;
Wilson Yangf80a0542013-10-07 13:02:37 -07004527 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004528
4529 ENTER();
4530
Wilson Yangf80a0542013-10-07 13:02:37 -07004531 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4532
4533 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004534 {
Wilson Yangf80a0542013-10-07 13:02:37 -07004535 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4536 "%s:LOGP in Progress. Ignore!!!",__func__);
4537 return -EAGAIN;
Jeff Johnson295189b2012-06-20 16:38:30 -07004538 }
4539
Wilson Yangf80a0542013-10-07 13:02:37 -07004540
4541 /*bss_update is not allowed during wlan driver loading or unloading*/
4542 if (pHddCtx->isLoadUnloadInProgress)
4543 {
4544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4545 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
4546 return VOS_STATUS_E_PERM;
4547 }
4548
4549
Jeff Johnson295189b2012-06-20 16:38:30 -07004550 /*
4551 * start getting scan results and populate cgf80211 BSS database
4552 */
4553 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
4554
4555 /* no scan results */
4556 if (NULL == pResult)
4557 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05304558 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result Status %d",
4559 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004560 return status;
4561 }
4562
4563 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
4564
4565 while (pScanResult)
4566 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304567 /*
4568 * cfg80211_inform_bss() is not updating ie field of bss entry, if
4569 * entry already exists in bss data base of cfg80211 for that
4570 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
4571 * bss entry instead of cfg80211_inform_bss, But this call expects
4572 * mgmt packet as input. As of now there is no possibility to get
4573 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07004574 * ieee80211_mgmt(probe response) and passing to c
4575 * fg80211_inform_bss_frame.
4576 * */
4577
4578 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
4579 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304580
Jeff Johnson295189b2012-06-20 16:38:30 -07004581
4582 if (NULL == bss_status)
4583 {
4584 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08004585 "%s: NULL returned by cfg80211_inform_bss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004586 }
4587 else
4588 {
Yue Maf49ba872013-08-19 12:04:25 -07004589 cfg80211_put_bss(
4590#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
4591 wiphy,
4592#endif
4593 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004594 }
4595
4596 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4597 }
4598
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304599 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07004600
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304601 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004602}
4603
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004604void
4605hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4606{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304607 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Arif Hussaina7c8e412013-11-20 11:06:42 -08004608 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(macAddr));
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004609} /****** end hddPrintMacAddr() ******/
4610
4611void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004612hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004613{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304614 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Arif Hussain6d2a3322013-11-17 19:50:10 -08004615 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004616 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4617 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4618 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004619} /****** end hddPrintPmkId() ******/
4620
4621//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4622//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4623
4624//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4625//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4626
4627#define dump_bssid(bssid) \
4628 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004629 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4630 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004631 }
4632
4633#define dump_pmkid(pMac, pmkid) \
4634 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004635 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4636 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004637 }
4638
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004639#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004640/*
4641 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4642 * This function is used to notify the supplicant of a new PMKSA candidate.
4643 */
4644int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304645 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004646 int index, bool preauth )
4647{
Jeff Johnsone7245742012-09-05 17:12:55 -07004648#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004649 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004650 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004651
4652 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004653 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004654
4655 if( NULL == pRoamInfo )
4656 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004657 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004658 return -EINVAL;
4659 }
4660
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004661 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
4662 {
4663 dump_bssid(pRoamInfo->bssid);
4664 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004665 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004666 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004667#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304668 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004669}
4670#endif //FEATURE_WLAN_LFR
4671
Yue Maef608272013-04-08 23:09:17 -07004672#ifdef FEATURE_WLAN_LFR_METRICS
4673/*
4674 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth
4675 * 802.11r/LFR metrics reporting function to report preauth initiation
4676 *
4677 */
4678#define MAX_LFR_METRICS_EVENT_LENGTH 100
4679VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
4680 tCsrRoamInfo *pRoamInfo)
4681{
4682 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4683 union iwreq_data wrqu;
4684
4685 ENTER();
4686
4687 if (NULL == pAdapter)
4688 {
4689 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4690 return VOS_STATUS_E_FAILURE;
4691 }
4692
4693 /* create the event */
4694 memset(&wrqu, 0, sizeof(wrqu));
4695 memset(metrics_notification, 0, sizeof(metrics_notification));
4696
4697 wrqu.data.pointer = metrics_notification;
4698 wrqu.data.length = scnprintf(metrics_notification,
4699 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_INIT "
4700 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
4701
4702 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4703
4704 EXIT();
4705
4706 return VOS_STATUS_SUCCESS;
4707}
4708
4709/*
4710 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth_status
4711 * 802.11r/LFR metrics reporting function to report preauth completion
4712 * or failure
4713 */
4714VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status(
4715 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, bool preauth_status)
4716{
4717 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4718 union iwreq_data wrqu;
4719
4720 ENTER();
4721
4722 if (NULL == pAdapter)
4723 {
4724 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4725 return VOS_STATUS_E_FAILURE;
4726 }
4727
4728 /* create the event */
4729 memset(&wrqu, 0, sizeof(wrqu));
4730 memset(metrics_notification, 0, sizeof(metrics_notification));
4731
4732 scnprintf(metrics_notification, sizeof(metrics_notification),
4733 "QCOM: LFR_PREAUTH_STATUS "MAC_ADDRESS_STR,
4734 MAC_ADDR_ARRAY(pRoamInfo->bssid));
4735
4736 if (1 == preauth_status)
4737 strncat(metrics_notification, " TRUE", 5);
4738 else
4739 strncat(metrics_notification, " FALSE", 6);
4740
4741 wrqu.data.pointer = metrics_notification;
4742 wrqu.data.length = strlen(metrics_notification);
4743
4744 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4745
4746 EXIT();
4747
4748 return VOS_STATUS_SUCCESS;
4749}
4750
4751/*
4752 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_handover
4753 * 802.11r/LFR metrics reporting function to report handover initiation
4754 *
4755 */
4756VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t * pAdapter,
4757 tCsrRoamInfo *pRoamInfo)
4758{
4759 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
4760 union iwreq_data wrqu;
4761
4762 ENTER();
4763
4764 if (NULL == pAdapter)
4765 {
4766 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
4767 return VOS_STATUS_E_FAILURE;
4768 }
4769
4770 /* create the event */
4771 memset(&wrqu, 0, sizeof(wrqu));
4772 memset(metrics_notification, 0, sizeof(metrics_notification));
4773
4774 wrqu.data.pointer = metrics_notification;
4775 wrqu.data.length = scnprintf(metrics_notification,
4776 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_HANDOVER "
4777 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
4778
4779 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
4780
4781 EXIT();
4782
4783 return VOS_STATUS_SUCCESS;
4784}
4785#endif
4786
Jeff Johnson295189b2012-06-20 16:38:30 -07004787/*
4788 * FUNCTION: hdd_cfg80211_scan_done_callback
4789 * scanning callback function, called after finishing scan
4790 *
4791 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304792static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07004793 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4794{
4795 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304796 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07004797 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004798 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4799 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004800 struct cfg80211_scan_request *req = NULL;
4801 int ret = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304802 long waitRet = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004803
4804 ENTER();
4805
4806 hddLog(VOS_TRACE_LEVEL_INFO,
4807 "%s called with halHandle = %p, pContext = %p,"
Arif Hussain6d2a3322013-11-17 19:50:10 -08004808 "scanID = %d, returned status = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07004809 __func__, halHandle, pContext, (int) scanId, (int) status);
4810
Kiet Lamac06e2c2013-10-23 16:25:07 +05304811 pScanInfo->mScanPendingCounter = 0;
4812
Jeff Johnson295189b2012-06-20 16:38:30 -07004813 //Block on scan req completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304814 waitRet = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004815 &pScanInfo->scan_req_completion_event,
4816 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304817 if (waitRet <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07004818 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304819 hddLog(VOS_TRACE_LEVEL_ERROR,
4820 "%s wait on scan_req_completion_event failed %ld",__func__, waitRet);
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004822 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004823 }
4824
Yue Maef608272013-04-08 23:09:17 -07004825 if (pScanInfo->mScanPending != VOS_TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -07004826 {
4827 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004828 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004829 }
4830
4831 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304832 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 {
4834 hddLog(VOS_TRACE_LEVEL_INFO,
4835 "%s called with mismatched scanId pScanInfo->scanId = %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08004836 "scanId = %d", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07004837 (int) scanId);
4838 }
4839
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304840 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07004841 pAdapter);
4842
4843 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304844 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004845
4846
4847 /* If any client wait scan result through WEXT
4848 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004849 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004850 {
4851 /* The other scan request waiting for current scan finish
4852 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004853 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004854 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004855 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 }
4857 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004858 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004859 {
4860 struct net_device *dev = pAdapter->dev;
4861 union iwreq_data wrqu;
4862 int we_event;
4863 char *msg;
4864
4865 memset(&wrqu, '\0', sizeof(wrqu));
4866 we_event = SIOCGIWSCAN;
4867 msg = NULL;
4868 wireless_send_event(dev, we_event, &wrqu, msg);
4869 }
4870 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004871 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004872
4873 /* Get the Scan Req */
4874 req = pAdapter->request;
4875
4876 if (!req)
4877 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08004878 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004879 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004880 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004881 }
4882
4883 /*
4884 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304885 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004886 req->n_ssids = 0;
4887 req->n_channels = 0;
4888 req->ie = 0;
4889
Jeff Johnson295189b2012-06-20 16:38:30 -07004890 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004891 /* Scan is no longer pending */
4892 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004893
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004894 /*
4895 * cfg80211_scan_done informing NL80211 about completion
4896 * of scanning
4897 */
4898 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004899 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004900
Jeff Johnsone7245742012-09-05 17:12:55 -07004901allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004902 /* release the wake lock at the end of the scan*/
4903 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004904
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004905 /* Acquire wakelock to handle the case where APP's tries to suspend
4906 * immediatly after the driver gets connect request(i.e after scan)
4907 * from supplicant, this result in app's is suspending and not able
4908 * to process the connect request to AP */
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05304909 hdd_prevent_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004910
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07004911#ifdef FEATURE_WLAN_TDLS
4912 wlan_hdd_tdls_scan_done_callback(pAdapter);
4913#endif
4914
Jeff Johnson295189b2012-06-20 16:38:30 -07004915 EXIT();
4916 return 0;
4917}
4918
4919/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004920 * FUNCTION: hdd_isScanAllowed
4921 * Go through each adapter and check if scan allowed
4922 *
4923 */
4924v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4925{
4926 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4927 hdd_station_ctx_t *pHddStaCtx = NULL;
4928 hdd_adapter_t *pAdapter = NULL;
4929 VOS_STATUS status = 0;
4930 v_U8_t staId = 0;
4931 v_U8_t *staMac = NULL;
4932
c_hpothu9b781ba2013-12-30 20:57:45 +05304933 if (TRUE == pHddCtx->btCoexModeSet)
4934 {
4935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4936 FL("BTCoex Mode operation in progress, Do not allow scan"));
4937 return VOS_FALSE;
4938 }
4939
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004940 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4941
4942 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4943 {
4944 pAdapter = pAdapterNode->pAdapter;
4945
4946 if( pAdapter )
4947 {
4948 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304949 "%s: Adapter with device mode %d exists",
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004950 __func__, pAdapter->device_mode);
4951 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4952 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4953 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4954 {
4955 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4956 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4957 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4958 {
4959 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4960 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain24bafea2013-11-15 15:10:03 -08004961 "%s: client " MAC_ADDRESS_STR
4962 " is in the middle of WPS/EAPOL exchange.", __func__,
4963 MAC_ADDR_ARRAY(staMac));
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004964 return VOS_FALSE;
4965 }
4966 }
4967 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4968 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4969 {
4970 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4971 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304972 if ((pAdapter->aStaInfo[staId].isUsed) &&
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004973 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4974 {
4975 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4976
4977 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain24bafea2013-11-15 15:10:03 -08004978 "%s: client " MAC_ADDRESS_STR " of SoftAP/P2P-GO is in the "
4979 "middle of WPS/EAPOL exchange.", __func__,
4980 MAC_ADDR_ARRAY(staMac));
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004981 return VOS_FALSE;
4982 }
4983 }
4984 }
4985 }
4986 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4987 pAdapterNode = pNext;
4988 }
4989 hddLog(VOS_TRACE_LEVEL_INFO,
4990 "%s: Scan allowed", __func__);
4991 return VOS_TRUE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304992}
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004993
4994/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004995 * FUNCTION: wlan_hdd_cfg80211_scan
4996 * this scan respond to scan trigger and update cfg80211 scan database
4997 * later, scan dump command can be used to recieve scan results
4998 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004999int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
5000#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
5001 struct net_device *dev,
5002#endif
5003 struct cfg80211_scan_request *request)
5004{
5005#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
5006 struct net_device *dev = request->wdev->netdev;
5007#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305008 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07005009 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5010 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305011 hdd_config_t *cfg_param = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005012 tCsrScanRequest scanRequest;
5013 tANI_U8 *channelList = NULL, i;
5014 v_U32_t scanId = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305015 int status;
5016 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005017 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005018
5019 ENTER();
5020
Arif Hussain6d2a3322013-11-17 19:50:10 -08005021 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005022 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005023
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305024 status = wlan_hdd_validate_context(pHddCtx);
5025
5026 if (0 != status)
5027 {
5028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5029 "%s: HDD context is not valid", __func__);
5030 return status;
5031 }
5032
5033 cfg_param = pHddCtx->cfg_ini;
5034 pScanInfo = &pHddCtx->scan_info;
5035
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005036 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005037 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005038 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005039 {
5040 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005041 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
5042 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005043 return -EBUSY;
5044 }
5045
Jeff Johnson295189b2012-06-20 16:38:30 -07005046#ifdef WLAN_BTAMP_FEATURE
5047 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005048 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07005049 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005050 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005051 "%s: No scanning when AMP is on", __func__);
5052 return -EOPNOTSUPP;
5053 }
5054#endif
5055 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005056 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07005057 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005058 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005059 "%s: Not scanning on device_mode = %d",
5060 __func__, pAdapter->device_mode);
5061 return -EOPNOTSUPP;
5062 }
5063
5064 if (TRUE == pScanInfo->mScanPending)
5065 {
Kiet Lamac06e2c2013-10-23 16:25:07 +05305066 if ( MAX_PENDING_LOG > pScanInfo->mScanPendingCounter++ )
5067 {
5068 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: mScanPending is TRUE", __func__);
5069 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005070 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07005071 }
5072
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305073 //Don't Allow Scan and return busy if Remain On
Jeff Johnson32d95a32012-09-10 13:15:23 -07005074 //Channel and action frame is pending
5075 //Otherwise Cancel Remain On Channel and allow Scan
5076 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005077 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07005078 {
Kiet Lamac06e2c2013-10-23 16:25:07 +05305079 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Remain On Channel Pending", __func__);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005080 return -EBUSY;
5081 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005082#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005083 /* if tdls disagree scan right now, return immediately.
5084 tdls will schedule the scan when scan is allowed. (return SUCCESS)
5085 or will reject the scan if any TDLS is in progress. (return -EBUSY)
5086 */
5087 status = wlan_hdd_tdls_scan_callback (pAdapter,
5088 wiphy,
5089#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
5090 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07005091#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005092 request);
5093 if(status <= 0)
5094 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305095 if(!status)
5096 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS in progress."
5097 "scan rejected %d", __func__, status);
5098 else
5099 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS teardown is ongoing %d",
5100 __func__, status);
5101
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07005102 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08005103 }
5104#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07005105
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
5107 {
5108 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08005109 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005110 return -EAGAIN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305111 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005112 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
5113 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305114 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005115 "%s: MAX TM Level Scan not allowed", __func__);
5116 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305117 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07005118 }
5119 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
5120
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08005121 /* Check if scan is allowed at this point of time.
5122 */
5123 if (!hdd_isScanAllowed(pHddCtx))
5124 {
5125 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
5126 return -EBUSY;
5127 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305128
Jeff Johnson295189b2012-06-20 16:38:30 -07005129 vos_mem_zero( &scanRequest, sizeof(scanRequest));
5130
5131 if (NULL != request)
5132 {
5133 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305134 (int)request->n_ssids);
Jeff Johnson295189b2012-06-20 16:38:30 -07005135
5136 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
5137 * Becasue of this, driver is assuming that this is not wildcard scan and so
5138 * is not aging out the scan results.
5139 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07005140 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07005141 {
5142 request->n_ssids = 0;
5143 }
5144
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005145 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07005146 {
5147 tCsrSSIDInfo *SsidInfo;
5148 int j;
5149 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
5150 /* Allocate num_ssid tCsrSSIDInfo structure */
5151 SsidInfo = scanRequest.SSIDs.SSIDList =
5152 ( tCsrSSIDInfo *)vos_mem_malloc(
5153 request->n_ssids*sizeof(tCsrSSIDInfo));
5154
5155 if(NULL == scanRequest.SSIDs.SSIDList)
5156 {
5157 hddLog(VOS_TRACE_LEVEL_ERROR,
Nirav Shah20ac06f2013-12-12 18:14:06 +05305158 "%s: memory alloc failed SSIDInfo buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 return -ENOMEM;
5160 }
5161
5162 /* copy all the ssid's and their length */
5163 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
5164 {
5165 /* get the ssid length */
5166 SsidInfo->SSID.length = request->ssids[j].ssid_len;
5167 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
5168 SsidInfo->SSID.length);
5169 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
Nirav Shah20ac06f2013-12-12 18:14:06 +05305170 hddLog(VOS_TRACE_LEVEL_INFO, "SSID number %d: %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 j, SsidInfo->SSID.ssId);
5172 }
5173 /* set the scan type to active */
5174 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5175 }
5176 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
5177 {
5178 /* set the scan type to active */
5179 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5180 }
5181 else
5182 {
5183 /*Set the scan type to default type, in this case it is ACTIVE*/
5184 scanRequest.scanType = pScanInfo->scan_mode;
5185 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305186 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
5188 }
5189 else
5190 {
5191 /* set the scan type to active */
5192 scanRequest.scanType = eSIR_ACTIVE_SCAN;
5193 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
5194
5195 /* set min and max channel time to zero */
5196 scanRequest.minChnTime = 0;
5197 scanRequest.maxChnTime = 0;
5198 }
5199
5200 /* set BSSType to default type */
5201 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
5202
5203 /*TODO: scan the requested channels only*/
5204
5205 /*Right now scanning all the channels */
5206 if( request )
5207 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305208 hddLog(VOS_TRACE_LEVEL_INFO,
5209 "No of Scan Channels: %d", request->n_channels);
Jeff Johnson295189b2012-06-20 16:38:30 -07005210 if( request->n_channels )
5211 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305212 char chList [(request->n_channels*5)+1];
5213 int len;
Jeff Johnson295189b2012-06-20 16:38:30 -07005214 channelList = vos_mem_malloc( request->n_channels );
5215 if( NULL == channelList )
5216 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305217 hddLog(VOS_TRACE_LEVEL_ERROR,
Nirav Shah20ac06f2013-12-12 18:14:06 +05305218 "%s: memory alloc failed channelList", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005219 status = -ENOMEM;
5220 goto free_mem;
5221 }
5222
Nirav Shah20ac06f2013-12-12 18:14:06 +05305223 for( i = 0, len = 0; i < request->n_channels ; i++ )
5224 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005225 channelList[i] = request->channels[i]->hw_value;
Nirav Shah20ac06f2013-12-12 18:14:06 +05305226 len += snprintf(chList+len, 5, "%d ", channelList[i]);
5227 }
5228
5229 hddLog(VOS_TRACE_LEVEL_INFO,
5230 "Channel-List: %s ", chList);
Jeff Johnson295189b2012-06-20 16:38:30 -07005231 }
5232
5233 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
5234 scanRequest.ChannelInfo.ChannelList = channelList;
5235
5236 /* set requestType to full scan */
5237 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305238
5239 /* Flush the scan results(only p2p beacons) for STA scan and P2P
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005240 * search (Flush on both full scan and social scan but not on single
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305241 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005242 */
5243
5244 /* Supplicant does single channel scan after 8-way handshake
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305245 * and in that case driver shoudnt flush scan results. If
5246 * driver flushes the scan results here and unfortunately if
5247 * the AP doesnt respond to our probe req then association
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005248 * fails which is not desired
5249 */
5250
5251 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
5252 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305253 hddLog(VOS_TRACE_LEVEL_DEBUG, "Flushing P2P Results");
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08005254 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
5255 pAdapter->sessionId );
5256 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005257
5258 if( request->ie_len )
5259 {
5260 /* save this for future association (join requires this) */
Agarwal Ashish4f616132013-12-30 23:32:50 +05305261 /*TODO: Array needs to be converted to dynamic allocation,
5262 * as multiple ie.s can be sent in cfg80211_scan_request structure
5263 * CR 597966
5264 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005265 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
5266 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
5267 pScanInfo->scanAddIE.length = request->ie_len;
5268
Agarwal Ashish4f616132013-12-30 23:32:50 +05305269 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07005270 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
Agarwal Ashish4f616132013-12-30 23:32:50 +05305271 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07005272 {
Agarwal Ashish4f616132013-12-30 23:32:50 +05305273 if ( request->ie_len <= SIR_MAC_MAX_IE_LENGTH)
5274 {
5275 pwextBuf->roamProfile.nAddIEScanLength = request->ie_len;
5276 memcpy( pwextBuf->roamProfile.addIEScan,
5277 request->ie, request->ie_len);
5278 }
5279 else
5280 {
5281 hddLog(VOS_TRACE_LEVEL_ERROR, "Scan Ie length is invalid:"
5282 "%d", request->ie_len);
5283 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005284
Agarwal Ashish4f616132013-12-30 23:32:50 +05305285 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005286 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
5287 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
5288
Jeff Johnson295189b2012-06-20 16:38:30 -07005289 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
5290 request->ie_len);
5291 if (pP2pIe != NULL)
5292 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07005293#ifdef WLAN_FEATURE_P2P_DEBUG
5294 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
5295 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
5296 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5297 {
5298 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
5299 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
5300 "Go nego completed to Connection is started");
5301 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
5302 "for 8way Handshake");
5303 }
5304 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
5305 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5306 {
5307 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
5308 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
5309 "Disconnected state to Connection is started");
5310 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
5311 "for 4way Handshake");
5312 }
5313#endif
5314
Jeff Johnsone7245742012-09-05 17:12:55 -07005315 /* no_cck will be set during p2p find to disable 11b rates */
5316 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07005317 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005318 hddLog(VOS_TRACE_LEVEL_INFO,
5319 "%s: This is a P2P Search", __func__);
5320 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07005321
Jeff Johnsone7245742012-09-05 17:12:55 -07005322 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
5323 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07005324 /* set requestType to P2P Discovery */
5325 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07005326 }
5327
5328 /*
5329 Skip Dfs Channel in case of P2P Search
5330 if it is set in ini file
5331 */
5332 if(cfg_param->skipDfsChnlInP2pSearch)
5333 {
5334 scanRequest.skipDfsChnlInP2pSearch = 1;
5335 }
5336 else
5337 {
5338 scanRequest.skipDfsChnlInP2pSearch = 0;
5339 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005340
Jeff Johnson295189b2012-06-20 16:38:30 -07005341 }
5342 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005343 }
5344 }
5345
5346 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
5347
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07005348 /* acquire the wakelock to avoid the apps suspend during the scan. To
5349 * address the following issues.
5350 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
5351 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
5352 * for long time, this result in apps running at full power for long time.
5353 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
5354 * be stuck in full power because of resume BMPS
5355 */
5356 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005357
Nirav Shah20ac06f2013-12-12 18:14:06 +05305358 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
5359 "requestType %d, scanType %d, minChnTime %d, maxChnTime %d,"
5360 "p2pSearch %d, skipDfsChnlInP2pSearch %d", scanRequest.requestType,
5361 scanRequest.scanType, scanRequest.minChnTime, scanRequest.maxChnTime,
5362 scanRequest.p2pSearch, scanRequest.skipDfsChnlInP2pSearch);
5363
Jeff Johnsone7245742012-09-05 17:12:55 -07005364 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005365 pAdapter->sessionId, &scanRequest, &scanId,
5366 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07005367
Jeff Johnson295189b2012-06-20 16:38:30 -07005368 if (eHAL_STATUS_SUCCESS != status)
5369 {
5370 hddLog(VOS_TRACE_LEVEL_ERROR,
5371 "%s: sme_ScanRequest returned error %d", __func__, status);
5372 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07005373 if(eHAL_STATUS_RESOURCES == status)
5374 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05305375 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HO is in progress."
5376 "So defer the scan by informing busy",__func__);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07005377 status = -EBUSY;
5378 } else {
5379 status = -EIO;
5380 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07005381 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005382 goto free_mem;
5383 }
5384
5385 pScanInfo->mScanPending = TRUE;
5386 pAdapter->request = request;
5387 pScanInfo->scanId = scanId;
5388
5389 complete(&pScanInfo->scan_req_completion_event);
5390
5391free_mem:
5392 if( scanRequest.SSIDs.SSIDList )
5393 {
5394 vos_mem_free(scanRequest.SSIDs.SSIDList);
5395 }
5396
5397 if( channelList )
5398 vos_mem_free( channelList );
5399
5400 EXIT();
5401
5402 return status;
5403}
5404
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005405
5406void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
5407{
5408 v_U8_t iniDot11Mode =
5409 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
5410 eHddDot11Mode hddDot11Mode = iniDot11Mode;
5411
5412 switch ( iniDot11Mode )
5413 {
5414 case eHDD_DOT11_MODE_AUTO:
5415 case eHDD_DOT11_MODE_11ac:
5416 case eHDD_DOT11_MODE_11ac_ONLY:
5417#ifdef WLAN_FEATURE_11AC
5418 hddDot11Mode = eHDD_DOT11_MODE_11ac;
5419#else
5420 hddDot11Mode = eHDD_DOT11_MODE_11n;
5421#endif
5422 break;
5423 case eHDD_DOT11_MODE_11n:
5424 case eHDD_DOT11_MODE_11n_ONLY:
5425 hddDot11Mode = eHDD_DOT11_MODE_11n;
5426 break;
5427 default:
5428 hddDot11Mode = iniDot11Mode;
5429 break;
5430 }
5431 /* This call decides required channel bonding mode */
5432 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
5433 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
5434 operationChannel);
5435}
5436
Jeff Johnson295189b2012-06-20 16:38:30 -07005437/*
5438 * FUNCTION: wlan_hdd_cfg80211_connect_start
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305439 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -07005440 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305441int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005442 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07005443{
5444 int status = 0;
5445 hdd_wext_state_t *pWextState;
5446 v_U32_t roamId;
5447 tCsrRoamProfile *pRoamProfile;
Jeff Johnson295189b2012-06-20 16:38:30 -07005448 eCsrAuthType RSNAuthType;
5449
5450 ENTER();
5451
5452 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305453
Jeff Johnson295189b2012-06-20 16:38:30 -07005454 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
5455 {
5456 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
5457 return -EINVAL;
5458 }
5459
5460 pRoamProfile = &pWextState->roamProfile;
5461
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305462 if (pRoamProfile)
Jeff Johnson295189b2012-06-20 16:38:30 -07005463 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005464 hdd_station_ctx_t *pHddStaCtx;
5465 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005466
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305467 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
5469 {
5470 /*QoS not enabled in cfg file*/
5471 pRoamProfile->uapsd_mask = 0;
5472 }
5473 else
5474 {
5475 /*QoS enabled, update uapsd mask from cfg file*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305476 pRoamProfile->uapsd_mask =
Jeff Johnson295189b2012-06-20 16:38:30 -07005477 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
5478 }
5479
5480 pRoamProfile->SSIDs.numOfSSIDs = 1;
5481 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
5482 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305483 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Jeff Johnson295189b2012-06-20 16:38:30 -07005484 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
5485 ssid, ssid_len);
5486
5487 if (bssid)
5488 {
5489 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
5490 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
5491 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305492 /* Save BSSID in seperate variable as well, as RoamProfile
5493 BSSID is getting zeroed out in the association process. And in
Jeff Johnson295189b2012-06-20 16:38:30 -07005494 case of join failure we should send valid BSSID to supplicant
5495 */
5496 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
5497 WNI_CFG_BSSID_LEN);
5498 }
Dhanashri Atre51981c62013-06-13 11:47:57 -07005499 else
5500 {
5501 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
5502 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005503
5504 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
5505 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305506 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005507 /*set gen ie*/
5508 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
5509 /*set auth*/
5510 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
5511 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005512#ifdef FEATURE_WLAN_WAPI
5513 if (pAdapter->wapi_info.nWapiMode)
5514 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005515 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005516 switch (pAdapter->wapi_info.wapiAuthMode)
5517 {
5518 case WAPI_AUTH_MODE_PSK:
5519 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005520 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005521 pAdapter->wapi_info.wapiAuthMode);
5522 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
5523 break;
5524 }
5525 case WAPI_AUTH_MODE_CERT:
5526 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005527 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005528 pAdapter->wapi_info.wapiAuthMode);
5529 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
5530 break;
5531 }
5532 } // End of switch
5533 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
5534 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
5535 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005536 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005537 pRoamProfile->AuthType.numEntries = 1;
5538 pRoamProfile->EncryptionType.numEntries = 1;
5539 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5540 pRoamProfile->mcEncryptionType.numEntries = 1;
5541 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
5542 }
5543 }
5544#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305545#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305546 /* Initializing gtkOffloadReqParams */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305547 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5548 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
5549 {
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05305550 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
5551 sizeof (tSirGtkOffloadParams));
5552 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05305553 }
5554#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005555 pRoamProfile->csrPersona = pAdapter->device_mode;
5556
Jeff Johnson32d95a32012-09-10 13:15:23 -07005557 if( operatingChannel )
5558 {
5559 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
5560 pRoamProfile->ChannelInfo.numOfChannels = 1;
5561 }
Chet Lanctot186b5732013-03-18 10:26:30 -07005562 else
5563 {
5564 pRoamProfile->ChannelInfo.ChannelList = NULL;
5565 pRoamProfile->ChannelInfo.numOfChannels = 0;
5566 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07005567 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
5568 {
5569 hdd_select_cbmode(pAdapter,operatingChannel);
5570 }
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005571 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
5572 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305573 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005574 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005575 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
5576 */
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305577 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5578 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005579 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
5580 eConnectionState_Connecting);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305581
5582 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07005583 pAdapter->sessionId, pRoamProfile, &roamId);
5584
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305585 if ((eHAL_STATUS_SUCCESS != status) &&
5586 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
5587 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305588
5589 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005590 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
5591 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
5592 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305593 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08005594 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05305595 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08005596
5597 pRoamProfile->ChannelInfo.ChannelList = NULL;
5598 pRoamProfile->ChannelInfo.numOfChannels = 0;
5599
Jeff Johnson295189b2012-06-20 16:38:30 -07005600 }
5601 else
5602 {
5603 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
5604 return -EINVAL;
5605 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08005606 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005607 return status;
5608}
5609
5610/*
5611 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
5612 * This function is used to set the authentication type (OPEN/SHARED).
5613 *
5614 */
5615static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
5616 enum nl80211_auth_type auth_type)
5617{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305618 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005619 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5620
5621 ENTER();
5622
5623 /*set authentication type*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305624 switch (auth_type)
Jeff Johnson295189b2012-06-20 16:38:30 -07005625 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005626 case NL80211_AUTHTYPE_AUTOMATIC:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305627 hddLog(VOS_TRACE_LEVEL_INFO,
5628 "%s: set authentication type to AUTOSWITCH", __func__);
5629 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
5630 break;
5631
5632 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07005633#ifdef WLAN_FEATURE_VOWIFI_11R
5634 case NL80211_AUTHTYPE_FT:
5635#endif /* WLAN_FEATURE_VOWIFI_11R */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305636 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005637 "%s: set authentication type to OPEN", __func__);
5638 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5639 break;
5640
5641 case NL80211_AUTHTYPE_SHARED_KEY:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305642 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005643 "%s: set authentication type to SHARED", __func__);
5644 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
5645 break;
5646#ifdef FEATURE_WLAN_CCX
5647 case NL80211_AUTHTYPE_NETWORK_EAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305648 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07005649 "%s: set authentication type to CCKM WPA", __func__);
5650 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
5651 break;
5652#endif
5653
5654
5655 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305656 hddLog(VOS_TRACE_LEVEL_ERROR,
5657 "%s: Unsupported authentication type %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07005658 auth_type);
5659 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
5660 return -EINVAL;
5661 }
5662
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305663 pWextState->roamProfile.AuthType.authType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005664 pHddStaCtx->conn_info.authType;
5665 return 0;
5666}
5667
5668/*
5669 * FUNCTION: wlan_hdd_set_akm_suite
5670 * This function is used to set the key mgmt type(PSK/8021x).
5671 *
5672 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305673static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07005674 u32 key_mgmt
5675 )
5676{
5677 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5678 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305679
Jeff Johnson295189b2012-06-20 16:38:30 -07005680 /*set key mgmt type*/
5681 switch(key_mgmt)
5682 {
5683 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305684#ifdef WLAN_FEATURE_VOWIFI_11R
5685 case WLAN_AKM_SUITE_FT_PSK:
5686#endif
5687 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07005688 __func__);
5689 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
5690 break;
5691
5692 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05305693#ifdef WLAN_FEATURE_VOWIFI_11R
5694 case WLAN_AKM_SUITE_FT_8021X:
5695#endif
5696 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07005697 __func__);
5698 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
5699 break;
5700#ifdef FEATURE_WLAN_CCX
5701#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
5702#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
5703 case WLAN_AKM_SUITE_CCKM:
5704 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
5705 __func__);
5706 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
5707 break;
5708#endif
5709
5710 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305711 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005712 __func__, key_mgmt);
5713 return -EINVAL;
5714
5715 }
5716 return 0;
5717}
5718
5719/*
5720 * FUNCTION: wlan_hdd_cfg80211_set_cipher
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305721 * This function is used to set the encryption type
Jeff Johnson295189b2012-06-20 16:38:30 -07005722 * (NONE/WEP40/WEP104/TKIP/CCMP).
5723 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305724static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
5725 u32 cipher,
Jeff Johnson295189b2012-06-20 16:38:30 -07005726 bool ucast
5727 )
5728{
5729 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305730 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005731 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5732
5733 ENTER();
5734
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305735 if (!cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005736 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305737 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
Jeff Johnson295189b2012-06-20 16:38:30 -07005738 __func__, cipher);
5739 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5740 }
5741 else
5742 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305743
Jeff Johnson295189b2012-06-20 16:38:30 -07005744 /*set encryption method*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305745 switch (cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07005746 {
5747 case IW_AUTH_CIPHER_NONE:
5748 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5749 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305750
Jeff Johnson295189b2012-06-20 16:38:30 -07005751 case WLAN_CIPHER_SUITE_WEP40:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305752 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305754
Jeff Johnson295189b2012-06-20 16:38:30 -07005755 case WLAN_CIPHER_SUITE_WEP104:
Gopichand Nakkala29149562013-05-10 21:43:41 +05305756 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
Jeff Johnson295189b2012-06-20 16:38:30 -07005757 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305758
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 case WLAN_CIPHER_SUITE_TKIP:
5760 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5761 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305762
Jeff Johnson295189b2012-06-20 16:38:30 -07005763 case WLAN_CIPHER_SUITE_CCMP:
5764 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5765 break;
5766#ifdef FEATURE_WLAN_WAPI
5767 case WLAN_CIPHER_SUITE_SMS4:
5768 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5769 break;
5770#endif
5771
5772#ifdef FEATURE_WLAN_CCX
5773 case WLAN_CIPHER_SUITE_KRK:
5774 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5775 break;
5776#endif
5777 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305778 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005779 __func__, cipher);
5780 return -EOPNOTSUPP;
5781 }
5782 }
5783
5784 if (ucast)
5785 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305786 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005787 __func__, encryptionType);
5788 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5789 pWextState->roamProfile.EncryptionType.numEntries = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305790 pWextState->roamProfile.EncryptionType.encryptionType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 encryptionType;
5792 }
5793 else
5794 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305795 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005796 __func__, encryptionType);
5797 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5798 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5799 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5800 }
5801
5802 return 0;
5803}
5804
5805
5806/*
5807 * FUNCTION: wlan_hdd_cfg80211_set_ie
5808 * This function is used to parse WPA/RSN IE's.
5809 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305810int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5811 u8 *ie,
Jeff Johnson295189b2012-06-20 16:38:30 -07005812 size_t ie_len
5813 )
5814{
5815 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5816 u8 *genie = ie;
5817 v_U16_t remLen = ie_len;
5818#ifdef FEATURE_WLAN_WAPI
5819 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5820 u16 *tmp;
5821 v_U16_t akmsuiteCount;
5822 int *akmlist;
5823#endif
5824 ENTER();
5825
5826 /* clear previous assocAddIE */
5827 pWextState->assocAddIE.length = 0;
5828 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5829
5830 while (remLen >= 2)
5831 {
5832 v_U16_t eLen = 0;
5833 v_U8_t elementId;
5834 elementId = *genie++;
5835 eLen = *genie++;
5836 remLen -= 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305837
Arif Hussain6d2a3322013-11-17 19:50:10 -08005838 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005839 __func__, elementId, eLen);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305840
5841 switch ( elementId )
Jeff Johnson295189b2012-06-20 16:38:30 -07005842 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305843 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005844 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 -07005845 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305846 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 "%s: Invalid WPA IE", __func__);
5848 return -EINVAL;
5849 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305850 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
Jeff Johnson295189b2012-06-20 16:38:30 -07005851 {
5852 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305853 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005854 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305855
Jeff Johnson295189b2012-06-20 16:38:30 -07005856 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5857 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005858 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5859 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 VOS_ASSERT(0);
5861 return -ENOMEM;
5862 }
5863 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5864 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5865 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305866
Jeff Johnson295189b2012-06-20 16:38:30 -07005867 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5868 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5869 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5870 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305871 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5872 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005873 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5874 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5875 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5876 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5877 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5878 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305879 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
Kiet Lam8da98992013-11-21 15:59:07 +05305880 P2P_OUI_TYPE_SIZE)))
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 {
5882 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305883 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305885
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5887 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005888 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5889 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 VOS_ASSERT(0);
5891 return -ENOMEM;
5892 }
5893 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5894 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5895 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305896
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5898 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5899 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005900#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305901 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5902 WFD_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07005903 /*Consider WFD IE, only for P2P Client */
5904 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5905 {
5906 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305907 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07005908 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305909
Jeff Johnson295189b2012-06-20 16:38:30 -07005910 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5911 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005912 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5913 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005914 VOS_ASSERT(0);
5915 return -ENOMEM;
5916 }
5917 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5918 // WPS IE + P2P IE + WFD IE
5919 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5920 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305921
Jeff Johnson295189b2012-06-20 16:38:30 -07005922 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5923 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5924 }
5925#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005926 /* Appending HS 2.0 Indication Element in Assiciation Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305927 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005928 HS20_OUI_TYPE_SIZE)) )
5929 {
5930 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305931 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005932 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005933
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005934 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5935 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005936 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5937 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005938 VOS_ASSERT(0);
5939 return -ENOMEM;
5940 }
5941 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5942 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005943
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005944 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5945 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5946 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005947
Praveen Kumar Sirisilla7d68b7b2013-09-22 14:01:42 -07005948 if (WLAN_HDD_IBSS == pAdapter->device_mode) {
5949
5950 /* populating as ADDIE in beacon frames */
5951 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
5952 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie - 2, eLen + 2,
5953 NULL, eANI_BOOLEAN_FALSE)== eHAL_STATUS_SUCCESS)
5954 {
5955 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5956 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5957 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5958 {
5959 hddLog(LOGE,
5960 "Coldn't pass "
5961 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
5962 }
5963 }/* ccmCfgSetStr(,WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, , )*/
5964 else
5965 hddLog(LOGE,
5966 "Could not pass on "
5967 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
5968
5969 /* IBSS mode doesn't contain params->proberesp_ies still
5970 beaconIE's need to be populated in probe response frames */
5971 if ( (NULL != (genie - 2)) && (0 != eLen + 2) )
5972 {
5973 u16 rem_probe_resp_ie_len = eLen + 2;
5974 u8 probe_rsp_ie_len[3] = {0};
5975 u8 counter = 0;
5976
5977 /* Check Probe Resp Length if it is greater then 255 then
5978 Store Probe Rsp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1
5979 & WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are
5980 not able Store More then 255 bytes into One Variable */
5981
5982 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
5983 {
5984 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
5985 {
5986 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
5987 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
5988 }
5989 else
5990 {
5991 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
5992 rem_probe_resp_ie_len = 0;
5993 }
5994 }
5995
5996 rem_probe_resp_ie_len = 0;
5997
5998 if (probe_rsp_ie_len[0] > 0)
5999 {
6000 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
6001 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
6002 (tANI_U8*)(genie - 2),
6003 probe_rsp_ie_len[0], NULL,
6004 eANI_BOOLEAN_FALSE)
6005 == eHAL_STATUS_FAILURE)
6006 {
6007 hddLog(LOGE,
6008 "Could not pass"
6009 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
6010 }
6011 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
6012 }
6013
6014 if (probe_rsp_ie_len[1] > 0)
6015 {
6016 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
6017 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
6018 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
6019 probe_rsp_ie_len[1], NULL,
6020 eANI_BOOLEAN_FALSE)
6021 == eHAL_STATUS_FAILURE)
6022 {
6023 hddLog(LOGE,
6024 "Could not pass"
6025 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
6026 }
6027 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
6028 }
6029
6030 if (probe_rsp_ie_len[2] > 0)
6031 {
6032 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
6033 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
6034 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
6035 probe_rsp_ie_len[2], NULL,
6036 eANI_BOOLEAN_FALSE)
6037 == eHAL_STATUS_FAILURE)
6038 {
6039 hddLog(LOGE,
6040 "Could not pass"
6041 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
6042 }
6043 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
6044 }
6045
6046 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
6047 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
6048 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
6049 {
6050 hddLog(LOGE,
6051 "Could not pass"
6052 "on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
6053 }
6054 }
6055 else
6056 {
6057 // Reset WNI_CFG_PROBE_RSP Flags
6058 wlan_hdd_reset_prob_rspies(pAdapter);
6059
6060 hddLog(VOS_TRACE_LEVEL_INFO,
6061 "%s: No Probe Response IE received in set beacon",
6062 __func__);
6063 }
6064 } /* end of if (WLAN_HDD_IBSS == pAdapter->device_mode) */
Jeff Johnson295189b2012-06-20 16:38:30 -07006065 break;
6066 case DOT11F_EID_RSN:
6067 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
6068 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
6069 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
6070 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
6071 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
6072 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006073 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
6074 case DOT11F_EID_EXTCAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306075 {
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006076 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306077 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006078 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306079
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006080 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
6081 {
Jeff Johnson902c9832012-12-10 14:28:09 -08006082 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
6083 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006084 VOS_ASSERT(0);
6085 return -ENOMEM;
6086 }
6087 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
6088 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306089
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006090 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
6091 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
6092 break;
6093 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006094#ifdef FEATURE_WLAN_WAPI
6095 case WLAN_EID_WAPI:
6096 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006097 hddLog(VOS_TRACE_LEVEL_INFO, "WAPI MODE IS %u",
Jeff Johnson295189b2012-06-20 16:38:30 -07006098 pAdapter->wapi_info.nWapiMode);
6099 tmp = (u16 *)ie;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306100 tmp = tmp + 2; // Skip element Id and Len, Version
Jeff Johnson295189b2012-06-20 16:38:30 -07006101 akmsuiteCount = WPA_GET_LE16(tmp);
6102 tmp = tmp + 1;
6103 akmlist = (int *)(tmp);
6104 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
6105 {
6106 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
6107 }
6108 else
6109 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006110 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count");
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 VOS_ASSERT(0);
6112 return -EINVAL;
6113 }
6114
6115 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
6116 {
6117 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006118 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006119 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306120 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006121 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306122 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006123 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006124 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006125 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
6126 }
6127 break;
6128#endif
6129 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306130 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006131 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07006132 /* when Unknown IE is received we should break and continue
6133 * to the next IE in the buffer instead we were returning
6134 * so changing this to break */
6135 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006136 }
6137 genie += eLen;
6138 remLen -= eLen;
6139 }
6140 EXIT();
6141 return 0;
6142}
6143
6144/*
Gopichand Nakkala18f0c262013-05-07 23:25:08 +05306145 * FUNCTION: hdd_isWPAIEPresent
6146 * Parse the received IE to find the WPA IE
6147 *
6148 */
6149static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len)
6150{
6151 v_U8_t eLen = 0;
6152 v_U16_t remLen = ie_len;
6153 v_U8_t elementId = 0;
6154
6155 while (remLen >= 2)
6156 {
6157 elementId = *ie++;
6158 eLen = *ie++;
6159 remLen -= 2;
6160 if (eLen > remLen)
6161 {
6162 hddLog(VOS_TRACE_LEVEL_ERROR,
6163 "%s: IE length is wrong %d", __func__, eLen);
6164 return FALSE;
6165 }
6166 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
6167 {
6168 /* OUI - 0x00 0X50 0XF2
6169 WPA Information Element - 0x01
6170 WPA version - 0x01*/
6171 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
6172 return TRUE;
6173 }
6174 ie += eLen;
6175 remLen -= eLen;
6176 }
6177 return FALSE;
6178}
6179
6180/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306182 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006183 * parameters during connect operation.
6184 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306185int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07006186 struct cfg80211_connect_params *req
6187 )
6188{
6189 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306190 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 ENTER();
6192
6193 /*set wpa version*/
6194 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
6195
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306196 if (req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07006197 {
Gopichand Nakkala781ded42013-06-28 12:10:45 +05306198 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07006199 {
6200 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
6201 }
6202 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
6203 {
6204 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
6205 }
6206 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306207
6208 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07006209 pWextState->wpaVersion);
6210
6211 /*set authentication type*/
6212 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
6213
6214 if (0 > status)
6215 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306216 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006217 "%s: failed to set authentication type ", __func__);
6218 return status;
6219 }
6220
6221 /*set key mgmt type*/
6222 if (req->crypto.n_akm_suites)
6223 {
6224 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
6225 if (0 > status)
6226 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306227 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
Jeff Johnson295189b2012-06-20 16:38:30 -07006228 __func__);
6229 return status;
6230 }
6231 }
6232
6233 /*set pairwise cipher type*/
6234 if (req->crypto.n_ciphers_pairwise)
6235 {
6236 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
6237 req->crypto.ciphers_pairwise[0], true);
6238 if (0 > status)
6239 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306240 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006241 "%s: failed to set unicast cipher type", __func__);
6242 return status;
6243 }
6244 }
6245 else
6246 {
6247 /*Reset previous cipher suite to none*/
6248 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
6249 if (0 > status)
6250 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306251 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006252 "%s: failed to set unicast cipher type", __func__);
6253 return status;
6254 }
6255 }
6256
6257 /*set group cipher type*/
6258 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
6259 false);
6260
6261 if (0 > status)
6262 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306263 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
Jeff Johnson295189b2012-06-20 16:38:30 -07006264 __func__);
6265 return status;
6266 }
6267
Chet Lanctot186b5732013-03-18 10:26:30 -07006268#ifdef WLAN_FEATURE_11W
6269 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
6270#endif
6271
Jeff Johnson295189b2012-06-20 16:38:30 -07006272 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
6273 if (req->ie_len)
6274 {
6275 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
6276 if ( 0 > status)
6277 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306278 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006279 __func__);
6280 return status;
6281 }
6282 }
6283
6284 /*incase of WEP set default key information*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306285 if (req->key && req->key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 {
6287 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
6288 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
6289 )
6290 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306291 if ( IW_AUTH_KEY_MGMT_802_1X
Jeff Johnson295189b2012-06-20 16:38:30 -07006292 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
6293 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306294 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07006295 __func__);
6296 return -EOPNOTSUPP;
6297 }
6298 else
6299 {
6300 u8 key_len = req->key_len;
6301 u8 key_idx = req->key_idx;
6302
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306303 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -07006304 && (CSR_MAX_NUM_KEY > key_idx)
6305 )
6306 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306307 hddLog(VOS_TRACE_LEVEL_INFO,
6308 "%s: setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07006309 __func__, key_idx, key_len);
6310 vos_mem_copy(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306311 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07006312 req->key, key_len);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306313 pWextState->roamProfile.Keys.KeyLength[key_idx] =
Jeff Johnson295189b2012-06-20 16:38:30 -07006314 (u8)key_len;
6315 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
6316 }
6317 }
6318 }
6319 }
6320
6321 return status;
6322}
6323
6324/*
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306325 * FUNCTION: wlan_hdd_try_disconnect
6326 * This function is used to disconnect from previous
6327 * connection
6328 */
6329static int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter )
6330{
6331 long ret = 0;
6332 hdd_station_ctx_t *pHddStaCtx;
6333 eMib_dot11DesiredBssType connectedBssType;
6334
6335 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6336
6337 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
6338
6339 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
6340 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
6341 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
6342 {
6343 /* Issue disconnect to CSR */
6344 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6345 if( eHAL_STATUS_SUCCESS ==
6346 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
6347 pAdapter->sessionId,
6348 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
6349 {
6350 ret = wait_for_completion_interruptible_timeout(
6351 &pAdapter->disconnect_comp_var,
6352 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6353 if (0 >= ret)
6354 {
6355 hddLog(LOGE, FL("Failed to receive disconnect event"));
6356 return -EALREADY;
6357 }
6358 }
6359 }
6360 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
6361 {
6362 ret = wait_for_completion_interruptible_timeout(
6363 &pAdapter->disconnect_comp_var,
6364 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6365 if (0 >= ret)
6366 {
6367 hddLog(LOGE, FL("Failed to receive disconnect event"));
6368 return -EALREADY;
6369 }
6370 }
6371
6372 return 0;
6373}
6374
6375/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006376 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306377 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006378 * parameters during connect operation.
6379 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306380static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 struct net_device *ndev,
6382 struct cfg80211_connect_params *req
6383 )
6384{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306385 int status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306386 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006387 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006388 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006389
6390 ENTER();
6391
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006392 if (!pAdapter)
6393 {
6394 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6395 "%s: Adapter context is null", __func__);
6396 return VOS_STATUS_E_FAILURE;
6397 }
6398
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306399 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006400 "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006401
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306402 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006403 if (!pHddCtx)
6404 {
6405 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6406 "%s: HDD context is null", __func__);
6407 return VOS_STATUS_E_FAILURE;
6408 }
6409
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306410 status = wlan_hdd_validate_context(pHddCtx);
6411
6412 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006413 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306414 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6415 "%s: HDD context is not valid", __func__);
6416 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006417 }
6418
6419#ifdef WLAN_BTAMP_FEATURE
6420 //Infra connect not supported when AMP traffic is on.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306421 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07006422 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306423 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006424 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006425 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07006426 }
6427#endif
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306428
6429 //If Device Mode is Station Concurrent Sessions Exit BMps
6430 //P2P Mode will be taken care in Open/close adapter
6431 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
6432 (vos_concurrent_sessions_running()))
6433 {
6434 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
6435 }
6436
6437 /*Try disconnecting if already in connected state*/
6438 status = wlan_hdd_try_disconnect(pAdapter);
6439 if ( 0 > status)
6440 {
6441 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
6442 " connection"));
6443 return -EALREADY;
6444 }
6445
Jeff Johnson295189b2012-06-20 16:38:30 -07006446 /*initialise security parameters*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306447 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
Jeff Johnson295189b2012-06-20 16:38:30 -07006448
6449 if ( 0 > status)
6450 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306451 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
Jeff Johnson295189b2012-06-20 16:38:30 -07006452 __func__);
6453 return status;
6454 }
6455
Mohit Khanna765234a2012-09-11 15:08:35 -07006456 if ( req->channel )
6457 {
6458 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
6459 req->ssid_len, req->bssid,
6460 req->channel->hw_value);
6461 }
6462 else
6463 {
6464 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306465 req->ssid_len, req->bssid, 0);
Mohit Khanna765234a2012-09-11 15:08:35 -07006466 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006467
6468 if (0 > status)
6469 {
6470 //ReEnable BMPS if disabled
6471 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
6472 (NULL != pHddCtx))
6473 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306474 if (pHddCtx->hdd_wlan_suspended)
6475 {
6476 hdd_set_pwrparams(pHddCtx);
6477 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006478 //ReEnable Bmps and Imps back
6479 hdd_enable_bmps_imps(pHddCtx);
6480 }
6481
6482 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6483 return status;
6484 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306485 pHddCtx->isAmpAllowed = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006486 EXIT();
6487 return status;
6488}
6489
6490
6491/*
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306492 * FUNCTION: wlan_hdd_disconnect
6493 * This function is used to issue a disconnect request to SME
6494 */
6495int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
6496{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306497 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306498 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306499 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306500 long ret;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306501
6502 status = wlan_hdd_validate_context(pHddCtx);
6503
6504 if (0 != status)
6505 {
6506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6507 "%s: HDD context is not valid", __func__);
6508 return status;
6509 }
6510
6511 pHddCtx->isAmpAllowed = VOS_TRUE;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306512 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306513 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306514
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306515 /*issue disconnect*/
6516 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
6517 pAdapter->sessionId, reason);
6518
6519 if ( 0 != status )
6520 {
6521 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006522 "%s csrRoamDisconnect failure, returned %d",
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306523 __func__, (int)status );
6524 return -EINVAL;
6525 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306526 ret = wait_for_completion_interruptible_timeout(
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306527 &pAdapter->disconnect_comp_var,
6528 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306529 if (ret <= 0)
6530 {
6531 hddLog(VOS_TRACE_LEVEL_ERROR,
6532 FL("wait on disconnect_comp_var failed %ld"), ret);
6533 }
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306534 /*stop tx queues*/
6535 netif_tx_disable(pAdapter->dev);
6536 netif_carrier_off(pAdapter->dev);
6537 return status;
6538}
6539
6540
6541/*
Jeff Johnson295189b2012-06-20 16:38:30 -07006542 * FUNCTION: wlan_hdd_cfg80211_disconnect
6543 * This function is used to issue a disconnect request to SME
6544 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306545static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006546 struct net_device *dev,
6547 u16 reason
6548 )
6549{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306550 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6551 tCsrRoamProfile *pRoamProfile =
Jeff Johnson295189b2012-06-20 16:38:30 -07006552 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306553 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006554 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006555 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306556#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006557 tANI_U8 staIdx;
6558#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306559
Jeff Johnson295189b2012-06-20 16:38:30 -07006560 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306561
Arif Hussain6d2a3322013-11-17 19:50:10 -08006562 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006563 __func__,pAdapter->device_mode);
6564
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306565 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
6566 __func__, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -07006567
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306568 status = wlan_hdd_validate_context(pHddCtx);
6569
6570 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006571 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6573 "%s: HDD context is not valid", __func__);
6574 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006575 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306576
Jeff Johnson295189b2012-06-20 16:38:30 -07006577 if (NULL != pRoamProfile)
6578 {
6579 /*issue disconnect request to SME, if station is in connected state*/
Mahesh A Saptasagar280fd5a2013-12-05 15:38:31 +05306580 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
6581 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting))
Jeff Johnson295189b2012-06-20 16:38:30 -07006582 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306583 eCsrRoamDisconnectReason reasonCode =
Jeff Johnson295189b2012-06-20 16:38:30 -07006584 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306585 hdd_scaninfo_t *pScanInfo;
Jeff Johnson295189b2012-06-20 16:38:30 -07006586 switch(reason)
6587 {
6588 case WLAN_REASON_MIC_FAILURE:
6589 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
6590 break;
6591
6592 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
6593 case WLAN_REASON_DISASSOC_AP_BUSY:
6594 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
6595 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
6596 break;
6597
6598 case WLAN_REASON_PREV_AUTH_NOT_VALID:
6599 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
6600 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
6601 break;
6602
6603 case WLAN_REASON_DEAUTH_LEAVING:
6604 default:
6605 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
6606 break;
6607 }
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306608 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6609 pScanInfo = &pHddCtx->scan_info;
6610 if (pScanInfo->mScanPending)
6611 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306612 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306613 "Aborting Scan");
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306614 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6615 eCSR_SCAN_ABORT_DEFAULT);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +05306616 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006617
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006618#ifdef FEATURE_WLAN_TDLS
6619 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006620 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006621 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006622 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
6623 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006624 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006625 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006626 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006627 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006628 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006629 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006630 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006631 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006632 pAdapter->sessionId,
6633 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08006634 }
6635 }
6636#endif
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306637 status = wlan_hdd_disconnect(pAdapter, reasonCode);
6638 if ( 0 != status )
Jeff Johnson295189b2012-06-20 16:38:30 -07006639 {
6640 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006641 "%s wlan_hdd_disconnect failure, returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006642 __func__, (int)status );
6643 return -EINVAL;
6644 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006645 }
Mahesh A Saptasagar280fd5a2013-12-05 15:38:31 +05306646 else
6647 {
6648 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unexpected cfg disconnect API"
6649 "called while in %d state", __func__,
6650 pHddStaCtx->conn_info.connState);
6651 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006652 }
6653 else
6654 {
6655 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
6656 }
6657
6658 return status;
6659}
6660
Gopichand Nakkala78a6c812013-05-13 16:39:49 +05306661
Jeff Johnson295189b2012-06-20 16:38:30 -07006662/*
6663 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306664 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07006665 * settings in IBSS mode.
6666 */
6667static int wlan_hdd_cfg80211_set_privacy_ibss(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306668 hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07006669 struct cfg80211_ibss_params *params
6670 )
6671{
6672 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306673 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006674 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
6675 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306676
Jeff Johnson295189b2012-06-20 16:38:30 -07006677 ENTER();
6678
6679 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Ravi Joshib58ca0d2013-10-29 09:50:23 -07006680 vos_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -07006681
6682 if (params->ie_len && ( NULL != params->ie) )
6683 {
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006684 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6685 params->ie_len, WLAN_EID_RSN ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006686 {
6687 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
6688 encryptionType = eCSR_ENCRYPT_TYPE_AES;
6689 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006690 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
Jeff Johnson295189b2012-06-20 16:38:30 -07006691 {
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006692 tDot11fIEWPA dot11WPAIE;
6693 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006694 u8 *ie;
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006695
Wilson Yang00256342013-10-10 23:13:38 -07006696 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006697 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
6698 params->ie_len, DOT11F_EID_WPA);
6699 if ( NULL != ie )
6700 {
6701 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
6702 // Unpack the WPA IE
6703 //Skip past the EID byte and length byte - and four byte WiFi OUI
6704 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
6705 &ie[2+4],
6706 ie[1] - 4,
6707 &dot11WPAIE);
6708 /*Extract the multicast cipher, the encType for unicast
6709 cipher for wpa-none is none*/
6710 encryptionType =
6711 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
6712 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006713 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -07006714
Jeff Johnson295189b2012-06-20 16:38:30 -07006715 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
6716
6717 if (0 > status)
6718 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306719 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -07006720 __func__);
6721 return status;
6722 }
6723 }
6724
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306725 pWextState->roamProfile.AuthType.authType[0] =
6726 pHddStaCtx->conn_info.authType =
Jeff Johnson295189b2012-06-20 16:38:30 -07006727 eCSR_AUTH_TYPE_OPEN_SYSTEM;
6728
6729 if (params->privacy)
6730 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306731 /* Security enabled IBSS, At this time there is no information available
6732 * about the security paramters, so initialise the encryption type to
Jeff Johnson295189b2012-06-20 16:38:30 -07006733 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306734 * The correct security parameters will be updated later in
Jeff Johnson295189b2012-06-20 16:38:30 -07006735 * wlan_hdd_cfg80211_add_key */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306736 /* Hal expects encryption type to be set inorder
Jeff Johnson295189b2012-06-20 16:38:30 -07006737 *enable privacy bit in beacons */
6738
6739 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6740 }
Shailender Karmuchi642e9812013-05-30 14:34:49 -07006741 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6742 "encryptionType=%d", encryptionType);
Jeff Johnson295189b2012-06-20 16:38:30 -07006743 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
6744 pWextState->roamProfile.EncryptionType.numEntries = 1;
6745 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
Jeff Johnson295189b2012-06-20 16:38:30 -07006746 return status;
6747}
6748
6749/*
6750 * FUNCTION: wlan_hdd_cfg80211_join_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306751 * This function is used to create/join an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006752 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306753static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006754 struct net_device *dev,
6755 struct cfg80211_ibss_params *params
6756 )
6757{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306758 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006759 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6760 tCsrRoamProfile *pRoamProfile;
6761 int status;
krunal sonie9002db2013-11-25 14:24:17 -08006762 bool alloc_bssid = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006763 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306764 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006765
6766 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306767
6768 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006769 "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006770
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306771 status = wlan_hdd_validate_context(pHddCtx);
6772
6773 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006774 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6776 "%s: HDD context is not valid", __func__);
6777 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006778 }
6779
6780 if (NULL == pWextState)
6781 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006782 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
Jeff Johnson295189b2012-06-20 16:38:30 -07006783 __func__);
6784 return -EIO;
6785 }
6786
Vinay Krishna Eranna21042322014-01-08 19:21:39 +05306787 /*Try disconnecting if already in connected state*/
6788 status = wlan_hdd_try_disconnect(pAdapter);
6789 if ( 0 > status)
6790 {
6791 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
6792 " IBSS connection"));
6793 return -EALREADY;
6794 }
6795
Jeff Johnson295189b2012-06-20 16:38:30 -07006796 pRoamProfile = &pWextState->roamProfile;
6797
6798 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
6799 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306800 hddLog (VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006801 "%s Interface type is not set to IBSS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006802 return -EINVAL;
6803 }
6804
Praveen Kumar Sirisillad123d142013-09-24 16:50:13 -07006805 /* BSSID is provided by upper layers hence no need to AUTO generate */
6806 if (NULL != params->bssid) {
6807 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
6808 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) {
6809 hddLog (VOS_TRACE_LEVEL_ERROR,
6810 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
6811 return -EIO;
6812 }
6813 }
krunal sonie9002db2013-11-25 14:24:17 -08006814 else if(pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0)
6815 {
6816 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
6817 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
6818 {
6819 hddLog (VOS_TRACE_LEVEL_ERROR,
6820 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
6821 return -EIO;
6822 }
6823 params->bssid = vos_mem_malloc(sizeof(VOS_MAC_ADDR_SIZE));
6824 if (!params->bssid)
6825 {
6826 hddLog (VOS_TRACE_LEVEL_ERROR,
6827 "%s:Failed memory allocation", __func__);
6828 return -EIO;
6829 }
6830 vos_mem_copy((v_U8_t *)params->bssid,
6831 (v_U8_t *)&pHddCtx->cfg_ini->IbssBssid.bytes[0],
6832 VOS_MAC_ADDR_SIZE);
6833 alloc_bssid = VOS_TRUE;
6834 }
Praveen Kumar Sirisillad123d142013-09-24 16:50:13 -07006835
Jeff Johnson295189b2012-06-20 16:38:30 -07006836 /* Set Channel */
Yue Maf49ba872013-08-19 12:04:25 -07006837 if (NULL !=
6838#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6839 params->chandef.chan)
6840#else
6841 params->channel)
6842#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006843 {
6844 u8 channelNum;
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006845 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6846 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6847 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6848 int indx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006849
6850 /* Get channel number */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306851 channelNum =
Yue Maf49ba872013-08-19 12:04:25 -07006852 ieee80211_frequency_to_channel(
6853#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
6854 params->chandef.chan->center_freq);
6855#else
6856 params->channel->center_freq);
6857#endif
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006858
6859 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6860 validChan, &numChans))
Jeff Johnson295189b2012-06-20 16:38:30 -07006861 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006862 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
6863 __func__);
6864 return -EOPNOTSUPP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006866
6867 for (indx = 0; indx < numChans; indx++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006868 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006869 if (channelNum == validChan[indx])
6870 {
6871 break;
6872 }
6873 }
6874 if (indx >= numChans)
6875 {
6876 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07006877 __func__, channelNum);
6878 return -EINVAL;
6879 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006880 /* Set the Operational Channel */
6881 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
6882 channelNum);
6883 pRoamProfile->ChannelInfo.numOfChannels = 1;
6884 pHddStaCtx->conn_info.operationChannel = channelNum;
6885 pRoamProfile->ChannelInfo.ChannelList =
6886 &pHddStaCtx->conn_info.operationChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -07006887 }
6888
6889 /* Initialize security parameters */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306890 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
Jeff Johnson295189b2012-06-20 16:38:30 -07006891 if (status < 0)
6892 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306893 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
Jeff Johnson295189b2012-06-20 16:38:30 -07006894 __func__);
6895 return status;
6896 }
6897
6898 /* Issue connect start */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306899 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07006900 params->ssid_len, params->bssid,
6901 pHddStaCtx->conn_info.operationChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07006902
6903 if (0 > status)
6904 {
6905 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
6906 return status;
6907 }
6908
krunal sonie9002db2013-11-25 14:24:17 -08006909 if (NULL != params->bssid &&
6910 pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0 &&
6911 alloc_bssid == VOS_TRUE)
6912 {
6913 vos_mem_free(params->bssid);
6914 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006915 return 0;
6916}
6917
6918/*
6919 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306920 * This function is used to leave an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -07006921 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306922static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006923 struct net_device *dev
6924 )
6925{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306926 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07006927 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6928 tCsrRoamProfile *pRoamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306929 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6930 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006931
6932 ENTER();
6933
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306934 status = wlan_hdd_validate_context(pHddCtx);
6935
6936 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006937 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6939 "%s: HDD context is not valid", __func__);
6940 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006941 }
6942
Arif Hussain6d2a3322013-11-17 19:50:10 -08006943 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",__func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006944 if (NULL == pWextState)
6945 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08006946 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
Jeff Johnson295189b2012-06-20 16:38:30 -07006947 __func__);
6948 return -EIO;
6949 }
6950
6951 pRoamProfile = &pWextState->roamProfile;
6952
6953 /* Issue disconnect only if interface type is set to IBSS */
6954 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
6955 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306956 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
Jeff Johnson295189b2012-06-20 16:38:30 -07006957 __func__);
6958 return -EINVAL;
6959 }
6960
6961 /* Issue Disconnect request */
6962 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6963 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6964 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6965
6966 return 0;
6967}
6968
6969/*
6970 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
6971 * This function is used to set the phy parameters
6972 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
6973 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306974static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006975 u32 changed)
6976{
6977 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6978 tHalHandle hHal = pHddCtx->hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306979 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006980
6981 ENTER();
6982
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306983 status = wlan_hdd_validate_context(pHddCtx);
6984
6985 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006986 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6988 "%s: HDD context is not valid", __func__);
6989 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006990 }
6991
Jeff Johnson295189b2012-06-20 16:38:30 -07006992 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
6993 {
6994 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
6995 WNI_CFG_RTS_THRESHOLD_STAMAX :
6996 wiphy->rts_threshold;
6997
6998 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306999 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
Jeff Johnson295189b2012-06-20 16:38:30 -07007000 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307001 hddLog(VOS_TRACE_LEVEL_ERROR,
7002 "%s: Invalid RTS Threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007003 __func__, rts_threshold);
7004 return -EINVAL;
7005 }
7006
7007 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
7008 rts_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307009 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007010 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307011 hddLog(VOS_TRACE_LEVEL_ERROR,
7012 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007013 __func__, rts_threshold);
7014 return -EIO;
7015 }
7016
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307017 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07007018 rts_threshold);
7019 }
7020
7021 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
7022 {
7023 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
7024 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
7025 wiphy->frag_threshold;
7026
7027 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307028 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
Jeff Johnson295189b2012-06-20 16:38:30 -07007029 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307030 hddLog(VOS_TRACE_LEVEL_ERROR,
7031 "%s: Invalid frag_threshold value %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07007032 frag_threshold);
7033 return -EINVAL;
7034 }
7035
7036 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
7037 frag_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307038 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007039 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307040 hddLog(VOS_TRACE_LEVEL_ERROR,
7041 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007042 __func__, frag_threshold);
7043 return -EIO;
7044 }
7045
7046 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
7047 frag_threshold);
7048 }
7049
7050 if ((changed & WIPHY_PARAM_RETRY_SHORT)
7051 || (changed & WIPHY_PARAM_RETRY_LONG))
7052 {
7053 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
7054 wiphy->retry_short :
7055 wiphy->retry_long;
7056
7057 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
7058 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
7059 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307060 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007061 __func__, retry_value);
7062 return -EINVAL;
7063 }
7064
7065 if (changed & WIPHY_PARAM_RETRY_SHORT)
7066 {
7067 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
7068 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307069 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007070 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307071 hddLog(VOS_TRACE_LEVEL_ERROR,
7072 "%s: ccmCfgSetInt failed for long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007073 __func__, retry_value);
7074 return -EIO;
7075 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307076 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007077 __func__, retry_value);
7078 }
7079 else if (changed & WIPHY_PARAM_RETRY_SHORT)
7080 {
7081 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
7082 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307083 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007084 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307085 hddLog(VOS_TRACE_LEVEL_ERROR,
7086 "%s: ccmCfgSetInt failed for short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007087 __func__, retry_value);
7088 return -EIO;
7089 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307090 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -07007091 __func__, retry_value);
7092 }
7093 }
7094
7095 return 0;
7096}
7097
7098/*
7099 * FUNCTION: wlan_hdd_cfg80211_set_txpower
7100 * This function is used to set the txpower
7101 */
7102static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Yue Maf49ba872013-08-19 12:04:25 -07007103#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
7104 struct wireless_dev *wdev,
7105#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007106#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307107 enum tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07007108#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307109 enum nl80211_tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -07007110#endif
7111 int dbm)
7112{
7113 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307114 tHalHandle hHal = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007115 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
7116 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307117 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007118
7119 ENTER();
7120
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307121 status = wlan_hdd_validate_context(pHddCtx);
7122
7123 if (0 != status)
7124 {
7125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7126 "%s: HDD context is not valid", __func__);
7127 return status;
7128 }
7129
7130 hHal = pHddCtx->hHal;
7131
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307132 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
7133 dbm, ccmCfgSetCallback,
7134 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -07007135 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307136 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007137 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
7138 return -EIO;
7139 }
7140
7141 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
7142 dbm);
7143
7144 switch(type)
7145 {
7146 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
7147 /* Fall through */
7148 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
7149 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
7150 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307151 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
7152 __func__);
7153 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007154 }
7155 break;
7156 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307157 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -07007158 __func__);
7159 return -EOPNOTSUPP;
7160 break;
7161 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307162 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
7163 __func__, type);
Jeff Johnson295189b2012-06-20 16:38:30 -07007164 return -EIO;
7165 }
7166
7167 return 0;
7168}
7169
7170/*
7171 * FUNCTION: wlan_hdd_cfg80211_get_txpower
7172 * This function is used to read the txpower
7173 */
Yue Maf49ba872013-08-19 12:04:25 -07007174static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
7175#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
7176 struct wireless_dev *wdev,
7177#endif
7178 int *dbm)
Jeff Johnson295189b2012-06-20 16:38:30 -07007179{
7180
7181 hdd_adapter_t *pAdapter;
7182 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307183 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007184
Jeff Johnsone7245742012-09-05 17:12:55 -07007185 ENTER();
7186
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307187 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007188
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307189 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007190 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7192 "%s: HDD context is not valid", __func__);
7193 *dbm = 0;
7194 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007195 }
7196
Jeff Johnson295189b2012-06-20 16:38:30 -07007197 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
7198 if (NULL == pAdapter)
7199 {
7200 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
7201 return -ENOENT;
7202 }
7203
7204 wlan_hdd_get_classAstats(pAdapter);
7205 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
7206
Jeff Johnsone7245742012-09-05 17:12:55 -07007207 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007208 return 0;
7209}
7210
7211static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
7212 u8* mac, struct station_info *sinfo)
7213{
7214 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
7215 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7216 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
7217 tANI_U8 rate_flags;
7218
7219 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
7220 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07007221
7222 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
7223 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
7224 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
7225 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
7226 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
7227 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
7228 tANI_U16 maxRate = 0;
7229 tANI_U16 myRate;
7230 tANI_U16 currentRate = 0;
7231 tANI_U8 maxSpeedMCS = 0;
7232 tANI_U8 maxMCSIdx = 0;
7233 tANI_U8 rateFlag = 1;
7234 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07007235 tANI_U16 temp;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307236 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007237
Leo Chang6f8870f2013-03-26 18:11:36 -07007238#ifdef WLAN_FEATURE_11AC
7239 tANI_U32 vht_mcs_map;
7240 eDataRate11ACMaxMcs vhtMaxMcs;
7241#endif /* WLAN_FEATURE_11AC */
7242
Jeff Johnsone7245742012-09-05 17:12:55 -07007243 ENTER();
7244
Jeff Johnson295189b2012-06-20 16:38:30 -07007245 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
7246 (0 == ssidlen))
7247 {
7248 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
7249 " Invalid ssidlen, %d", __func__, ssidlen);
7250 /*To keep GUI happy*/
7251 return 0;
7252 }
7253
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307254 status = wlan_hdd_validate_context(pHddCtx);
7255
7256 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007257 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7259 "%s: HDD context is not valid", __func__);
7260 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007261 }
7262
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07007263 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007264 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
7265
Kiet Lam3b17fc82013-09-27 05:24:08 +05307266 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
7267 sinfo->filled |= STATION_INFO_SIGNAL;
7268
Jeff Johnson295189b2012-06-20 16:38:30 -07007269 //convert to the UI units of 100kbps
7270 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
7271
7272#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -07007273 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 -07007274 sinfo->signal,
7275 pCfg->reportMaxLinkSpeed,
7276 myRate,
7277 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007278 (int) pCfg->linkSpeedRssiMid,
7279 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -07007280 (int) rate_flags,
7281 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07007282#endif //LINKSPEED_DEBUG_ENABLED
7283
7284 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
7285 {
7286 // we do not want to necessarily report the current speed
7287 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
7288 {
7289 // report the max possible speed
7290 rssidx = 0;
7291 }
7292 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
7293 {
7294 // report the max possible speed with RSSI scaling
7295 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
7296 {
7297 // report the max possible speed
7298 rssidx = 0;
7299 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007300 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07007301 {
7302 // report middle speed
7303 rssidx = 1;
7304 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007305 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
7306 {
7307 // report middle speed
7308 rssidx = 2;
7309 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007310 else
7311 {
7312 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007313 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07007314 }
7315 }
7316 else
7317 {
7318 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
7319 hddLog(VOS_TRACE_LEVEL_ERROR,
7320 "%s: Invalid value for reportMaxLinkSpeed: %u",
7321 __func__, pCfg->reportMaxLinkSpeed);
7322 rssidx = 0;
7323 }
7324
7325 maxRate = 0;
7326
7327 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307328 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
7329 OperationalRates, &ORLeng))
7330 {
7331 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7332 /*To keep GUI happy*/
7333 return 0;
7334 }
7335
Jeff Johnson295189b2012-06-20 16:38:30 -07007336 for (i = 0; i < ORLeng; i++)
7337 {
Jeff Johnsone7245742012-09-05 17:12:55 -07007338 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07007339 {
7340 /* Validate Rate Set */
7341 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
7342 {
7343 currentRate = supported_data_rate[j].supported_rate[rssidx];
7344 break;
7345 }
7346 }
7347 /* Update MAX rate */
7348 maxRate = (currentRate > maxRate)?currentRate:maxRate;
7349 }
7350
7351 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307352 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
7353 ExtendedRates, &ERLeng))
7354 {
7355 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7356 /*To keep GUI happy*/
7357 return 0;
7358 }
7359
Jeff Johnson295189b2012-06-20 16:38:30 -07007360 for (i = 0; i < ERLeng; i++)
7361 {
Jeff Johnsone7245742012-09-05 17:12:55 -07007362 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07007363 {
7364 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
7365 {
7366 currentRate = supported_data_rate[j].supported_rate[rssidx];
7367 break;
7368 }
7369 }
7370 /* Update MAX rate */
7371 maxRate = (currentRate > maxRate)?currentRate:maxRate;
7372 }
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307373 /* Get MCS Rate Set --
Kaushik, Sushantdc304d82014-01-22 10:58:37 +05307374 Only if we are always reporting max speed (or)
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307375 if we have good rssi */
Kaushik, Sushantdc304d82014-01-22 10:58:37 +05307376 if ((0 == rssidx) ||
Kiet Lamb69f8dc2013-11-15 15:34:27 +05307377 (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed))
Jeff Johnson295189b2012-06-20 16:38:30 -07007378 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05307379 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
7380 MCSRates, &MCSLeng))
7381 {
7382 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
7383 /*To keep GUI happy*/
7384 return 0;
7385 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007386 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -07007387#ifdef WLAN_FEATURE_11AC
7388 /* VHT80 rate has seperate rate table */
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307389 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
Jeff Johnson295189b2012-06-20 16:38:30 -07007390 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007391 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307392 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
Leo Chang6f8870f2013-03-26 18:11:36 -07007393 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -07007394 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007395 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -07007396 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007397 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -07007398 {
Leo Chang6f8870f2013-03-26 18:11:36 -07007399 maxMCSIdx = 7;
7400 }
7401 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
7402 {
7403 maxMCSIdx = 8;
7404 }
7405 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
7406 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307407 //VHT20 is supporting 0~8
7408 if (rate_flags & eHAL_TX_RATE_VHT20)
7409 maxMCSIdx = 8;
7410 else
7411 maxMCSIdx = 9;
Leo Chang6f8870f2013-03-26 18:11:36 -07007412 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307413
7414 if (rate_flags & eHAL_TX_RATE_VHT80)
7415 {
7416 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
7417 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
7418 }
7419 else if (rate_flags & eHAL_TX_RATE_VHT40)
7420 {
7421 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
7422 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
7423 }
7424 else if (rate_flags & eHAL_TX_RATE_VHT20)
7425 {
7426 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
7427 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
7428 }
7429
Leo Chang6f8870f2013-03-26 18:11:36 -07007430 maxSpeedMCS = 1;
7431 if (currentRate > maxRate)
7432 {
7433 maxRate = currentRate;
7434 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307435
Leo Chang6f8870f2013-03-26 18:11:36 -07007436 }
7437 else
7438#endif /* WLAN_FEATURE_11AC */
7439 {
7440 if (rate_flags & eHAL_TX_RATE_HT40)
7441 {
7442 rateFlag |= 1;
7443 }
7444 if (rate_flags & eHAL_TX_RATE_SGI)
7445 {
7446 rateFlag |= 2;
7447 }
7448
7449 for (i = 0; i < MCSLeng; i++)
7450 {
7451 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
7452 for (j = 0; j < temp; j++)
7453 {
7454 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
7455 {
7456 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
7457 break;
7458 }
7459 }
7460 if ((j < temp) && (currentRate > maxRate))
7461 {
7462 maxRate = currentRate;
7463 maxSpeedMCS = 1;
7464 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
7465 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007466 }
7467 }
7468 }
7469
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307470 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
7471 {
7472 maxRate = myRate;
7473 maxSpeedMCS = 1;
7474 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
7475 }
7476
Jeff Johnson295189b2012-06-20 16:38:30 -07007477 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07007478 if (((maxRate < myRate) && (0 == rssidx)) ||
7479 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07007480 {
7481 maxRate = myRate;
7482 if (rate_flags & eHAL_TX_RATE_LEGACY)
7483 {
7484 maxSpeedMCS = 0;
7485 }
7486 else
7487 {
7488 maxSpeedMCS = 1;
7489 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
7490 }
7491 }
7492
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307493 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson295189b2012-06-20 16:38:30 -07007494 {
7495 sinfo->txrate.legacy = maxRate;
7496#ifdef LINKSPEED_DEBUG_ENABLED
7497 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
7498#endif //LINKSPEED_DEBUG_ENABLED
7499 }
7500 else
7501 {
7502 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -07007503#ifdef WLAN_FEATURE_11AC
7504 sinfo->txrate.nss = 1;
7505 if (rate_flags & eHAL_TX_RATE_VHT80)
7506 {
7507 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307508 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Leo Chang6f8870f2013-03-26 18:11:36 -07007509 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307510 else if (rate_flags & eHAL_TX_RATE_VHT40)
Leo Chang6f8870f2013-03-26 18:11:36 -07007511 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307512 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7513 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7514 }
7515 else if (rate_flags & eHAL_TX_RATE_VHT20)
7516 {
7517 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7518 }
7519#endif /* WLAN_FEATURE_11AC */
7520 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
7521 {
7522 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
7523 if (rate_flags & eHAL_TX_RATE_HT40)
7524 {
7525 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7526 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007527 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007528 if (rate_flags & eHAL_TX_RATE_SGI)
7529 {
7530 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
7531 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +05307532
Jeff Johnson295189b2012-06-20 16:38:30 -07007533#ifdef LINKSPEED_DEBUG_ENABLED
7534 pr_info("Reporting MCS rate %d flags %x\n",
7535 sinfo->txrate.mcs,
7536 sinfo->txrate.flags );
7537#endif //LINKSPEED_DEBUG_ENABLED
7538 }
7539 }
7540 else
7541 {
7542 // report current rate instead of max rate
7543
7544 if (rate_flags & eHAL_TX_RATE_LEGACY)
7545 {
7546 //provide to the UI in units of 100kbps
7547 sinfo->txrate.legacy = myRate;
7548#ifdef LINKSPEED_DEBUG_ENABLED
7549 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
7550#endif //LINKSPEED_DEBUG_ENABLED
7551 }
7552 else
7553 {
7554 //must be MCS
7555 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -07007556#ifdef WLAN_FEATURE_11AC
7557 sinfo->txrate.nss = 1;
7558 if (rate_flags & eHAL_TX_RATE_VHT80)
7559 {
7560 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
7561 }
7562 else
7563#endif /* WLAN_FEATURE_11AC */
7564 {
7565 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
7566 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007567 if (rate_flags & eHAL_TX_RATE_SGI)
7568 {
7569 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
7570 }
7571 if (rate_flags & eHAL_TX_RATE_HT40)
7572 {
7573 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
7574 }
Leo Chang6f8870f2013-03-26 18:11:36 -07007575#ifdef WLAN_FEATURE_11AC
7576 else if (rate_flags & eHAL_TX_RATE_VHT80)
7577 {
7578 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
7579 }
7580#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007581#ifdef LINKSPEED_DEBUG_ENABLED
7582 pr_info("Reporting actual MCS rate %d flags %x\n",
7583 sinfo->txrate.mcs,
7584 sinfo->txrate.flags );
7585#endif //LINKSPEED_DEBUG_ENABLED
7586 }
7587 }
7588 sinfo->filled |= STATION_INFO_TX_BITRATE;
7589
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07007590 sinfo->tx_packets =
7591 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
7592 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
7593 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
7594 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
7595
7596 sinfo->tx_retries =
7597 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
7598 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
7599 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
7600 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
7601
7602 sinfo->tx_failed =
7603 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
7604 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
7605 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
7606 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
7607
7608 sinfo->filled |=
7609 STATION_INFO_TX_PACKETS |
7610 STATION_INFO_TX_RETRIES |
7611 STATION_INFO_TX_FAILED;
7612
7613 EXIT();
7614 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007615}
7616
7617static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Sameer Thalappilc9f26e92013-06-07 10:11:06 -07007618 struct net_device *dev, bool mode, int timeout)
Jeff Johnson295189b2012-06-20 16:38:30 -07007619{
7620 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307621 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007622 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307623 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007624
Jeff Johnsone7245742012-09-05 17:12:55 -07007625 ENTER();
7626
Jeff Johnson295189b2012-06-20 16:38:30 -07007627 if (NULL == pAdapter)
7628 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007629 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007630 return -ENODEV;
7631 }
7632
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307633 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307634 status = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307635
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307636 if (0 != status)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307637 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7639 "%s: HDD context is not valid", __func__);
7640 return status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307641 }
7642
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307643 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
7644 (TRUE == pHddCtx->hdd_wlan_suspended) &&
7645 (pHddCtx->cfg_ini->fhostArpOffload) &&
7646 (eConnectionState_Associated ==
7647 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
7648 {
Amar Singhald53568e2013-09-26 11:03:45 -07007649
7650 hddLog(VOS_TRACE_LEVEL_INFO,
7651 "offload: in cfg80211_set_power_mgmt, calling arp offload");
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05307652 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307653 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7654 {
7655 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08007656 "%s:Failed to enable ARPOFFLOAD Feature %d",
Gopichand Nakkala20c4c042013-04-19 22:08:55 +05307657 __func__, vos_status);
7658 }
7659 }
7660
Jeff Johnson295189b2012-06-20 16:38:30 -07007661 /**The get power cmd from the supplicant gets updated by the nl only
7662 *on successful execution of the function call
7663 *we are oppositely mapped w.r.t mode in the driver
7664 **/
7665 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
7666
Jeff Johnsone7245742012-09-05 17:12:55 -07007667 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007668 if (VOS_STATUS_E_FAILURE == vos_status)
7669 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7671 "%s: failed to enter bmps mode", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007672 return -EINVAL;
7673 }
7674 return 0;
7675}
7676
7677
7678#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7679static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
7680 struct net_device *netdev,
7681 u8 key_index)
7682{
Jeff Johnsone7245742012-09-05 17:12:55 -07007683 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007684 return 0;
7685}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307686#endif //LINUX_VERSION_CODE
Jeff Johnson295189b2012-06-20 16:38:30 -07007687
7688#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
7689static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7690 struct net_device *dev,
7691 struct ieee80211_txq_params *params)
7692{
Jeff Johnsone7245742012-09-05 17:12:55 -07007693 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007694 return 0;
7695}
7696#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7697static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
7698 struct ieee80211_txq_params *params)
7699{
Jeff Johnsone7245742012-09-05 17:12:55 -07007700 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007701 return 0;
7702}
7703#endif //LINUX_VERSION_CODE
7704
7705static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
7706 struct net_device *dev, u8 *mac)
7707{
7708 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307709 hdd_context_t *pHddCtx;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007710 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307711 int status;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007712 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007713
Jeff Johnsone7245742012-09-05 17:12:55 -07007714 ENTER();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307715 if ( NULL == pAdapter )
Jeff Johnson295189b2012-06-20 16:38:30 -07007716 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307717 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007718 return -EINVAL;
7719 }
7720
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307721 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7722 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007723
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307724 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007725 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307726 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7727 "%s: HDD context is not valid", __func__);
7728 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007729 }
7730
Jeff Johnson295189b2012-06-20 16:38:30 -07007731 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007732 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07007733 )
7734 {
7735 if( NULL == mac )
7736 {
7737 v_U16_t i;
7738 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
7739 {
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007740 if ((pAdapter->aStaInfo[i].isUsed) &&
7741 (!pAdapter->aStaInfo[i].isDeauthInProgress))
Jeff Johnson295189b2012-06-20 16:38:30 -07007742 {
7743 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
7744 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007745 "%s: Delete STA with MAC::"
7746 MAC_ADDRESS_STR,
7747 __func__, MAC_ADDR_ARRAY(macAddr));
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007748 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
7749 if (VOS_IS_STATUS_SUCCESS(vos_status))
7750 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007751 }
7752 }
7753 }
7754 else
7755 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007756
7757 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
7758 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7759 {
7760 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007761 "%s: Skip this DEL STA as this is not used::"
7762 MAC_ADDRESS_STR,
7763 __func__, MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007764 return -ENOENT;
7765 }
7766
7767 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
7768 {
7769 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -08007770 "%s: Skip this DEL STA as deauth is in progress::"
7771 MAC_ADDRESS_STR,
7772 __func__, MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007773 return -ENOENT;
7774 }
7775
7776 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
7777
Jeff Johnson295189b2012-06-20 16:38:30 -07007778 hddLog(VOS_TRACE_LEVEL_INFO,
7779 "%s: Delete STA with MAC::"
Arif Hussain24bafea2013-11-15 15:10:03 -08007780 MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007781 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08007782 MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007783
7784 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
7785 if (!VOS_IS_STATUS_SUCCESS(vos_status))
7786 {
7787 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
7788 hddLog(VOS_TRACE_LEVEL_INFO,
7789 "%s: STA removal failed for ::"
Arif Hussain24bafea2013-11-15 15:10:03 -08007790 MAC_ADDRESS_STR,
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007791 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08007792 MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007793 return -ENOENT;
7794 }
7795
Jeff Johnson295189b2012-06-20 16:38:30 -07007796 }
7797 }
7798
7799 EXIT();
7800
7801 return 0;
7802}
7803
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007804static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
7805 struct net_device *dev, u8 *mac, struct station_parameters *params)
7806{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007807 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007808#ifdef FEATURE_WLAN_TDLS
7809 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08007810 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007811 mask = params->sta_flags_mask;
7812
7813 set = params->sta_flags_set;
7814
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007815#ifdef WLAN_FEATURE_TDLS_DEBUG
7816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7817 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
7818 __func__, mask, set, MAC_ADDR_ARRAY(mac));
7819#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007820
7821 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7822 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007823 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007824 }
7825 }
7826#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007827 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07007828}
7829
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007830
7831#ifdef FEATURE_WLAN_LFR
Wilson Yang6507c4e2013-10-01 20:11:19 -07007832#define MAX_PMKSAIDS_IN_CACHE 8
7833
7834static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD local cache
7835static tANI_U32 PMKIDCacheIndex; // HDD local Cache index
7836
7837
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007838static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07007839 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007840{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307841 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007842 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7843 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307844 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307845 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007846 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307847 hdd_context_t *pHddCtx;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307848
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007849 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: set PMKSA for " MAC_ADDRESS_STR,
7850 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Jeff Johnsone7245742012-09-05 17:12:55 -07007851
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307852 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307853 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007854 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307855 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007856 return -EINVAL;
7857 }
7858
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307859 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7860 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007861
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307862 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007863 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7865 "%s: HDD context is not valid", __func__);
7866 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007867 }
7868
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307869 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007870 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7871
Wilson Yang6507c4e2013-10-01 20:11:19 -07007872 for (j = 0; j < PMKIDCacheIndex; j++)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007873 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307874 if(vos_mem_compare(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007875 pmksa->bssid, WNI_CFG_BSSID_LEN))
7876 {
7877 /* BSSID matched previous entry. Overwrite it. */
7878 BSSIDMatched = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307879 vos_mem_copy(PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007880 pmksa->bssid, WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307881 vos_mem_copy(PMKIDCache[j].PMKID,
7882 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007883 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307884 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007885 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007886 dump_bssid(pmksa->bssid);
7887 dump_pmkid(halHandle, pmksa->pmkid);
7888 break;
7889 }
7890 }
7891
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007892 /* Check we compared all entries,if then take the first slot now */
Wilson Yang6507c4e2013-10-01 20:11:19 -07007893 if(j == MAX_PMKSAIDS_IN_CACHE) PMKIDCacheIndex=0;
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07007894
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007895 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307896 {
7897 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
Wilson Yang6507c4e2013-10-01 20:11:19 -07007898 vos_mem_copy(PMKIDCache[PMKIDCacheIndex].BSSID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307899 pmksa->bssid, ETHER_ADDR_LEN);
Wilson Yang6507c4e2013-10-01 20:11:19 -07007900 vos_mem_copy(PMKIDCache[PMKIDCacheIndex].PMKID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307901 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007902 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307903 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Wilson Yang6507c4e2013-10-01 20:11:19 -07007904 __func__, PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007905 dump_bssid(pmksa->bssid);
7906 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307907 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007908 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Wilson Yang6507c4e2013-10-01 20:11:19 -07007909 if (PMKIDCacheIndex <= (MAX_PMKSAIDS_IN_CACHE-1)) PMKIDCacheIndex++; else PMKIDCacheIndex = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007910 }
7911
7912
7913 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307914 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007915 // __func__, i );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307916 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Wilson Yang6507c4e2013-10-01 20:11:19 -07007917 __func__, PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007918 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307919 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
7920 PMKIDCache,
Wilson Yang6507c4e2013-10-01 20:11:19 -07007921 PMKIDCacheIndex);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007922 return 0;
7923}
7924
7925
Wilson Yang6507c4e2013-10-01 20:11:19 -07007926
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007927static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Wilson Yang6507c4e2013-10-01 20:11:19 -07007928 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007929{
Wilson Yang6507c4e2013-10-01 20:11:19 -07007930 tANI_U32 j=0;
7931 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7932 tHalHandle halHandle;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007933 tANI_U8 BSSIDMatched = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007934 hdd_context_t *pHddCtx;
Wilson Yangef657d32014-01-15 19:19:23 -08007935 int status = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07007936
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007937 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: deleting PMKSA for " MAC_ADDRESS_STR,
7938 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Wilson Yang6507c4e2013-10-01 20:11:19 -07007939
7940 /* Validate pAdapter */
7941 if (NULL == pAdapter)
7942 {
7943 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
7944 return -EINVAL;
7945 }
7946
7947 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7948 status = wlan_hdd_validate_context(pHddCtx);
7949
7950 if (0 != status)
7951 {
7952 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7953 "%s: HDD context is not valid", __func__);
7954 return status;
7955 }
7956
7957 /*Retrieve halHandle*/
7958 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
7959
7960 /*in case index is 0,no entry to delete*/
7961 if (0 == PMKIDCacheIndex)
7962 {
7963 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid entry to delete" ,
7964 __func__);
7965 return -EINVAL;
7966 }
7967
7968 /*find the matching PMKSA entry from j=0 to (index-1),
7969 * and delete the matched one
7970 */
7971 for (j = 0; j<PMKIDCacheIndex; j++)
7972 {
7973 if (vos_mem_compare(PMKIDCache[j].BSSID,
7974 pmksa->bssid,
7975 WNI_CFG_BSSID_LEN))
7976 {
7977 /* BSSID matched entry */
7978 BSSIDMatched = 1;
7979
7980 if (j<PMKIDCacheIndex-1)
7981 {
7982 /*replace the matching entry with the last entry in HDD local cache*/
7983 vos_mem_copy(PMKIDCache[j].BSSID,
7984 PMKIDCache[PMKIDCacheIndex-1].BSSID,
7985 WNI_CFG_BSSID_LEN);
7986 vos_mem_copy(PMKIDCache[j].PMKID,
7987 PMKIDCache[PMKIDCacheIndex-1].PMKID,
7988 CSR_RSN_PMKID_SIZE);
7989 }
7990
7991 /*clear the last entry in HDD cache ---[index-1]*/
Wilson Yang6507c4e2013-10-01 20:11:19 -07007992 vos_mem_zero(PMKIDCache[PMKIDCacheIndex-1].BSSID, WNI_CFG_BSSID_LEN);
7993 vos_mem_zero(PMKIDCache[PMKIDCacheIndex-1].PMKID, CSR_RSN_PMKID_SIZE);
7994
7995 /*reduce the PMKID array index*/
7996 PMKIDCacheIndex--;
7997
7998 /*delete the last PMKID cache in CSR*/
Wilson Yangef657d32014-01-15 19:19:23 -08007999 if (eHAL_STATUS_SUCCESS !=
8000 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pmksa->bssid))
Wilson Yang6507c4e2013-10-01 20:11:19 -07008001 {
8002 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cannot delete PMKSA %d CONTENT.",
8003 __func__,PMKIDCacheIndex);
Wilson Yangef657d32014-01-15 19:19:23 -08008004 status = -EINVAL;
Wilson Yang6507c4e2013-10-01 20:11:19 -07008005 }
8006
8007 dump_bssid(pmksa->bssid);
8008 dump_pmkid(halHandle,pmksa->pmkid);
8009
8010 break;
8011 }
8012 }
8013
8014 /* we compare all entries,but cannot find matching entry */
8015 if (j == MAX_PMKSAIDS_IN_CACHE && !BSSIDMatched)
8016 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008017 hddLog(VOS_TRACE_LEVEL_FATAL,
8018 "%s: No such PMKSA entry existed " MAC_ADDRESS_STR,
8019 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Wilson Yang6507c4e2013-10-01 20:11:19 -07008020 dump_bssid(pmksa->bssid);
8021 dump_pmkid(halHandle, pmksa->pmkid);
8022 return -EINVAL;
8023 }
Wilson Yangef657d32014-01-15 19:19:23 -08008024 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008025}
8026
Wilson Yang6507c4e2013-10-01 20:11:19 -07008027
8028
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008029static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
8030{
Wilson Yang6507c4e2013-10-01 20:11:19 -07008031 tANI_U32 j=0;
8032 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8033 tHalHandle halHandle;
8034 hdd_context_t *pHddCtx;
8035 tANI_U8 *pBSSId;
Wilson Yangef657d32014-01-15 19:19:23 -08008036 int status = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -07008037
8038 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: flushing PMKSA ",__func__);
8039
8040 /* Validate pAdapter */
8041 if (NULL == pAdapter)
8042 {
8043 hddLog(VOS_TRACE_LEVEL_ERROR,
8044 "%s: Invalid Adapter" ,__func__);
8045 return -EINVAL;
8046 }
8047
8048 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8049 status = wlan_hdd_validate_context(pHddCtx);
8050
8051 if (0 != status)
8052 {
8053 hddLog(VOS_TRACE_LEVEL_ERROR,
8054 "%s: HDD context is not valid", __func__);
8055 return status;
8056 }
8057
8058 /*Retrieve halHandle*/
8059 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
8060
8061 /*in case index is 0,no entry to delete*/
8062 if (0 == PMKIDCacheIndex)
8063 {
8064 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid entry to delete" ,
8065 __func__);
8066 return -EINVAL;
8067 }
8068
8069 /*delete all the PMKSA one by one */
8070 for (j = 0; j<PMKIDCacheIndex; j++)
8071 {
Wilson Yang6507c4e2013-10-01 20:11:19 -07008072 pBSSId =(tANI_U8 *)(PMKIDCache[j].BSSID);
Wilson Yang6507c4e2013-10-01 20:11:19 -07008073
8074 /*delete the PMKID in CSR*/
Wilson Yangef657d32014-01-15 19:19:23 -08008075 if (eHAL_STATUS_SUCCESS !=
8076 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pBSSId))
Wilson Yang6507c4e2013-10-01 20:11:19 -07008077 {
8078 hddLog(VOS_TRACE_LEVEL_ERROR ,"%s cannot flush PMKIDCache %d.",
8079 __func__,j);
Wilson Yangef657d32014-01-15 19:19:23 -08008080 status = -EINVAL;
Wilson Yang6507c4e2013-10-01 20:11:19 -07008081 }
Kiet Lam8d21d5b2013-10-31 17:18:29 +05308082 /*clear the entry in HDD cache 0--index-1 */
8083 vos_mem_zero(PMKIDCache[j].BSSID, WNI_CFG_BSSID_LEN);
8084 vos_mem_zero(PMKIDCache[j].PMKID, CSR_RSN_PMKID_SIZE);
Wilson Yang6507c4e2013-10-01 20:11:19 -07008085 }
8086
8087 PMKIDCacheIndex = 0;
Wilson Yangef657d32014-01-15 19:19:23 -08008088 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008089}
8090#endif
8091
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008092#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308093static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008094 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
8095{
8096 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8097 hdd_station_ctx_t *pHddStaCtx;
8098
8099 if (NULL == pAdapter)
8100 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008101 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008102 return -ENODEV;
8103 }
8104
8105 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8106
8107 // Added for debug on reception of Re-assoc Req.
8108 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
8109 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008110 hddLog(LOGE, FL("Called with Ie of length = %zu when not associated"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008111 ftie->ie_len);
Arif Hussain6d2a3322013-11-17 19:50:10 -08008112 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008113 }
8114
8115#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Arif Hussain6d2a3322013-11-17 19:50:10 -08008116 hddLog(LOGE, FL("%s called with Ie of length = %zu"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008117 ftie->ie_len);
8118#endif
8119
8120 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05308121 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
8122 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07008123 ftie->ie_len);
8124 return 0;
8125}
8126#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008127
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308128#ifdef FEATURE_WLAN_SCAN_PNO
8129
8130void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
8131 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
8132{
8133 int ret;
8134 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
8135 hdd_context_t *pHddCtx;
8136
Nirav Shah80830bf2013-12-31 16:35:12 +05308137 ENTER();
8138
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308139 if (NULL == pAdapter)
8140 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308142 "%s: HDD adapter is Null", __func__);
8143 return ;
8144 }
8145
8146 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8147 if (NULL == pHddCtx)
8148 {
8149 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8150 "%s: HDD context is Null!!!", __func__);
8151 return ;
8152 }
8153
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308154 spin_lock(&pHddCtx->schedScan_lock);
8155 if (TRUE == pHddCtx->isWiphySuspended)
8156 {
8157 pHddCtx->isSchedScanUpdatePending = TRUE;
8158 spin_unlock(&pHddCtx->schedScan_lock);
8159 hddLog(VOS_TRACE_LEVEL_INFO,
8160 "%s: Update cfg80211 scan database after it resume", __func__);
8161 return ;
8162 }
8163 spin_unlock(&pHddCtx->schedScan_lock);
8164
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308165 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
8166
8167 if (0 > ret)
8168 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
8169
8170 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308171 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8172 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308173}
8174
8175/*
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308176 * FUNCTION: wlan_hdd_is_pno_allowed
8177 * To check is there any P2P GO/SAP or P2P Client/STA
8178 * session is active
8179 */
8180static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter)
8181{
8182 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8183 hdd_adapter_t *pTempAdapter = NULL;
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308184 hdd_station_ctx_t *pStaCtx;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308185 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8186 int status = 0;
8187 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
8188
8189 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status))
8190 {
8191 pTempAdapter = pAdapterNode->pAdapter;
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308192 pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pTempAdapter);
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308193
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308194 if (((WLAN_HDD_INFRA_STATION == pTempAdapter->device_mode)
8195 && (eConnectionState_NotConnected != pStaCtx->conn_info.connState))
8196 || (WLAN_HDD_P2P_CLIENT == pTempAdapter->device_mode)
8197 || (WLAN_HDD_P2P_GO == pTempAdapter->device_mode)
8198 || (WLAN_HDD_SOFTAP == pTempAdapter->device_mode)
8199 )
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308200 {
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308201 return eHAL_STATUS_FAILURE;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308202 }
8203 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8204 pAdapterNode = pNext;
8205 }
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308206 return eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308207}
8208
8209/*
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308210 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
8211 * NL interface to enable PNO
8212 */
8213static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
8214 struct net_device *dev, struct cfg80211_sched_scan_request *request)
8215{
8216 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8217 tpSirPNOScanReq pPnoRequest = NULL;
8218 hdd_context_t *pHddCtx;
8219 tHalHandle hHal;
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05308220 v_U32_t i, indx, num_ch, tempInterval;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308221 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
8222 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN];
8223 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
8224 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308225 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308226
8227 if (NULL == pAdapter)
8228 {
8229 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8230 "%s: HDD adapter is Null", __func__);
8231 return -ENODEV;
8232 }
8233
8234 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308235 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308236
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308237 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308238 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8240 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308241 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308242 }
8243
8244 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8245 if (NULL == hHal)
8246 {
8247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8248 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308249 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308250 }
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308251
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308252 /* The current firmware design for PNO does not consider concurrent
8253 * active sessions.Hence , determine the concurrent active sessions
8254 * and return a failure to the framework on a request for schedule
8255 * scan.
8256 */
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308257 if (eHAL_STATUS_SUCCESS != wlan_hdd_is_pno_allowed(pAdapter))
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308258 {
8259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +05308260 FL("Cannot handle sched_scan"));
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +05308261 return -EBUSY;
8262 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308263
8264 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
8265 if (NULL == pPnoRequest)
8266 {
8267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8268 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308269 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308270 }
8271
Madan Mohan Koyyalamudic3f04352013-09-26 19:21:48 +05308272 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308273 pPnoRequest->enable = 1; /*Enable PNO */
8274 pPnoRequest->ucNetworksCount = request->n_match_sets;
8275
8276 if (( !pPnoRequest->ucNetworksCount ) ||
8277 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
8278 {
8279 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308280 "%s: Network input is not correct %d",
8281 __func__, pPnoRequest->ucNetworksCount);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308282 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308283 goto error;
8284 }
8285
8286 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
8287 {
8288 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308289 "%s: Incorrect number of channels %d",
8290 __func__, request->n_channels);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308291 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308292 goto error;
8293 }
8294
8295 /* Framework provides one set of channels(all)
8296 * common for all saved profile */
8297 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
8298 channels_allowed, &num_channels_allowed))
8299 {
8300 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8301 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308302 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308303 goto error;
8304 }
8305 /* Checking each channel against allowed channel list */
8306 num_ch = 0;
Nirav Shah80830bf2013-12-31 16:35:12 +05308307 if (request->n_channels)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308308 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308309 char chList [(request->n_channels*5)+1];
8310 int len;
8311 for (i = 0, len = 0; i < request->n_channels; i++)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308312 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308313 for (indx = 0; indx < num_channels_allowed; indx++)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308314 {
Nirav Shah80830bf2013-12-31 16:35:12 +05308315 if (request->channels[i]->hw_value == channels_allowed[indx])
8316 {
8317 valid_ch[num_ch++] = request->channels[i]->hw_value;
8318 len += snprintf(chList+len, 5, "%d ",
8319 request->channels[i]->hw_value);
8320 break ;
8321 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308322 }
8323 }
Nirav Shah80830bf2013-12-31 16:35:12 +05308324 hddLog(VOS_TRACE_LEVEL_INFO,"Channel-List: %s ", chList);
8325 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308326
8327 /* Filling per profile params */
8328 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
8329 {
8330 pPnoRequest->aNetworks[i].ssId.length =
8331 request->match_sets[i].ssid.ssid_len;
8332
8333 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
8334 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
8335 {
8336 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308337 "%s: SSID Len %d is not correct for network %d",
8338 __func__, pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308339 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308340 goto error;
8341 }
8342
8343 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
8344 request->match_sets[i].ssid.ssid,
8345 request->match_sets[i].ssid.ssid_len);
8346 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
8347 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
8348 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
8349
8350 /*Copying list of valid channel into request */
8351 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
8352 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
8353
8354 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
8355 }
8356
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +05308357 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson59a121e2013-11-30 09:46:08 -08008358 "request->ie_len = %zu", request->ie_len);
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +05308359 if ((0 < request->ie_len) && (NULL != request->ie))
8360 {
8361 pPnoRequest->us24GProbeTemplateLen = request->ie_len;
8362 memcpy(&pPnoRequest->p24GProbeTemplate, request->ie,
8363 pPnoRequest->us24GProbeTemplateLen);
8364
8365 pPnoRequest->us5GProbeTemplateLen = request->ie_len;
8366 memcpy(&pPnoRequest->p5GProbeTemplate, request->ie,
8367 pPnoRequest->us5GProbeTemplateLen);
8368 }
8369
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +05308370 /* Driver gets only one time interval which is hardcoded in
8371 * supplicant for 10000ms. Taking power consumption into account 6 timers
8372 * will be used, Timervalue is increased exponentially i.e 10,20,40,
8373 * 80,160,320 secs. And number of scan cycle for each timer
8374 * is configurable through INI param gPNOScanTimerRepeatValue.
8375 * If it is set to 0 only one timer will be used and PNO scan cycle
8376 * will be repeated after each interval specified by supplicant
8377 * till PNO is disabled.
8378 */
8379 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
8380 pPnoRequest->scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
8381 else
8382 pPnoRequest->scanTimers.ucScanTimersCount =
8383 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
8384
8385 tempInterval = (request->interval)/1000;
8386 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8387 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
8388 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
8389 for ( i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++)
8390 {
8391 pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat =
8392 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
8393 pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = tempInterval;
8394 tempInterval *= 2;
8395 }
8396 //Repeat last timer until pno disabled.
8397 pPnoRequest->scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
8398
Madan Mohan Koyyalamudid206c7b2013-09-26 22:54:51 +05308399 pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308400
Nirav Shah80830bf2013-12-31 16:35:12 +05308401 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8402 "SessionId %d, enable %d, modePNO %d, ucScanTimersCount %d",
8403 pAdapter->sessionId, pPnoRequest->enable, pPnoRequest->modePNO,
8404 pPnoRequest->scanTimers.ucScanTimersCount);
8405
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308406 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
8407 pPnoRequest, pAdapter->sessionId,
8408 hdd_cfg80211_sched_scan_done_callback, pAdapter);
8409 if (eHAL_STATUS_SUCCESS != status)
8410 {
8411 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +05308412 "%s: Failed to enable PNO", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308413 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308414 goto error;
8415 }
8416
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308417 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8418 "PNO scanRequest offloaded");
8419
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308420error:
8421 vos_mem_free(pPnoRequest);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308422 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308423}
8424
8425/*
8426 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
8427 * NL interface to disable PNO
8428 */
8429static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
8430 struct net_device *dev)
8431{
8432 eHalStatus status = eHAL_STATUS_FAILURE;
8433 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8434 hdd_context_t *pHddCtx;
8435 tHalHandle hHal;
8436 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308437 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308438
8439 ENTER();
8440
8441 if (NULL == pAdapter)
8442 {
8443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8444 "%s: HDD adapter is Null", __func__);
8445 return -ENODEV;
8446 }
8447
8448 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308449
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308450 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308451 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05308452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308453 "%s: HDD context is Null", __func__);
8454 return -ENODEV;
8455 }
8456
8457 /* The return 0 is intentional when isLogpInProgress and
8458 * isLoadUnloadInProgress. We did observe a crash due to a return of
8459 * failure in sched_scan_stop , especially for a case where the unload
8460 * of the happens at the same time. The function __cfg80211_stop_sched_scan
8461 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
8462 * success. If it returns a failure , then its next invocation due to the
8463 * clean up of the second interface will have the dev pointer corresponding
8464 * to the first one leading to a crash.
8465 */
8466 if (pHddCtx->isLogpInProgress)
8467 {
8468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8469 "%s: LOGP in Progress. Ignore!!!", __func__);
8470 return ret;
8471 }
8472
8473 if (pHddCtx->isLoadUnloadInProgress)
8474 {
8475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8476 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
8477 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308478 }
8479
8480 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8481 if (NULL == hHal)
8482 {
8483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8484 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308485 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308486 }
8487
8488 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
8489 if (NULL == pPnoRequest)
8490 {
8491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8492 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308493 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308494 }
8495
8496 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
8497 pPnoRequest->enable = 0; /* Disable PNO */
8498 pPnoRequest->ucNetworksCount = 0;
8499
8500 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
8501 pAdapter->sessionId,
8502 NULL, pAdapter);
8503 if (eHAL_STATUS_SUCCESS != status)
8504 {
8505 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8506 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308507 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308508 }
8509
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8511 "%s: PNO scan disabled", __func__);
8512
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308513 vos_mem_free(pPnoRequest);
8514
8515 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +05308516 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05308517}
8518
8519#endif /*FEATURE_WLAN_SCAN_PNO*/
8520
8521
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008522#ifdef FEATURE_WLAN_TDLS
8523static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
8524 u8 *peer, u8 action_code, u8 dialog_token,
8525 u16 status_code, const u8 *buf, size_t len)
8526{
8527
8528 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8529 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008530 u8 peerMac[6];
8531 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07008532 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08008533 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -07008534 long rc;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008535
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008536 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008537 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008539 "Invalid arguments");
8540 return -EINVAL;
8541 }
8542
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008543 if (pHddCtx->isLogpInProgress)
8544 {
8545 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8546 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008547 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008548 return -EBUSY;
8549 }
8550
Hoonki Lee27511902013-03-14 18:19:06 -07008551 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008552 {
Hoonki Lee27511902013-03-14 18:19:06 -07008553 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
8554 "%s: TDLS mode is disabled OR not enabled in FW."
8555 MAC_ADDRESS_STR " action %d declined.",
8556 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008557 return -ENOTSUPP;
8558 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008559
Hoonki Lee27511902013-03-14 18:19:06 -07008560 /* other than teardown frame, other mgmt frames are not sent if disabled */
8561 if (SIR_MAC_TDLS_TEARDOWN != action_code)
8562 {
8563 /* if tdls_mode is disabled to respond to peer's request */
8564 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
8565 {
8566 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
8567 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008568 " TDLS mode is disabled. action %d declined.",
8569 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07008570
8571 return -ENOTSUPP;
8572 }
8573 }
8574
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008575 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
8576 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308577 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008578 {
8579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008580 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008581 " TDLS setup is ongoing. action %d declined.",
8582 __func__, MAC_ADDR_ARRAY(peer), action_code);
8583 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008584 }
8585 }
8586
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008587 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
8588 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08008589 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008590 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008591 {
8592 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
8593 we return error code at 'add_station()'. Hence we have this
8594 check again in addtion to add_station().
8595 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008596 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08008597 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8599 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008600 " TDLS Max peer already connected. action %d declined.",
8601 __func__, MAC_ADDR_ARRAY(peer), action_code);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308602 return -EINVAL;
Lee Hoonkic1262f22013-01-24 21:59:00 -08008603 }
8604 else
8605 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008606 /* maximum reached. tweak to send error code to peer and return
8607 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08008608 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8610 "%s: " MAC_ADDRESS_STR
8611 " TDLS Max peer already connected send response status %d",
8612 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008613 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008614 /* fall through to send setup resp with failure status
8615 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08008616 }
8617 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008618 else
8619 {
8620 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308621 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008622 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008623 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07008625 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
8626 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008627 return -EPERM;
8628 }
8629 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008630 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008631 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008632
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008633#ifdef WLAN_FEATURE_TDLS_DEBUG
8634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008635 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
8636 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
8637 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008638#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008639
Hoonki Leea34dd892013-02-05 22:56:02 -08008640 /*Except teardown responder will not be used so just make 0*/
8641 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08008642 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08008643 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008644
8645 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308646 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac, TRUE);
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008647
8648 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
8649 responder = pTdlsPeer->is_responder;
8650 else
Hoonki Leea34dd892013-02-05 22:56:02 -08008651 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -07008652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8653 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d",
8654 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
8655 dialog_token, status_code, len);
8656 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -08008657 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008658 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008659
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308660 /* For explicit trigger of DIS_REQ come out of BMPS for
8661 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -07008662 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308663 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
8664 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -07008665 {
8666 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
8667 {
8668 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308669 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -07008670 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
8671 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +05308672 if (SIR_MAC_TDLS_DIS_REQ != action_code)
8673 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -07008674 }
8675
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008676 /* make sure doesn't call send_mgmt() while it is pending */
8677 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
8678 {
8679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008680 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY",
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008681 __func__, MAC_ADDR_ARRAY(peer), action_code);
8682 return -EBUSY;
8683 }
8684
8685 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008686 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
8687
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008688 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08008689 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008690
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008691 if (VOS_STATUS_SUCCESS != status)
8692 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008693 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8694 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008695 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -07008696 wlan_hdd_tdls_check_bmps(pAdapter);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308697 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008698 }
8699
Hoonki Leed37cbb32013-04-20 00:31:14 -07008700 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
8701 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
8702
8703 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008704 {
Hoonki Leed37cbb32013-04-20 00:31:14 -07008705 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008706 "%s: Mgmt Tx Completion failed status %ld TxCompletion %u",
Hoonki Leed37cbb32013-04-20 00:31:14 -07008707 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008708 pAdapter->mgmtTxCompletionStatus = FALSE;
Yue Ma4f55ef32014-01-23 16:45:33 -08008709
8710 if (pHddCtx->isLogpInProgress)
8711 {
8712 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8713 "%s: LOGP in Progress. Ignore!!!", __func__);
8714 return -EAGAIN;
8715 }
8716
Hoonki Leed37cbb32013-04-20 00:31:14 -07008717 wlan_hdd_tdls_check_bmps(pAdapter);
Sunil Dutt388ac8f2013-11-28 18:06:52 +05308718 return -EINVAL;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008719 }
8720
Gopichand Nakkala05922802013-03-14 12:23:19 -07008721 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -07008722 {
8723 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -07008724 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -07008725 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008726
Hoonki Leea34dd892013-02-05 22:56:02 -08008727 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
8728 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008729 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08008730 }
8731 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
8732 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08008733 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08008734 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008735
8736 return 0;
8737}
8738
8739static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
8740 u8 *peer, enum nl80211_tdls_operation oper)
8741{
8742 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8743 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308744 int status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008745 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008746
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308747 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008748 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08008749 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07008750 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008751 return -EINVAL;
8752 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008753
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308754 status = wlan_hdd_validate_context(pHddCtx);
8755
8756 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008757 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8759 "%s: HDD context is not valid", __func__);
8760 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08008761 }
8762
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008763
8764 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008765 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008766 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08008767 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -07008768 "TDLS Disabled in INI OR not enabled in FW. "
8769 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008770 return -ENOTSUPP;
8771 }
8772
8773 switch (oper) {
8774 case NL80211_TDLS_ENABLE_LINK:
8775 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008776 VOS_STATUS status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308777 long ret;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308778 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008779
Sunil Dutt41de4e22013-11-14 18:09:02 +05308780 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8781
8782 if ( NULL == pTdlsPeer ) {
8783 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
8784 " (oper %d) not exsting. ignored",
8785 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
8786 return -EINVAL;
8787 }
8788
8789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8790 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
8791 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
8792 "NL80211_TDLS_ENABLE_LINK");
8793
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -07008794 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
8795 {
8796 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
8797 MAC_ADDRESS_STR " failed",
8798 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
8799 return -EINVAL;
8800 }
8801
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008802 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008803 {
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308804 if (IS_ADVANCE_TDLS_ENABLE) {
Gopichand Nakkala24be5312013-07-02 16:47:12 +05308805
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308806 if (0 != wlan_hdd_tdls_get_link_establish_params(
8807 pAdapter, peer,&tdlsLinkEstablishParams)) {
8808 return -EINVAL;
8809 }
8810 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308811
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +05308812 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
8813 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
8814 /* Send TDLS peer UAPSD capabilities to the firmware and
8815 * register with the TL on after the response for this operation
8816 * is received .
8817 */
8818 ret = wait_for_completion_interruptible_timeout(
8819 &pAdapter->tdls_link_establish_req_comp,
8820 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
8821 if (ret <= 0)
8822 {
8823 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8824 "%s: Link Establish Request Faled Status %ld",
8825 __func__, ret);
8826 return -EINVAL;
8827 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308828 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008829 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +05308830 /* Mark TDLS client Authenticated .*/
8831 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
8832 pTdlsPeer->staId,
8833 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008834 if (VOS_STATUS_SUCCESS == status)
8835 {
Hoonki Lee14621352013-04-16 17:51:19 -07008836 if (pTdlsPeer->is_responder == 0)
8837 {
8838 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
8839
8840 wlan_hdd_tdls_timer_restart(pAdapter,
8841 &pTdlsPeer->initiatorWaitTimeoutTimer,
8842 WAIT_TIME_TDLS_INITIATOR);
8843 /* suspend initiator TX until it receives direct packet from the
8844 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
8845 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8846 &staId, NULL);
8847 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07008848 wlan_hdd_tdls_increment_peer_count(pAdapter);
8849 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008850 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308851
8852 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308853 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
8854 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308855 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +05308856 int ac;
8857 uint8 ucAc[4] = { WLANTL_AC_VO,
8858 WLANTL_AC_VI,
8859 WLANTL_AC_BK,
8860 WLANTL_AC_BE };
8861 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
8862 for(ac=0; ac < 4; ac++)
8863 {
8864 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
8865 pTdlsPeer->staId, ucAc[ac],
8866 tlTid[ac], tlTid[ac], 0, 0,
8867 WLANTL_BI_DIR );
8868 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05308869 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008870 }
8871
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008872 }
8873 break;
8874 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08008875 {
Sunil Dutt41de4e22013-11-14 18:09:02 +05308876 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8877
8878 if ( NULL == pTdlsPeer ) {
8879 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
8880 " (oper %d) not exsting. ignored",
8881 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
8882 return -EINVAL;
8883 }
8884
8885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8886 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
8887 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
8888 "NL80211_TDLS_DISABLE_LINK");
8889
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008890 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -08008891 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008892 long status;
8893
8894 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
8895
Lee Hoonkic1262f22013-01-24 21:59:00 -08008896 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
8897 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008898
8899 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
8900 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
8901 if (status <= 0)
8902 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008903 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07008904 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8905 "%s: Del station failed status %ld",
8906 __func__, status);
8907 return -EPERM;
8908 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07008909 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008910 }
8911 else
8912 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008913 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8914 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08008915 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08008916 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07008917 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008918 case NL80211_TDLS_TEARDOWN:
Sunil Dutt41de4e22013-11-14 18:09:02 +05308919 {
8920 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8921 " %s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR,
8922 __func__, MAC_ADDR_ARRAY(peer));
8923
8924 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
8925 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
8926
8927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8928 " %s TDLS External control and Implicit Trigger not enabled ",
8929 __func__);
8930 return -ENOTSUPP;
8931 }
8932
Sunil Dutt41de4e22013-11-14 18:09:02 +05308933
8934 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
8935
8936 if ( NULL == pTdlsPeer ) {
8937 hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR
8938 " peer not exsting",
8939 __func__, MAC_ADDR_ARRAY(peer));
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308940 return -EINVAL;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308941 }
8942 else {
8943 wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer,
8944 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
8945 }
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308946
8947 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE) )
8948 return -EINVAL;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308949 break;
8950 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008951 case NL80211_TDLS_SETUP:
Sunil Dutt41de4e22013-11-14 18:09:02 +05308952 {
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308953 hddTdlsPeer_t *pTdlsPeer;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308954 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8955 " %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR,
8956 __func__, MAC_ADDR_ARRAY(peer));
8957
8958 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
8959 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
8960
8961 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8962 " %s TDLS External control and Implicit Trigger not enabled ",
8963 __func__);
8964 return -ENOTSUPP;
8965 }
8966
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308967 /* To cater the requirement of establishing the TDLS link
8968 * irrespective of the data traffic , get an entry of TDLS peer.
8969 */
8970 pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer);
8971 if (pTdlsPeer == NULL) {
8972 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8973 "%s: peer " MAC_ADDRESS_STR " not existing",
8974 __func__, MAC_ADDR_ARRAY(peer));
8975 return -EINVAL;
8976 }
Naresh Jayaram937abdf2013-11-26 19:50:25 +05308977
8978 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) {
8979
8980 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8981 " %s TDLS Add Force Peer Failed",
8982 __func__);
8983 return -EINVAL;
8984 }
Naresh Jayaramdb4514b2013-11-25 18:08:10 +05308985 break;
Sunil Dutt41de4e22013-11-14 18:09:02 +05308986 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008987 case NL80211_TDLS_DISCOVERY_REQ:
8988 /* We don't support in-driver setup/teardown/discovery */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308989 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8990 "%s: We don't support in-driver setup/teardown/discovery "
8991 ,__func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008992 return -ENOTSUPP;
8993 default:
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308994 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8995 "%s: unsupported event",__func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08008996 return -ENOTSUPP;
8997 }
8998 return 0;
8999}
Chilam NG571c65a2013-01-19 12:27:36 +05309000
9001int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
9002 struct net_device *dev, u8 *peer)
9003{
Arif Hussaina7c8e412013-11-20 11:06:42 -08009004 hddLog(VOS_TRACE_LEVEL_INFO,
9005 "tdls send discover req: "MAC_ADDRESS_STR,
9006 MAC_ADDR_ARRAY(peer));
Chilam NG571c65a2013-01-19 12:27:36 +05309007
9008 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
9009 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
9010}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08009011#endif
9012
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309013#ifdef WLAN_FEATURE_GTK_OFFLOAD
9014/*
9015 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
9016 * Callback rountine called upon receiving response for
9017 * get offload info
9018 */
9019void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
9020 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
9021{
9022
9023 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309024 tANI_U8 tempReplayCounter[8];
9025 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309026
9027 ENTER();
9028
9029 if (NULL == pAdapter)
9030 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05309031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309032 "%s: HDD adapter is Null", __func__);
9033 return ;
9034 }
9035
9036 if (NULL == pGtkOffloadGetInfoRsp)
9037 {
9038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9039 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
9040 return ;
9041 }
9042
9043 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
9044 {
9045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9046 "%s: wlan Failed to get replay counter value",
9047 __func__);
9048 return ;
9049 }
9050
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309051 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9052 /* Update replay counter */
9053 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
9054 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
9055
9056 {
9057 /* changing from little to big endian since supplicant
9058 * works on big endian format
9059 */
9060 int i;
9061 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
9062
9063 for (i = 0; i < 8; i++)
9064 {
9065 tempReplayCounter[7-i] = (tANI_U8)p[i];
9066 }
9067 }
9068
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309069 /* Update replay counter to NL */
9070 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309071 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309072}
9073
9074/*
9075 * FUNCTION: wlan_hdd_cfg80211_set_rekey_data
9076 * This function is used to offload GTK rekeying job to the firmware.
9077 */
9078int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
9079 struct cfg80211_gtk_rekey_data *data)
9080{
9081 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9082 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9083 hdd_station_ctx_t *pHddStaCtx;
9084 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309085 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309086 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309087 eHalStatus status = eHAL_STATUS_FAILURE;
9088
9089 ENTER();
9090
9091 if (NULL == pAdapter)
9092 {
9093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9094 "%s: HDD adapter is Null", __func__);
9095 return -ENODEV;
9096 }
9097
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309098 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309099
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309100 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309101 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05309102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9103 "%s: HDD context is not valid", __func__);
9104 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309105 }
9106
9107 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9108 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9109 if (NULL == hHal)
9110 {
9111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9112 "%s: HAL context is Null!!!", __func__);
9113 return -EAGAIN;
9114 }
9115
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309116 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
9117 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
9118 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
9119 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309120 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309121 {
9122 /* changing from big to little endian since driver
9123 * works on little endian format
9124 */
9125 tANI_U8 *p =
9126 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
9127 int i;
9128
9129 for (i = 0; i < 8; i++)
9130 {
9131 p[7-i] = data->replay_ctr[i];
9132 }
9133 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309134
9135 if (TRUE == pHddCtx->hdd_wlan_suspended)
9136 {
9137 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309138 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
9139 sizeof (tSirGtkOffloadParams));
9140 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309141 pAdapter->sessionId);
9142
9143 if (eHAL_STATUS_SUCCESS != status)
9144 {
9145 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9146 "%s: sme_SetGTKOffload failed, returned %d",
9147 __func__, status);
9148 return status;
9149 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309150 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9151 "%s: sme_SetGTKOffload successfull", __func__);
9152 }
9153 else
9154 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309155 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9156 "%s: wlan not suspended GTKOffload request is stored",
9157 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309158 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309159
9160 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309161}
9162#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
9163
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05309164/*
9165 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
9166 * This function is used to set access control policy
9167 */
9168static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
9169 struct net_device *dev, const struct cfg80211_acl_data *params)
9170{
9171 int i;
9172 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9173 hdd_hostapd_state_t *pHostapdState;
9174 tsap_Config_t *pConfig;
9175 v_CONTEXT_t pVosContext = NULL;
9176 hdd_context_t *pHddCtx;
9177 int status;
9178
9179 ENTER();
9180
9181 if (NULL == pAdapter)
9182 {
9183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9184 "%s: HDD adapter is Null", __func__);
9185 return -ENODEV;
9186 }
9187
9188 if (NULL == params)
9189 {
9190 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9191 "%s: params is Null", __func__);
9192 return -EINVAL;
9193 }
9194
9195 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9196 status = wlan_hdd_validate_context(pHddCtx);
9197
9198 if (0 != status)
9199 {
9200 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9201 "%s: HDD context is not valid", __func__);
9202 return status;
9203 }
9204
9205 pVosContext = pHddCtx->pvosContext;
9206 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9207
9208 if (NULL == pHostapdState)
9209 {
9210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9211 "%s: pHostapdState is Null", __func__);
9212 return -EINVAL;
9213 }
9214
9215 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
9216 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
9217
9218 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
9219 {
9220 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
9221
9222 /* default value */
9223 pConfig->num_accept_mac = 0;
9224 pConfig->num_deny_mac = 0;
9225
9226 /**
9227 * access control policy
9228 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
9229 * listed in hostapd.deny file.
9230 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
9231 * listed in hostapd.accept file.
9232 */
9233 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
9234 {
9235 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
9236 }
9237 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
9238 {
9239 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
9240 }
9241 else
9242 {
9243 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9244 "%s:Acl Policy : %d is not supported",
9245 __func__, params->acl_policy);
9246 return -ENOTSUPP;
9247 }
9248
9249 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
9250 {
9251 pConfig->num_accept_mac = params->n_acl_entries;
9252 for (i = 0; i < params->n_acl_entries; i++)
9253 {
9254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9255 "** Add ACL MAC entry %i in WhiletList :"
9256 MAC_ADDRESS_STR, i,
9257 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
9258
9259 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
9260 sizeof(qcmacaddr));
9261 }
9262 }
9263 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
9264 {
9265 pConfig->num_deny_mac = params->n_acl_entries;
9266 for (i = 0; i < params->n_acl_entries; i++)
9267 {
9268 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9269 "** Add ACL MAC entry %i in BlackList :"
9270 MAC_ADDRESS_STR, i,
9271 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
9272
9273 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
9274 sizeof(qcmacaddr));
9275 }
9276 }
9277
9278 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
9279 {
9280 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9281 "%s: SAP Set Mac Acl fail", __func__);
9282 return -EINVAL;
9283 }
9284 }
9285 else
9286 {
9287 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9288 "%s: Invalid device_mode = %d",
9289 __func__, pAdapter->device_mode);
9290 return -EINVAL;
9291 }
9292
9293 return 0;
9294}
9295
Leo Chang9056f462013-08-01 19:21:11 -07009296#ifdef WLAN_NL80211_TESTMODE
9297#ifdef FEATURE_WLAN_LPHB
Leo Changd9df8aa2013-09-26 13:32:26 -07009298void wlan_hdd_cfg80211_lphb_ind_handler
Leo Chang9056f462013-08-01 19:21:11 -07009299(
9300 void *pAdapter,
9301 void *indCont
9302)
9303{
Leo Changd9df8aa2013-09-26 13:32:26 -07009304 tSirLPHBInd *lphbInd;
9305 struct sk_buff *skb;
Leo Chang9056f462013-08-01 19:21:11 -07009306
9307 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -07009308 "LPHB indication arrived");
Leo Chang9056f462013-08-01 19:21:11 -07009309
9310 if (NULL == indCont)
9311 {
9312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -07009313 "LPHB IND, invalid argument");
Leo Chang9056f462013-08-01 19:21:11 -07009314 return;
9315 }
9316
Leo Changd9df8aa2013-09-26 13:32:26 -07009317 lphbInd = (tSirLPHBInd *)indCont;
Leo Chang9056f462013-08-01 19:21:11 -07009318 skb = cfg80211_testmode_alloc_event_skb(
9319 ((hdd_adapter_t *)pAdapter)->wdev.wiphy,
Leo Changd9df8aa2013-09-26 13:32:26 -07009320 sizeof(tSirLPHBInd),
Leo Chang9056f462013-08-01 19:21:11 -07009321 GFP_ATOMIC);
9322 if (!skb)
9323 {
9324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9325 "LPHB timeout, NL buffer alloc fail");
9326 return;
9327 }
9328
Leo Changac3ba772013-10-07 09:47:04 -07009329 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB))
Leo Changd9df8aa2013-09-26 13:32:26 -07009330 {
9331 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9332 "WLAN_HDD_TM_ATTR_CMD put fail");
9333 goto nla_put_failure;
9334 }
Leo Changac3ba772013-10-07 09:47:04 -07009335 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType))
Leo Changd9df8aa2013-09-26 13:32:26 -07009336 {
9337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9338 "WLAN_HDD_TM_ATTR_TYPE put fail");
9339 goto nla_put_failure;
9340 }
Leo Changac3ba772013-10-07 09:47:04 -07009341 if(nla_put(skb, WLAN_HDD_TM_ATTR_DATA,
Leo Changd9df8aa2013-09-26 13:32:26 -07009342 sizeof(tSirLPHBInd), lphbInd))
9343 {
9344 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9345 "WLAN_HDD_TM_ATTR_DATA put fail");
9346 goto nla_put_failure;
9347 }
Leo Chang9056f462013-08-01 19:21:11 -07009348 cfg80211_testmode_event(skb, GFP_ATOMIC);
9349 return;
9350
9351nla_put_failure:
9352 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9353 "NLA Put fail");
9354 kfree_skb(skb);
9355
9356 return;
9357}
9358#endif /* FEATURE_WLAN_LPHB */
9359
9360static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
9361{
9362 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
9363 int err = 0;
9364#ifdef FEATURE_WLAN_LPHB
9365 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Leo Changd9df8aa2013-09-26 13:32:26 -07009366 eHalStatus smeStatus;
Leo Chang9056f462013-08-01 19:21:11 -07009367#endif /* FEATURE_WLAN_LPHB */
9368
9369 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
9370 if (err)
9371 {
9372 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9373 "%s Testmode INV ATTR", __func__);
9374 return err;
9375 }
9376
9377 if (!tb[WLAN_HDD_TM_ATTR_CMD])
9378 {
9379 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9380 "%s Testmode INV CMD", __func__);
9381 return -EINVAL;
9382 }
9383
9384 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
9385 {
9386#ifdef FEATURE_WLAN_LPHB
9387 /* Low Power Heartbeat configuration request */
9388 case WLAN_HDD_TM_CMD_WLAN_HB:
9389 {
9390 int buf_len;
9391 void *buf;
9392 tSirLPHBReq *hb_params = NULL;
Amar Singhal05852702014-02-04 14:40:00 -08009393 tSirLPHBReq *hb_params_temp = NULL;
Leo Chang9056f462013-08-01 19:21:11 -07009394
9395 if (!tb[WLAN_HDD_TM_ATTR_DATA])
9396 {
9397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9398 "%s Testmode INV DATA", __func__);
9399 return -EINVAL;
9400 }
9401
9402 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
9403 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
Amar Singhal05852702014-02-04 14:40:00 -08009404
9405 hb_params_temp =(tSirLPHBReq *)buf;
9406 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID) &&
9407 (hb_params_temp->params.lphbTcpParamReq.timePeriodSec == 0))
9408 return -EINVAL;
9409
Leo Chang9056f462013-08-01 19:21:11 -07009410 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
9411 if (NULL == hb_params)
9412 {
9413 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9414 "%s Request Buffer Alloc Fail", __func__);
9415 return -EINVAL;
9416 }
9417
9418 vos_mem_copy(hb_params, buf, buf_len);
Leo Changd9df8aa2013-09-26 13:32:26 -07009419 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
9420 hb_params,
9421 wlan_hdd_cfg80211_lphb_ind_handler);
9422 if (eHAL_STATUS_SUCCESS != smeStatus)
Leo Chang9056f462013-08-01 19:21:11 -07009423 {
Leo Changd9df8aa2013-09-26 13:32:26 -07009424 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9425 "LPHB Config Fail, disable");
Leo Chang9056f462013-08-01 19:21:11 -07009426 vos_mem_free(hb_params);
9427 }
Leo Chang9056f462013-08-01 19:21:11 -07009428 return 0;
9429 }
9430#endif /* FEATURE_WLAN_LPHB */
9431 default:
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309432 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9433 "%s: unsupported event",__func__);
Leo Chang9056f462013-08-01 19:21:11 -07009434 return -EOPNOTSUPP;
9435 }
9436
9437 return err;
9438}
9439#endif /* CONFIG_NL80211_TESTMODE */
9440
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309441static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
9442 struct net_device *dev,
9443 int idx, struct survey_info *survey)
9444{
9445 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9446 hdd_context_t *pHddCtx;
Mihir Sheted9072e02013-08-21 17:02:29 +05309447 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309448 tHalHandle halHandle;
Mihir Sheted9072e02013-08-21 17:02:29 +05309449 v_U32_t channel = 0, freq = 0; /* Initialization Required */
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309450 v_S7_t snr,rssi;
9451 int status, i, j, filled = 0;
9452
9453 ENTER();
9454
9455
9456 if (NULL == pAdapter)
9457 {
9458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9459 "%s: HDD adapter is Null", __func__);
9460 return -ENODEV;
9461 }
9462
9463 if (NULL == wiphy)
9464 {
9465 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9466 "%s: wiphy is Null", __func__);
9467 return -ENODEV;
9468 }
9469
9470 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9471 status = wlan_hdd_validate_context(pHddCtx);
9472
9473 if (0 != status)
9474 {
9475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9476 "%s: HDD context is not valid", __func__);
9477 return status;
9478 }
9479
Mihir Sheted9072e02013-08-21 17:02:29 +05309480 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9481
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309482 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
Mihir Sheted9072e02013-08-21 17:02:29 +05309483 0 != pAdapter->survey_idx ||
9484 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309485 {
9486 /* The survey dump ops when implemented completely is expected to
9487 * return a survey of all channels and the ops is called by the
9488 * kernel with incremental values of the argument 'idx' till it
9489 * returns -ENONET. But we can only support the survey for the
9490 * operating channel for now. survey_idx is used to track
9491 * that the ops is called only once and then return -ENONET for
9492 * the next iteration
9493 */
9494 pAdapter->survey_idx = 0;
9495 return -ENONET;
9496 }
9497
9498 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9499
9500 wlan_hdd_get_snr(pAdapter, &snr);
9501 wlan_hdd_get_rssi(pAdapter, &rssi);
9502
9503 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
9504 hdd_wlan_get_freq(channel, &freq);
9505
9506
9507 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
9508 {
9509 if (NULL == wiphy->bands[i])
9510 {
9511 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
9512 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
9513 continue;
9514 }
9515
9516 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
9517 {
9518 struct ieee80211_supported_band *band = wiphy->bands[i];
9519
9520 if (band->channels[j].center_freq == (v_U16_t)freq)
9521 {
9522 survey->channel = &band->channels[j];
9523 /* The Rx BDs contain SNR values in dB for the received frames
9524 * while the supplicant expects noise. So we calculate and
9525 * return the value of noise (dBm)
9526 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
9527 */
9528 survey->noise = rssi - snr;
9529 survey->filled = SURVEY_INFO_NOISE_DBM;
9530 filled = 1;
9531 }
9532 }
9533 }
9534
9535 if (filled)
9536 pAdapter->survey_idx = 1;
9537 else
9538 {
9539 pAdapter->survey_idx = 0;
9540 return -ENONET;
9541 }
9542
9543 return 0;
9544}
9545
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309546/*
9547 * FUNCTION: wlan_hdd_cfg80211_resume_wlan
9548 * this is called when cfg80211 driver resume
9549 * driver updates latest sched_scan scan result(if any) to cfg80211 database
9550 */
9551int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
9552{
9553 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9554 hdd_adapter_t *pAdapter;
9555 hdd_adapter_list_node_t *pAdapterNode, *pNext;
9556 VOS_STATUS status = VOS_STATUS_SUCCESS;
9557
9558 ENTER();
9559
9560 if ( NULL == pHddCtx )
9561 {
9562 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9563 "%s: HddCtx validation failed", __func__);
9564 return 0;
9565 }
9566
9567 if (pHddCtx->isLogpInProgress)
9568 {
9569 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9570 "%s: LOGP in Progress. Ignore!!!", __func__);
9571 return 0;
9572 }
9573
9574 if (pHddCtx->isLoadUnloadInProgress)
9575 {
9576 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9577 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
9578 return 0;
9579 }
9580
9581 spin_lock(&pHddCtx->schedScan_lock);
9582 pHddCtx->isWiphySuspended = FALSE;
9583 if (TRUE != pHddCtx->isSchedScanUpdatePending)
9584 {
9585 spin_unlock(&pHddCtx->schedScan_lock);
9586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9587 "%s: Return resume is not due to PNO indication", __func__);
9588 return 0;
9589 }
9590 // Reset flag to avoid updatating cfg80211 data old results again
9591 pHddCtx->isSchedScanUpdatePending = FALSE;
9592 spin_unlock(&pHddCtx->schedScan_lock);
9593
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309594
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309595 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9596
9597 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9598 {
9599 pAdapter = pAdapterNode->pAdapter;
9600 if ( (NULL != pAdapter) &&
9601 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
9602 {
9603 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309604 {
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309605 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9606 "%s: NO SCAN result", __func__);
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309607 }
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309608 else
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309609 {
9610 /* Acquire wakelock to handle the case where APP's tries to
9611 * suspend immediately after updating the scan results. Whis
9612 * results in app's is in suspended state and not able to
9613 * process the connect request to AP
9614 */
9615 hdd_prevent_suspend_timeout(2000);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309616 cfg80211_sched_scan_results(pHddCtx->wiphy);
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05309617 }
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309618
9619 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9620 "%s : cfg80211 scan result database updated", __func__);
9621
9622 return 0;
9623
9624 }
9625 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9626 pAdapterNode = pNext;
9627 }
9628
9629 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9630 "%s: Failed to find Adapter", __func__);
9631 return 0;
9632}
9633
9634/*
9635 * FUNCTION: wlan_hdd_cfg80211_suspend_wlan
9636 * this is called when cfg80211 driver suspends
9637 */
9638int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
9639 struct cfg80211_wowlan *wow)
9640{
9641 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9642
9643 ENTER();
9644 if (NULL == pHddCtx)
9645 {
9646 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9647 "%s: HddCtx validation failed", __func__);
9648 return 0;
9649 }
9650
9651 pHddCtx->isWiphySuspended = TRUE;
9652
9653 EXIT();
9654
9655 return 0;
9656}
9657
Jeff Johnson295189b2012-06-20 16:38:30 -07009658/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309659static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -07009660{
9661 .add_virtual_intf = wlan_hdd_add_virtual_intf,
9662 .del_virtual_intf = wlan_hdd_del_virtual_intf,
9663 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
9664 .change_station = wlan_hdd_change_station,
9665#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
9666 .add_beacon = wlan_hdd_cfg80211_add_beacon,
9667 .del_beacon = wlan_hdd_cfg80211_del_beacon,
9668 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07009669#else
9670 .start_ap = wlan_hdd_cfg80211_start_ap,
9671 .change_beacon = wlan_hdd_cfg80211_change_beacon,
9672 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07009673#endif
9674 .change_bss = wlan_hdd_cfg80211_change_bss,
9675 .add_key = wlan_hdd_cfg80211_add_key,
9676 .get_key = wlan_hdd_cfg80211_get_key,
9677 .del_key = wlan_hdd_cfg80211_del_key,
9678 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08009679#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07009680 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08009681#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009682 .scan = wlan_hdd_cfg80211_scan,
9683 .connect = wlan_hdd_cfg80211_connect,
9684 .disconnect = wlan_hdd_cfg80211_disconnect,
9685 .join_ibss = wlan_hdd_cfg80211_join_ibss,
9686 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
9687 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
9688 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
9689 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07009690 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
9691 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
9692 .mgmt_tx = wlan_hdd_action,
9693#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9694 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
9695 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
9696 .set_txq_params = wlan_hdd_set_txq_params,
9697#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009698 .get_station = wlan_hdd_cfg80211_get_station,
9699 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
9700 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07009701 .add_station = wlan_hdd_cfg80211_add_station,
9702#ifdef FEATURE_WLAN_LFR
9703 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
9704 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
9705 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
9706#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07009707#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
9708 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
9709#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08009710#ifdef FEATURE_WLAN_TDLS
9711 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
9712 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
9713#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309714#ifdef WLAN_FEATURE_GTK_OFFLOAD
9715 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
9716#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05309717#ifdef FEATURE_WLAN_SCAN_PNO
9718 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
9719 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
9720#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05309721 .resume = wlan_hdd_cfg80211_resume_wlan,
9722 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05309723 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -07009724#ifdef WLAN_NL80211_TESTMODE
9725 .testmode_cmd = wlan_hdd_cfg80211_testmode,
9726#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309727 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -07009728};
9729