blob: a8070f9434ca47e7da0bf5081175f02f040e5318 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, 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/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**========================================================================
43
44 \file wlan_hdd_cfg80211.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 21/12/09 Ashwani Created module.
69
70 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
71 Ganesh K
72 ==========================================================================*/
73
Jeff Johnson295189b2012-06-20 16:38:30 -070074
75#include <linux/version.h>
76#include <linux/module.h>
77#include <linux/kernel.h>
78#include <linux/init.h>
79#include <linux/wireless.h>
80#include <wlan_hdd_includes.h>
81#include <net/arp.h>
82#include <net/cfg80211.h>
83#include <linux/wireless.h>
84#include <wlan_hdd_wowl.h>
85#include <aniGlobal.h>
86#include "ccmApi.h"
87#include "sirParams.h"
88#include "dot11f.h"
89#include "wlan_hdd_assoc.h"
90#include "wlan_hdd_wext.h"
91#include "sme_Api.h"
92#include "wlan_hdd_p2p.h"
93#include "wlan_hdd_cfg80211.h"
94#include "wlan_hdd_hostapd.h"
95#include "sapInternal.h"
96#include "wlan_hdd_softap_tx_rx.h"
97#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053098#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070099#ifdef WLAN_BTAMP_FEATURE
100#include "bap_hdd_misc.h"
101#endif
102#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800103#ifdef FEATURE_WLAN_TDLS
104#include "wlan_hdd_tdls.h"
105#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +0530106#include "wlan_nv.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700107
108#define g_mode_rates_size (12)
109#define a_mode_rates_size (8)
110#define FREQ_BASE_80211G (2407)
111#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700112#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
114 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
115
116#define HDD2GHZCHAN(freq, chan, flag) { \
117 .band = IEEE80211_BAND_2GHZ, \
118 .center_freq = (freq), \
119 .hw_value = (chan),\
120 .flags = (flag), \
121 .max_antenna_gain = 0 ,\
122 .max_power = 30, \
123}
124
125#define HDD5GHZCHAN(freq, chan, flag) { \
126 .band = IEEE80211_BAND_5GHZ, \
127 .center_freq = (freq), \
128 .hw_value = (chan),\
129 .flags = (flag), \
130 .max_antenna_gain = 0 ,\
131 .max_power = 30, \
132}
133
134#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
135{\
136 .bitrate = rate, \
137 .hw_value = rate_id, \
138 .flags = flag, \
139}
140
Lee Hoonkic1262f22013-01-24 21:59:00 -0800141#ifndef WLAN_FEATURE_TDLS_DEBUG
142#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
143#else
144#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
145#endif
146
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530147#ifdef WLAN_FEATURE_VOWIFI_11R
148#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
149#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
150#endif
151
Jeff Johnson295189b2012-06-20 16:38:30 -0700152static const u32 hdd_cipher_suites[] =
153{
154 WLAN_CIPHER_SUITE_WEP40,
155 WLAN_CIPHER_SUITE_WEP104,
156 WLAN_CIPHER_SUITE_TKIP,
157#ifdef FEATURE_WLAN_CCX
158#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
159 WLAN_CIPHER_SUITE_KRK,
160 WLAN_CIPHER_SUITE_CCMP,
161#else
162 WLAN_CIPHER_SUITE_CCMP,
163#endif
164#ifdef FEATURE_WLAN_WAPI
165 WLAN_CIPHER_SUITE_SMS4,
166#endif
167};
168
169static inline int is_broadcast_ether_addr(const u8 *addr)
170{
171 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
172 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
173}
174
175static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
176{
177 HDD2GHZCHAN(2412, 1, 0) ,
178 HDD2GHZCHAN(2417, 2, 0) ,
179 HDD2GHZCHAN(2422, 3, 0) ,
180 HDD2GHZCHAN(2427, 4, 0) ,
181 HDD2GHZCHAN(2432, 5, 0) ,
182 HDD2GHZCHAN(2437, 6, 0) ,
183 HDD2GHZCHAN(2442, 7, 0) ,
184 HDD2GHZCHAN(2447, 8, 0) ,
185 HDD2GHZCHAN(2452, 9, 0) ,
186 HDD2GHZCHAN(2457, 10, 0) ,
187 HDD2GHZCHAN(2462, 11, 0) ,
188 HDD2GHZCHAN(2467, 12, 0) ,
189 HDD2GHZCHAN(2472, 13, 0) ,
190 HDD2GHZCHAN(2484, 14, 0) ,
191};
192
Jeff Johnson295189b2012-06-20 16:38:30 -0700193static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
194{
195 HDD2GHZCHAN(2412, 1, 0) ,
196 HDD2GHZCHAN(2437, 6, 0) ,
197 HDD2GHZCHAN(2462, 11, 0) ,
198};
Jeff Johnson295189b2012-06-20 16:38:30 -0700199
200static struct ieee80211_channel hdd_channels_5_GHZ[] =
201{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700202 HDD5GHZCHAN(4920, 240, 0) ,
203 HDD5GHZCHAN(4940, 244, 0) ,
204 HDD5GHZCHAN(4960, 248, 0) ,
205 HDD5GHZCHAN(4980, 252, 0) ,
206 HDD5GHZCHAN(5040, 208, 0) ,
207 HDD5GHZCHAN(5060, 212, 0) ,
208 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700209 HDD5GHZCHAN(5180, 36, 0) ,
210 HDD5GHZCHAN(5200, 40, 0) ,
211 HDD5GHZCHAN(5220, 44, 0) ,
212 HDD5GHZCHAN(5240, 48, 0) ,
213 HDD5GHZCHAN(5260, 52, 0) ,
214 HDD5GHZCHAN(5280, 56, 0) ,
215 HDD5GHZCHAN(5300, 60, 0) ,
216 HDD5GHZCHAN(5320, 64, 0) ,
217 HDD5GHZCHAN(5500,100, 0) ,
218 HDD5GHZCHAN(5520,104, 0) ,
219 HDD5GHZCHAN(5540,108, 0) ,
220 HDD5GHZCHAN(5560,112, 0) ,
221 HDD5GHZCHAN(5580,116, 0) ,
222 HDD5GHZCHAN(5600,120, 0) ,
223 HDD5GHZCHAN(5620,124, 0) ,
224 HDD5GHZCHAN(5640,128, 0) ,
225 HDD5GHZCHAN(5660,132, 0) ,
226 HDD5GHZCHAN(5680,136, 0) ,
227 HDD5GHZCHAN(5700,140, 0) ,
228 HDD5GHZCHAN(5745,149, 0) ,
229 HDD5GHZCHAN(5765,153, 0) ,
230 HDD5GHZCHAN(5785,157, 0) ,
231 HDD5GHZCHAN(5805,161, 0) ,
232 HDD5GHZCHAN(5825,165, 0) ,
233};
234
235static struct ieee80211_rate g_mode_rates[] =
236{
237 HDD_G_MODE_RATETAB(10, 0x1, 0),
238 HDD_G_MODE_RATETAB(20, 0x2, 0),
239 HDD_G_MODE_RATETAB(55, 0x4, 0),
240 HDD_G_MODE_RATETAB(110, 0x8, 0),
241 HDD_G_MODE_RATETAB(60, 0x10, 0),
242 HDD_G_MODE_RATETAB(90, 0x20, 0),
243 HDD_G_MODE_RATETAB(120, 0x40, 0),
244 HDD_G_MODE_RATETAB(180, 0x80, 0),
245 HDD_G_MODE_RATETAB(240, 0x100, 0),
246 HDD_G_MODE_RATETAB(360, 0x200, 0),
247 HDD_G_MODE_RATETAB(480, 0x400, 0),
248 HDD_G_MODE_RATETAB(540, 0x800, 0),
249};
250
251static struct ieee80211_rate a_mode_rates[] =
252{
253 HDD_G_MODE_RATETAB(60, 0x10, 0),
254 HDD_G_MODE_RATETAB(90, 0x20, 0),
255 HDD_G_MODE_RATETAB(120, 0x40, 0),
256 HDD_G_MODE_RATETAB(180, 0x80, 0),
257 HDD_G_MODE_RATETAB(240, 0x100, 0),
258 HDD_G_MODE_RATETAB(360, 0x200, 0),
259 HDD_G_MODE_RATETAB(480, 0x400, 0),
260 HDD_G_MODE_RATETAB(540, 0x800, 0),
261};
262
263static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
264{
265 .channels = hdd_channels_2_4_GHZ,
266 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
267 .band = IEEE80211_BAND_2GHZ,
268 .bitrates = g_mode_rates,
269 .n_bitrates = g_mode_rates_size,
270 .ht_cap.ht_supported = 1,
271 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
272 | IEEE80211_HT_CAP_GRN_FLD
273 | IEEE80211_HT_CAP_DSSSCCK40
274 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
275 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
276 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
277 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
278 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
279 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
280};
281
Jeff Johnson295189b2012-06-20 16:38:30 -0700282static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
283{
284 .channels = hdd_social_channels_2_4_GHZ,
285 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
286 .band = IEEE80211_BAND_2GHZ,
287 .bitrates = g_mode_rates,
288 .n_bitrates = g_mode_rates_size,
289 .ht_cap.ht_supported = 1,
290 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
291 | IEEE80211_HT_CAP_GRN_FLD
292 | IEEE80211_HT_CAP_DSSSCCK40
293 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
294 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
295 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
296 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
297 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
298 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
299};
Jeff Johnson295189b2012-06-20 16:38:30 -0700300
301static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
302{
303 .channels = hdd_channels_5_GHZ,
304 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
305 .band = IEEE80211_BAND_5GHZ,
306 .bitrates = a_mode_rates,
307 .n_bitrates = a_mode_rates_size,
308 .ht_cap.ht_supported = 1,
309 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
310 | IEEE80211_HT_CAP_GRN_FLD
311 | IEEE80211_HT_CAP_DSSSCCK40
312 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
313 | IEEE80211_HT_CAP_SGI_40
314 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
315 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
316 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
317 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
318 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
319 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
320};
321
322/* This structure contain information what kind of frame are expected in
323 TX/RX direction for each kind of interface */
324static const struct ieee80211_txrx_stypes
325wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
326 [NL80211_IFTYPE_STATION] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ACTION) |
329 BIT(SIR_MAC_MGMT_PROBE_REQ),
330 },
331 [NL80211_IFTYPE_AP] = {
332 .tx = 0xffff,
333 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
334 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
335 BIT(SIR_MAC_MGMT_PROBE_REQ) |
336 BIT(SIR_MAC_MGMT_DISASSOC) |
337 BIT(SIR_MAC_MGMT_AUTH) |
338 BIT(SIR_MAC_MGMT_DEAUTH) |
339 BIT(SIR_MAC_MGMT_ACTION),
340 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700341 [NL80211_IFTYPE_P2P_CLIENT] = {
342 .tx = 0xffff,
343 .rx = BIT(SIR_MAC_MGMT_ACTION) |
344 BIT(SIR_MAC_MGMT_PROBE_REQ),
345 },
346 [NL80211_IFTYPE_P2P_GO] = {
347 /* This is also same as for SoftAP */
348 .tx = 0xffff,
349 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
350 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
351 BIT(SIR_MAC_MGMT_PROBE_REQ) |
352 BIT(SIR_MAC_MGMT_DISASSOC) |
353 BIT(SIR_MAC_MGMT_AUTH) |
354 BIT(SIR_MAC_MGMT_DEAUTH) |
355 BIT(SIR_MAC_MGMT_ACTION),
356 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700357};
358
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800359#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800360static const struct ieee80211_iface_limit
361wlan_hdd_iface_limit[] = {
362 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800363 /* max = 3 ; Our driver create two interfaces during driver init
364 * wlan0 and p2p0 interfaces. p2p0 is considered as station
365 * interface until a group is formed. In JB architecture, once the
366 * group is formed, interface type of p2p0 is changed to P2P GO or
367 * Client.
368 * When supplicant remove the group, it first issue a set interface
369 * cmd to change the mode back to Station. In JB this works fine as
370 * we advertize two station type interface during driver init.
371 * Some vendors create separate interface for P2P GO/Client,
372 * after group formation(Third one). But while group remove
373 * supplicant first tries to change the mode(3rd interface) to STATION
374 * But as we advertized only two sta type interfaces nl80211 was
375 * returning error for the third one which was leading to failure in
376 * delete interface. Ideally while removing the group, supplicant
377 * should not try to change the 3rd interface mode to Station type.
378 * Till we get a fix in wpa_supplicant, we advertize max STA
379 * interface type to 3
380 */
381 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800382 .types = BIT(NL80211_IFTYPE_STATION),
383 },
384 {
385 .max = 1,
386 .types = BIT(NL80211_IFTYPE_AP),
387 },
388 {
389 .max = 1,
390 .types = BIT(NL80211_IFTYPE_P2P_GO) |
391 BIT(NL80211_IFTYPE_P2P_CLIENT),
392 },
393};
394
395/* By default, only single channel concurrency is allowed */
396static struct ieee80211_iface_combination
397wlan_hdd_iface_combination = {
398 .limits = wlan_hdd_iface_limit,
399 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800400 /*
401 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
402 * and p2p0 interfaces during driver init
403 * Some vendors create separate interface for P2P operations.
404 * wlan0: STA interface
405 * p2p0: P2P Device interface, action frames goes
406 * through this interface.
407 * p2p-xx: P2P interface, After GO negotiation this interface is
408 * created for p2p operations(GO/CLIENT interface).
409 */
410 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800411 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
412 .beacon_int_infra_match = false,
413};
414#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800415
Jeff Johnson295189b2012-06-20 16:38:30 -0700416static struct cfg80211_ops wlan_hdd_cfg80211_ops;
417
418/* Data rate 100KBPS based on IE Index */
419struct index_data_rate_type
420{
421 v_U8_t beacon_rate_index;
422 v_U16_t supported_rate[4];
423};
424
425/* 11B, 11G Rate table include Basic rate and Extended rate
426 The IDX field is the rate index
427 The HI field is the rate when RSSI is strong or being ignored
428 (in this case we report actual rate)
429 The MID field is the rate when RSSI is moderate
430 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
431 The LO field is the rate when RSSI is low
432 (in this case we don't report rates, actual current rate used)
433 */
434static const struct
435{
436 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700437 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700438} supported_data_rate[] =
439{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700440/* IDX HI HM LM LO (RSSI-based index */
441 {2, { 10, 10, 10, 0}},
442 {4, { 20, 20, 10, 0}},
443 {11, { 55, 20, 10, 0}},
444 {12, { 60, 55, 20, 0}},
445 {18, { 90, 55, 20, 0}},
446 {22, {110, 55, 20, 0}},
447 {24, {120, 90, 60, 0}},
448 {36, {180, 120, 60, 0}},
449 {44, {220, 180, 60, 0}},
450 {48, {240, 180, 90, 0}},
451 {66, {330, 180, 90, 0}},
452 {72, {360, 240, 90, 0}},
453 {96, {480, 240, 120, 0}},
454 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700455};
456
457/* MCS Based rate table */
458static struct index_data_rate_type supported_mcs_rate[] =
459{
460/* MCS L20 L40 S20 S40 */
461 {0, {65, 135, 72, 150}},
462 {1, {130, 270, 144, 300}},
463 {2, {195, 405, 217, 450}},
464 {3, {260, 540, 289, 600}},
465 {4, {390, 810, 433, 900}},
466 {5, {520, 1080, 578, 1200}},
467 {6, {585, 1215, 650, 1350}},
468 {7, {650, 1350, 722, 1500}}
469};
470
471extern struct net_device_ops net_ops_struct;
472
473/*
474 * FUNCTION: wlan_hdd_cfg80211_init
475 * This function is called by hdd_wlan_startup()
476 * during initialization.
477 * This function is used to initialize and register wiphy structure.
478 */
479struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
480{
481 struct wiphy *wiphy;
482 ENTER();
483
484 /*
485 * Create wiphy device
486 */
487 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
488
489 if (!wiphy)
490 {
491 /* Print error and jump into err label and free the memory */
492 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
493 return NULL;
494 }
495
496 return wiphy;
497}
498
499/*
500 * FUNCTION: wlan_hdd_cfg80211_update_band
501 * This function is called from the supplicant through a
502 * private ioctl to change the band value
503 */
504int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
505{
Jeff Johnsone7245742012-09-05 17:12:55 -0700506 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700507 switch(eBand)
508 {
509 case eCSR_BAND_24:
510 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
511 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
512 break;
513 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700514 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700515 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
516 break;
517 case eCSR_BAND_ALL:
518 default:
519 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
520 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
521 }
522 return 0;
523}
524/*
525 * FUNCTION: wlan_hdd_cfg80211_init
526 * This function is called by hdd_wlan_startup()
527 * during initialization.
528 * This function is used to initialize and register wiphy structure.
529 */
530int wlan_hdd_cfg80211_register(struct device *dev,
531 struct wiphy *wiphy,
532 hdd_config_t *pCfg
533 )
534{
Jeff Johnsone7245742012-09-05 17:12:55 -0700535 ENTER();
536
Jeff Johnson295189b2012-06-20 16:38:30 -0700537 /* Now bind the underlying wlan device with wiphy */
538 set_wiphy_dev(wiphy, dev);
539
540 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
541
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700542 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700543
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700544#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700545 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
546 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
547 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700548 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700549#endif
James Zmuda77fb5ae2013-01-29 08:00:17 -0800550#ifdef FEATURE_WLAN_LFR
551 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
552#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800553#ifdef FEATURE_WLAN_TDLS
554 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
555 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
556#endif
557
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700558 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
559 driver can still register regulatory callback and
560 it will get CRDA setting in wiphy->band[], but
561 driver need to determine what to do with both
562 regulatory settings */
563 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700564
Jeff Johnson295189b2012-06-20 16:38:30 -0700565 wiphy->max_scan_ssids = MAX_SCAN_SSID;
566
567 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
568
569 /* Supports STATION & AD-HOC modes right now */
570 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
571 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -0700572 | BIT(NL80211_IFTYPE_P2P_CLIENT)
573 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -0700574 | BIT(NL80211_IFTYPE_AP);
575
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800576#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800577 if( pCfg->enableMCC )
578 {
579 /* Currently, supports up to two channels */
580 wlan_hdd_iface_combination.num_different_channels = 2;
581
582 if( !pCfg->allowMCCGODiffBI )
583 wlan_hdd_iface_combination.beacon_int_infra_match = true;
584
585 }
586 wiphy->iface_combinations = &wlan_hdd_iface_combination;
587 wiphy->n_iface_combinations = 1;
588#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800589
Jeff Johnson295189b2012-06-20 16:38:30 -0700590 /* Before registering we need to update the ht capabilitied based
591 * on ini values*/
592 if( !pCfg->ShortGI20MhzEnable )
593 {
594 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
595 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
596 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
597 }
598
599 if( !pCfg->ShortGI40MhzEnable )
600 {
601 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
602 }
603
604 if( !pCfg->nChannelBondingMode5GHz )
605 {
606 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
607 }
608
609 /*Initialize band capability*/
610 switch(pCfg->nBandCapability)
611 {
612 case eCSR_BAND_24:
613 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
614 break;
615 case eCSR_BAND_5G:
Jeff Johnson295189b2012-06-20 16:38:30 -0700616 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700617 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
618 break;
619 case eCSR_BAND_ALL:
620 default:
621 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
622 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
623 }
624 /*Initialise the supported cipher suite details*/
625 wiphy->cipher_suites = hdd_cipher_suites;
626 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
627
628 /*signal strength in mBm (100*dBm) */
629 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
630
631#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -0700632 wiphy->max_remain_on_channel_duration = 1000;
633#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700634
635 /* Register our wiphy dev with cfg80211 */
636 if (0 > wiphy_register(wiphy))
637 {
638 /* print eror */
639 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
640 return -EIO;
641 }
642
643 EXIT();
644 return 0;
645}
646
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700647/* In this function we will try to get default country code from crda.
648 If the gCrdaDefaultCountryCode is configured in ini file,
649 we will try to call user space crda to get the regulatory settings for
650 that country. We will timeout if we can't get it from crda.
651 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
652*/
653int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
654{
655 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
656 if (memcmp(pCfg->crdaDefaultCountryCode,
657 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
658 {
659 init_completion(&pHddCtx->driver_crda_req);
660 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
661 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
662 CRDA_WAIT_TIME);
663 }
664 return 0;
665}
666
Jeff Johnson295189b2012-06-20 16:38:30 -0700667/* In this function we will do all post VOS start initialization.
668 In this function we will register for all frame in which supplicant
669 is interested.
670*/
671void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
672{
Jeff Johnson295189b2012-06-20 16:38:30 -0700673 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
674 /* Register for all P2P action, public action etc frames */
675 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
676
Jeff Johnsone7245742012-09-05 17:12:55 -0700677 ENTER();
678
Jeff Johnson295189b2012-06-20 16:38:30 -0700679 /* Right now we are registering these frame when driver is getting
680 initialized. Once we will move to 2.6.37 kernel, in which we have
681 frame register ops, we will move this code as a part of that */
682 /* GAS Initial Request */
683 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
684 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
685
686 /* GAS Initial Response */
687 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
688 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
689
690 /* GAS Comeback Request */
691 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
692 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
693
694 /* GAS Comeback Response */
695 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
696 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
697
698 /* P2P Public Action */
699 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
700 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
701 P2P_PUBLIC_ACTION_FRAME_SIZE );
702
703 /* P2P Action */
704 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
705 (v_U8_t*)P2P_ACTION_FRAME,
706 P2P_ACTION_FRAME_SIZE );
Jeff Johnson295189b2012-06-20 16:38:30 -0700707}
708
709void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
710{
Jeff Johnson295189b2012-06-20 16:38:30 -0700711 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
712 /* Register for all P2P action, public action etc frames */
713 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
714
Jeff Johnsone7245742012-09-05 17:12:55 -0700715 ENTER();
716
Jeff Johnson295189b2012-06-20 16:38:30 -0700717 /* Right now we are registering these frame when driver is getting
718 initialized. Once we will move to 2.6.37 kernel, in which we have
719 frame register ops, we will move this code as a part of that */
720 /* GAS Initial Request */
721
722 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
723 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
724
725 /* GAS Initial Response */
726 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
727 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
728
729 /* GAS Comeback Request */
730 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
731 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
732
733 /* GAS Comeback Response */
734 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
735 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
736
737 /* P2P Public Action */
738 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
739 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
740 P2P_PUBLIC_ACTION_FRAME_SIZE );
741
742 /* P2P Action */
743 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
744 (v_U8_t*)P2P_ACTION_FRAME,
745 P2P_ACTION_FRAME_SIZE );
Jeff Johnson295189b2012-06-20 16:38:30 -0700746}
747
748#ifdef FEATURE_WLAN_WAPI
749void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
750 const u8 *mac_addr, u8 *key , int key_Len)
751{
752 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
753 tCsrRoamSetKey setKey;
754 v_BOOL_t isConnected = TRUE;
755 int status = 0;
756 v_U32_t roamId= 0xFF;
757 tANI_U8 *pKeyPtr = NULL;
758 int n = 0;
759
760 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
761 __func__,pAdapter->device_mode);
762
Gopichand Nakkalae7480202013-02-11 15:24:22 +0530763 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -0700764 setKey.keyId = key_index; // Store Key ID
765 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
766 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
767 setKey.paeRole = 0 ; // the PAE role
768 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
769 {
770 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
771 }
772 else
773 {
774 isConnected = hdd_connIsConnected(pHddStaCtx);
775 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
776 }
777 setKey.keyLength = key_Len;
778 pKeyPtr = setKey.Key;
779 memcpy( pKeyPtr, key, key_Len);
780
781 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
782 __func__, key_Len);
783 for (n = 0 ; n < key_Len; n++)
784 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
785 __func__,n,setKey.Key[n]);
786
787 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
788 if ( isConnected )
789 {
790 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
791 pAdapter->sessionId, &setKey, &roamId );
792 }
793 if ( status != 0 )
794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "[%4d] sme_RoamSetKey returned ERROR status= %d",
797 __LINE__, status );
798 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
799 }
800}
801#endif /* FEATURE_WLAN_WAPI*/
802
803#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
804int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
805 beacon_data_t **ppBeacon,
806 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700807#else
808int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
809 beacon_data_t **ppBeacon,
810 struct cfg80211_beacon_data *params,
811 int dtim_period)
812#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700813{
814 int size;
815 beacon_data_t *beacon = NULL;
816 beacon_data_t *old = NULL;
817 int head_len,tail_len;
818
Jeff Johnsone7245742012-09-05 17:12:55 -0700819 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700820 if (params->head && !params->head_len)
821 return -EINVAL;
822
823 old = pAdapter->sessionCtx.ap.beacon;
824
825 if (!params->head && !old)
826 return -EINVAL;
827
828 if (params->tail && !params->tail_len)
829 return -EINVAL;
830
831#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
832 /* Kernel 3.0 is not updating dtim_period for set beacon */
833 if (!params->dtim_period)
834 return -EINVAL;
835#endif
836
837 if(params->head)
838 head_len = params->head_len;
839 else
840 head_len = old->head_len;
841
842 if(params->tail || !old)
843 tail_len = params->tail_len;
844 else
845 tail_len = old->tail_len;
846
847 size = sizeof(beacon_data_t) + head_len + tail_len;
848
849 beacon = kzalloc(size, GFP_KERNEL);
850
851 if( beacon == NULL )
852 return -ENOMEM;
853
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700854#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700855 if(params->dtim_period || !old )
856 beacon->dtim_period = params->dtim_period;
857 else
858 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700859#else
860 if(dtim_period || !old )
861 beacon->dtim_period = dtim_period;
862 else
863 beacon->dtim_period = old->dtim_period;
864#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700865
866 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
867 beacon->tail = beacon->head + head_len;
868 beacon->head_len = head_len;
869 beacon->tail_len = tail_len;
870
871 if(params->head) {
872 memcpy (beacon->head,params->head,beacon->head_len);
873 }
874 else {
875 if(old)
876 memcpy (beacon->head,old->head,beacon->head_len);
877 }
878
879 if(params->tail) {
880 memcpy (beacon->tail,params->tail,beacon->tail_len);
881 }
882 else {
883 if(old)
884 memcpy (beacon->tail,old->tail,beacon->tail_len);
885 }
886
887 *ppBeacon = beacon;
888
889 kfree(old);
890
891 return 0;
892
893}
Jeff Johnson295189b2012-06-20 16:38:30 -0700894
895v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
896{
897 int left = length;
898 v_U8_t *ptr = pIes;
899 v_U8_t elem_id,elem_len;
900
901 while(left >= 2)
902 {
903 elem_id = ptr[0];
904 elem_len = ptr[1];
905 left -= 2;
906 if(elem_len > left)
907 {
908 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700909 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700910 eid,elem_len,left);
911 return NULL;
912 }
913 if (elem_id == eid)
914 {
915 return ptr;
916 }
917
918 left -= elem_len;
919 ptr += (elem_len + 2);
920 }
921 return NULL;
922}
923
Jeff Johnson295189b2012-06-20 16:38:30 -0700924/* Check if rate is 11g rate or not */
925static int wlan_hdd_rate_is_11g(u8 rate)
926{
927 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
928 u8 i;
929 for (i = 0; i < 8; i++)
930 {
931 if(rate == gRateArray[i])
932 return TRUE;
933 }
934 return FALSE;
935}
936
937/* Check for 11g rate and set proper 11g only mode */
938static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
939 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
940{
941 u8 i, num_rates = pIe[0];
942
943 pIe += 1;
944 for ( i = 0; i < num_rates; i++)
945 {
946 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
947 {
948 /* If rate set have 11g rate than change the mode to 11G */
949 *pSapHw_mode = eSAP_DOT11_MODE_11g;
950 if (pIe[i] & BASIC_RATE_MASK)
951 {
952 /* If we have 11g rate as basic rate, it means mode
953 is 11g only mode.
954 */
955 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
956 *pCheckRatesfor11g = FALSE;
957 }
958 }
959 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
960 {
961 *require_ht = TRUE;
962 }
963 }
964 return;
965}
966
967static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
968{
969 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
970 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
971 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
972 u8 checkRatesfor11g = TRUE;
973 u8 require_ht = FALSE;
974 u8 *pIe=NULL;
975
976 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
977
978 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
979 pBeacon->head_len, WLAN_EID_SUPP_RATES);
980 if (pIe != NULL)
981 {
982 pIe += 1;
983 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
984 &pConfig->SapHw_mode);
985 }
986
987 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
988 WLAN_EID_EXT_SUPP_RATES);
989 if (pIe != NULL)
990 {
991
992 pIe += 1;
993 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
994 &pConfig->SapHw_mode);
995 }
996
997 if( pConfig->channel > 14 )
998 {
999 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1000 }
1001
1002 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1003 WLAN_EID_HT_CAPABILITY);
1004
1005 if(pIe)
1006 {
1007 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1008 if(require_ht)
1009 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1010 }
1011}
1012
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301013static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
1014 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
1015{
1016 v_U8_t ielen = 0;
1017 v_U8_t *pIe = NULL;
1018 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1019
1020 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
1021 pBeacon->tail, pBeacon->tail_len);
1022
1023 if (pIe)
1024 {
1025 ielen = pIe[1] + 2;
1026 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
1027 {
1028 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
1029 }
1030 else
1031 {
1032 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
1033 return -EINVAL;
1034 }
1035 *total_ielen += ielen;
1036 }
1037 return 0;
1038}
1039
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001040#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001041static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1042 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001043#else
1044static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1045 struct cfg80211_beacon_data *params)
1046#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001047{
1048 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301049 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001050 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07001051 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001052
1053 genie = vos_mem_malloc(MAX_GENIE_LEN);
1054
1055 if(genie == NULL) {
1056
1057 return -ENOMEM;
1058 }
1059
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301060 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1061 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001062 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301063 ret = -EINVAL;
1064 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001065 }
1066
1067#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301068 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1069 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
1070 {
1071 ret = -EINVAL;
1072 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001073 }
1074#endif
1075
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301076 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1077 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001078 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301079 ret = -EINVAL;
1080 goto done;
1081 }
1082
1083 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
1084 {
1085 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
1086 &total_ielen, SS_OUI_TYPE, SS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07001087 {
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301088 ret = -EINVAL;
1089 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001090 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001091 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001092
1093 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1094 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1095 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1096 {
1097 hddLog(LOGE,
1098 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001099 ret = -EINVAL;
1100 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001101 }
1102
1103 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1104 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1105 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1106 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1107 ==eHAL_STATUS_FAILURE)
1108 {
1109 hddLog(LOGE,
1110 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001111 ret = -EINVAL;
1112 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001113 }
1114
1115 // Added for ProResp IE
1116 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1117 {
1118 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1119 u8 probe_rsp_ie_len[3] = {0};
1120 u8 counter = 0;
1121 /* Check Probe Resp Length if it is greater then 255 then Store
1122 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1123 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1124 Store More then 255 bytes into One Variable.
1125 */
1126 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1127 {
1128 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1129 {
1130 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1131 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1132 }
1133 else
1134 {
1135 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1136 rem_probe_resp_ie_len = 0;
1137 }
1138 }
1139
1140 rem_probe_resp_ie_len = 0;
1141
1142 if (probe_rsp_ie_len[0] > 0)
1143 {
1144 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1145 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1146 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1147 probe_rsp_ie_len[0], NULL,
1148 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1149 {
1150 hddLog(LOGE,
1151 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001152 ret = -EINVAL;
1153 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 }
1155 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1156 }
1157
1158 if (probe_rsp_ie_len[1] > 0)
1159 {
1160 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1161 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1162 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1163 probe_rsp_ie_len[1], NULL,
1164 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1165 {
1166 hddLog(LOGE,
1167 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001168 ret = -EINVAL;
1169 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001170 }
1171 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1172 }
1173
1174 if (probe_rsp_ie_len[2] > 0)
1175 {
1176 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1177 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1178 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1179 probe_rsp_ie_len[2], NULL,
1180 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1181 {
1182 hddLog(LOGE,
1183 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001184 ret = -EINVAL;
1185 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001186 }
1187 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1188 }
1189
1190 if (probe_rsp_ie_len[1] == 0 )
1191 {
1192 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1193 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1194 eANI_BOOLEAN_FALSE) )
1195 {
1196 hddLog(LOGE,
1197 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1198 }
1199 }
1200
1201 if (probe_rsp_ie_len[2] == 0 )
1202 {
1203 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1204 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1205 eANI_BOOLEAN_FALSE) )
1206 {
1207 hddLog(LOGE,
1208 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1209 }
1210 }
1211
1212 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1213 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1214 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1215 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1216 == eHAL_STATUS_FAILURE)
1217 {
1218 hddLog(LOGE,
1219 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001220 ret = -EINVAL;
1221 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001222 }
1223 }
1224 else
1225 {
1226 // Reset WNI_CFG_PROBE_RSP Flags
1227 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1228
1229 hddLog(VOS_TRACE_LEVEL_INFO,
1230 "%s: No Probe Response IE received in set beacon",
1231 __func__);
1232 }
1233
1234 // Added for AssocResp IE
1235 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1236 {
1237 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1238 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1239 params->assocresp_ies_len, NULL,
1240 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1241 {
1242 hddLog(LOGE,
1243 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001244 ret = -EINVAL;
1245 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001246 }
1247
1248 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1249 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1250 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1251 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1252 == eHAL_STATUS_FAILURE)
1253 {
1254 hddLog(LOGE,
1255 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001256 ret = -EINVAL;
1257 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001258 }
1259 }
1260 else
1261 {
1262 hddLog(VOS_TRACE_LEVEL_INFO,
1263 "%s: No Assoc Response IE received in set beacon",
1264 __func__);
1265
1266 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1267 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1268 eANI_BOOLEAN_FALSE) )
1269 {
1270 hddLog(LOGE,
1271 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1272 }
1273 }
1274
Jeff Johnsone7245742012-09-05 17:12:55 -07001275done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05301277 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001278}
Jeff Johnson295189b2012-06-20 16:38:30 -07001279
1280/*
1281 * FUNCTION: wlan_hdd_validate_operation_channel
1282 * called by wlan_hdd_cfg80211_start_bss() and
1283 * wlan_hdd_cfg80211_set_channel()
1284 * This function validates whether given channel is part of valid
1285 * channel list.
1286 */
1287static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1288{
1289
1290 v_U32_t num_ch = 0;
1291 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1292 u32 indx = 0;
1293 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301294 v_U8_t fValidChannel = FALSE, count = 0;
1295 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001296
1297 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1298
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301299 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001300 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301301 /* Validate the channel */
1302 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001303 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301304 if ( channel == rfChannels[count].channelNum )
1305 {
1306 fValidChannel = TRUE;
1307 break;
1308 }
1309 }
1310 if (fValidChannel != TRUE)
1311 {
1312 hddLog(VOS_TRACE_LEVEL_ERROR,
1313 "%s: Invalid Channel [%d]", __func__, channel);
1314 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001315 }
1316 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301317 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001318 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301319 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1320 valid_ch, &num_ch))
1321 {
1322 hddLog(VOS_TRACE_LEVEL_ERROR,
1323 "%s: failed to get valid channel list", __func__);
1324 return VOS_STATUS_E_FAILURE;
1325 }
1326 for (indx = 0; indx < num_ch; indx++)
1327 {
1328 if (channel == valid_ch[indx])
1329 {
1330 break;
1331 }
1332 }
1333
1334 if (indx >= num_ch)
1335 {
1336 hddLog(VOS_TRACE_LEVEL_ERROR,
1337 "%s: Invalid Channel [%d]", __func__, channel);
1338 return VOS_STATUS_E_FAILURE;
1339 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001340 }
1341 return VOS_STATUS_SUCCESS;
1342
1343}
1344
Viral Modi3a32cc52013-02-08 11:14:52 -08001345/**
1346 * FUNCTION: wlan_hdd_cfg80211_set_channel
1347 * This function is used to set the channel number
1348 */
1349static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1350 struct ieee80211_channel *chan,
1351 enum nl80211_channel_type channel_type
1352 )
1353{
1354 v_U32_t num_ch = 0;
1355 u32 channel = 0;
1356 hdd_adapter_t *pAdapter = NULL;
1357 int freq = chan->center_freq; /* freq is in MHZ */
1358
1359 ENTER();
1360
1361 if( NULL == dev )
1362 {
1363 hddLog(VOS_TRACE_LEVEL_ERROR,
1364 "%s: Called with dev = NULL.\n", __func__);
1365 return -ENODEV;
1366 }
1367 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1368
1369 hddLog(VOS_TRACE_LEVEL_INFO,
1370 "%s: device_mode = %d freq = %d \n",__func__,
1371 pAdapter->device_mode, chan->center_freq);
1372 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1373 {
1374 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1375 return -EAGAIN;
1376 }
1377
1378 /*
1379 * Do freq to chan conversion
1380 * TODO: for 11a
1381 */
1382
1383 channel = ieee80211_frequency_to_channel(freq);
1384
1385 /* Check freq range */
1386 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1387 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1388 {
1389 hddLog(VOS_TRACE_LEVEL_ERROR,
1390 "%s: Channel [%d] is outside valid range from %d to %d\n",
1391 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1392 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1393 return -EINVAL;
1394 }
1395
1396 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1397
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301398 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1399 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001400 {
1401 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1402 {
1403 hddLog(VOS_TRACE_LEVEL_ERROR,
1404 "%s: Invalid Channel [%d] \n", __func__, channel);
1405 return -EINVAL;
1406 }
1407 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1408 "%s: set channel to [%d] for device mode =%d",
1409 __func__, channel,pAdapter->device_mode);
1410 }
1411 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001412 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001413 )
1414 {
1415 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1416 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1417 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1418
1419 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1420 {
1421 /* Link is up then return cant set channel*/
1422 hddLog( VOS_TRACE_LEVEL_ERROR,
1423 "%s: IBSS Associated, can't set the channel\n", __func__);
1424 return -EINVAL;
1425 }
1426
1427 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1428 pHddStaCtx->conn_info.operationChannel = channel;
1429 pRoamProfile->ChannelInfo.ChannelList =
1430 &pHddStaCtx->conn_info.operationChannel;
1431 }
1432 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001433 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001434 )
1435 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301436 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1437 {
1438 if(VOS_STATUS_SUCCESS !=
1439 wlan_hdd_validate_operation_channel(pAdapter,channel))
1440 {
1441 hddLog(VOS_TRACE_LEVEL_ERROR,
1442 "%s: Invalid Channel [%d] \n", __func__, channel);
1443 return -EINVAL;
1444 }
1445 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1446 }
1447 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001448 {
1449 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1450
1451 /* If auto channel selection is configured as enable/ 1 then ignore
1452 channel set by supplicant
1453 */
1454 if ( cfg_param->apAutoChannelSelection )
1455 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301456 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1457 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001458 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1459 "%s: set channel to auto channel (0) for device mode =%d",
1460 __func__, pAdapter->device_mode);
1461 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301462 else
1463 {
1464 if(VOS_STATUS_SUCCESS !=
1465 wlan_hdd_validate_operation_channel(pAdapter,channel))
1466 {
1467 hddLog(VOS_TRACE_LEVEL_ERROR,
1468 "%s: Invalid Channel [%d] \n", __func__, channel);
1469 return -EINVAL;
1470 }
1471 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1472 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001473 }
1474 }
1475 else
1476 {
1477 hddLog(VOS_TRACE_LEVEL_FATAL,
1478 "%s: Invalid device mode failed to set valid channel", __func__);
1479 return -EINVAL;
1480 }
1481 EXIT();
1482 return 0;
1483}
1484
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301485/*
1486 * FUNCTION: wlan_hdd_select_cbmode
1487 * called by wlan_hdd_cfg80211_start_bss() and
1488 * This function selects the cbmode based on primary channel
1489 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001490VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301491{
1492 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001493 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1494 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1495
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301496 if(
1497#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001498 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1499 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301500#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001501 SapHw_mode != eSAP_DOT11_MODE_11n &&
1502 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301503 )
1504 {
1505 return VOS_STATUS_SUCCESS;
1506 }
1507
1508 if (!pConfigIni->nChannelBondingMode5GHz) {
1509 return VOS_STATUS_SUCCESS;
1510 }
1511
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001512 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301513 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1514
1515 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1516
1517#ifdef WLAN_FEATURE_11AC
1518
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001519 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1520 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301521 {
1522 if ( channel== 36 || channel == 52 || channel == 100 ||
1523 channel == 116 || channel == 149 )
1524 {
1525 smeConfig.csrConfig.channelBondingMode5GHz =
1526 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1527 }
1528 else if ( channel == 40 || channel == 56 || channel == 104 ||
1529 channel == 120 || channel == 153 )
1530 {
1531 smeConfig.csrConfig.channelBondingMode5GHz =
1532 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1533 }
1534 else if ( channel == 44 || channel == 60 || channel == 108 ||
1535 channel == 124 || channel == 157 )
1536 {
1537 smeConfig.csrConfig.channelBondingMode5GHz =
1538 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1539 }
1540 else if ( channel == 48 || channel == 64 || channel == 112 ||
1541 channel == 128 || channel == 161 )
1542 {
1543 smeConfig.csrConfig.channelBondingMode5GHz =
1544 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1545 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001546 else if ( channel == 165 )
1547 {
1548 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1549 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301550 }
1551#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001552 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1553 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301554 {
1555 if ( channel== 40 || channel == 48 || channel == 56 ||
1556 channel == 64 || channel == 104 || channel == 112 ||
1557 channel == 120 || channel == 128 || channel == 136 ||
1558 channel == 144 || channel == 153 || channel == 161 )
1559 {
1560 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1561 }
1562 else if ( channel== 36 || channel == 44 || channel == 52 ||
1563 channel == 60 || channel == 100 || channel == 108 ||
1564 channel == 116 || channel == 124 || channel == 132 ||
1565 channel == 140 || channel == 149 || channel == 157 )
1566 {
1567 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1568 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001569 else if ( channel == 165 )
1570 {
1571 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1572 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301573 }
1574 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1575
1576 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1577 return VOS_STATUS_SUCCESS;
1578}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001579
Jeff Johnson295189b2012-06-20 16:38:30 -07001580#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1581static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1582 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001583#else
1584static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1585 struct cfg80211_beacon_data *params,
1586 const u8 *ssid, size_t ssid_len,
1587 enum nl80211_hidden_ssid hidden_ssid)
1588#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001589{
1590 tsap_Config_t *pConfig;
1591 beacon_data_t *pBeacon = NULL;
1592 struct ieee80211_mgmt *pMgmt_frame;
1593 v_U8_t *pIe=NULL;
1594 v_U16_t capab_info;
1595 eCsrAuthType RSNAuthType;
1596 eCsrEncryptionType RSNEncryptType;
1597 eCsrEncryptionType mcRSNEncryptType;
1598 int status = VOS_STATUS_SUCCESS;
1599 tpWLAN_SAPEventCB pSapEventCallback;
1600 hdd_hostapd_state_t *pHostapdState;
1601 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1602 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301603 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001604 struct qc_mac_acl_entry *acl_entry = NULL;
1605 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001606 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001607
1608 ENTER();
1609
1610 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1611
1612 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1613
1614 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1615
1616 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1617
1618 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1619
1620 //channel is already set in the set_channel Call back
1621 //pConfig->channel = pCommitConfig->channel;
1622
1623 /*Protection parameter to enable or disable*/
1624 pConfig->protEnabled =
1625 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1626
1627 pConfig->dtim_period = pBeacon->dtim_period;
1628
1629 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1630 pConfig->dtim_period);
1631
1632
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001633 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001634 {
1635 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001637 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001638 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001639 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001640 pConfig->ieee80211d = 1;
1641 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1642 sme_setRegInfo(hHal, pConfig->countryCode);
1643 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001644 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001645 else
1646 {
1647 pConfig->ieee80211d = 0;
1648 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301649 /*
1650 * If auto channel is configured i.e. channel is 0,
1651 * so skip channel validation.
1652 */
1653 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1654 {
1655 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1656 {
1657 hddLog(VOS_TRACE_LEVEL_ERROR,
1658 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1659 return -EINVAL;
1660 }
1661 }
1662 else
1663 {
1664 if(1 != pHddCtx->is_dynamic_channel_range_set)
1665 {
1666 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1667 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1668 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1669 }
1670 pHddCtx->is_dynamic_channel_range_set = 0;
1671 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001673 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001674 {
1675 pConfig->ieee80211d = 0;
1676 }
1677 pConfig->authType = eSAP_AUTO_SWITCH;
1678
1679 capab_info = pMgmt_frame->u.beacon.capab_info;
1680
1681 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1682 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1683
1684 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1685
1686 /*Set wps station to configured*/
1687 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1688
1689 if(pIe)
1690 {
1691 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1692 {
1693 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1694 return -EINVAL;
1695 }
1696 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1697 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001698 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001699 /* Check 15 bit of WPS IE as it contain information for wps state
1700 * WPS state
1701 */
1702 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1703 {
1704 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1705 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1706 {
1707 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1708 }
1709 }
1710 }
1711 else
1712 {
1713 pConfig->wps_state = SAP_WPS_DISABLED;
1714 }
1715 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1716
1717 pConfig->RSNWPAReqIELength = 0;
1718 pConfig->pRSNWPAReqIE = NULL;
1719 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1720 WLAN_EID_RSN);
1721 if(pIe && pIe[1])
1722 {
1723 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1724 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1725 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1726 /* The actual processing may eventually be more extensive than
1727 * this. Right now, just consume any PMKIDs that are sent in
1728 * by the app.
1729 * */
1730 status = hdd_softap_unpackIE(
1731 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1732 &RSNEncryptType,
1733 &mcRSNEncryptType,
1734 &RSNAuthType,
1735 pConfig->pRSNWPAReqIE[1]+2,
1736 pConfig->pRSNWPAReqIE );
1737
1738 if( VOS_STATUS_SUCCESS == status )
1739 {
1740 /* Now copy over all the security attributes you have
1741 * parsed out
1742 * */
1743 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1744 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1745 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1746 = RSNEncryptType;
1747 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1748 "EncryptionType = %d mcEncryptionType = %d\n"),
1749 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1750 }
1751 }
1752
1753 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1754 pBeacon->tail, pBeacon->tail_len);
1755
1756 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1757 {
1758 if (pConfig->pRSNWPAReqIE)
1759 {
1760 /*Mixed mode WPA/WPA2*/
1761 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1762 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1763 }
1764 else
1765 {
1766 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1767 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1768 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1769 status = hdd_softap_unpackIE(
1770 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1771 &RSNEncryptType,
1772 &mcRSNEncryptType,
1773 &RSNAuthType,
1774 pConfig->pRSNWPAReqIE[1]+2,
1775 pConfig->pRSNWPAReqIE );
1776
1777 if( VOS_STATUS_SUCCESS == status )
1778 {
1779 /* Now copy over all the security attributes you have
1780 * parsed out
1781 * */
1782 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1783 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1784 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1785 = RSNEncryptType;
1786 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1787 "EncryptionType = %d mcEncryptionType = %d\n"),
1788 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1789 }
1790 }
1791 }
1792
1793 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1794
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001795#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001796 if (params->ssid != NULL)
1797 {
1798 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1799 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1800 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1801 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1802 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001803#else
1804 if (ssid != NULL)
1805 {
1806 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1807 pConfig->SSIDinfo.ssid.length = ssid_len;
1808 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1809 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1810 }
1811#endif
1812
Jeff Johnson295189b2012-06-20 16:38:30 -07001813 vos_mem_copy(pConfig->self_macaddr.bytes,
1814 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1815
1816 /* default value */
1817 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1818 pConfig->num_accept_mac = 0;
1819 pConfig->num_deny_mac = 0;
1820
1821 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1822 pBeacon->tail, pBeacon->tail_len);
1823
1824 /* pIe for black list is following form:
1825 type : 1 byte
1826 length : 1 byte
1827 OUI : 4 bytes
1828 acl type : 1 byte
1829 no of mac addr in black list: 1 byte
1830 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1831 */
1832 if ((pIe != NULL) && (pIe[1] != 0))
1833 {
1834 pConfig->SapMacaddr_acl = pIe[6];
1835 pConfig->num_deny_mac = pIe[7];
1836 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1837 pIe[6], pIe[7]);
1838 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1839 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1840 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1841 for (i = 0; i < pConfig->num_deny_mac; i++)
1842 {
1843 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1844 acl_entry++;
1845 }
1846 }
1847 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1848 pBeacon->tail, pBeacon->tail_len);
1849
1850 /* pIe for white list is following form:
1851 type : 1 byte
1852 length : 1 byte
1853 OUI : 4 bytes
1854 acl type : 1 byte
1855 no of mac addr in white list: 1 byte
1856 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1857 */
1858 if ((pIe != NULL) && (pIe[1] != 0))
1859 {
1860 pConfig->SapMacaddr_acl = pIe[6];
1861 pConfig->num_accept_mac = pIe[7];
1862 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1863 pIe[6], pIe[7]);
1864 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1865 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1866 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1867 for (i = 0; i < pConfig->num_accept_mac; i++)
1868 {
1869 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1870 acl_entry++;
1871 }
1872 }
1873 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1874
Jeff Johnsone7245742012-09-05 17:12:55 -07001875#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001876 /* Overwrite the hostapd setting for HW mode only for 11ac.
1877 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1878 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1879 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1880 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1881 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1882 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1883 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001884 {
1885 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1886 }
1887#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301888
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001889 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1890 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001891 // ht_capab is not what the name conveys,this is used for protection bitmap
1892 pConfig->ht_capab =
1893 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1894
1895 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1896 {
1897 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1898 return -EINVAL;
1899 }
1900
1901 //Uapsd Enabled Bit
1902 pConfig->UapsdEnable =
1903 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1904 //Enable OBSS protection
1905 pConfig->obssProtEnabled =
1906 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1907
1908 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1909 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1910 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1911 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1912 (int)pConfig->channel);
1913 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1914 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1915 pConfig->authType);
1916 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1917 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1918 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1919 pConfig->protEnabled, pConfig->obssProtEnabled);
1920
1921 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1922 {
1923 //Bss already started. just return.
1924 //TODO Probably it should update some beacon params.
1925 hddLog( LOGE, "Bss Already started...Ignore the request");
1926 EXIT();
1927 return 0;
1928 }
1929
1930 pConfig->persona = pHostapdAdapter->device_mode;
1931
1932 pSapEventCallback = hdd_hostapd_SAPEventCB;
1933 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1934 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1935 {
1936 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1937 return -EINVAL;
1938 }
1939
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001940 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001941 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1942
1943 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1944
1945 if (!VOS_IS_STATUS_SUCCESS(status))
1946 {
1947 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1948 ("ERROR: HDD vos wait for single_event failed!!\n"));
1949 VOS_ASSERT(0);
1950 }
1951
1952 //Succesfully started Bss update the state bit.
1953 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1954
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001955#ifdef WLAN_FEATURE_P2P_DEBUG
1956 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1957 {
1958 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1959 {
1960 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1961 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001962 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001963 }
1964 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1965 {
1966 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1967 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001968 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001969 }
1970 }
1971#endif
1972
Jeff Johnson295189b2012-06-20 16:38:30 -07001973 pHostapdState->bCommit = TRUE;
1974 EXIT();
1975
1976 return 0;
1977}
1978
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001979#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001980static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1981 struct net_device *dev,
1982 struct beacon_parameters *params)
1983{
1984 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1985 int status=VOS_STATUS_SUCCESS;
1986
1987 ENTER();
1988
1989 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1990
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001991 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1992 {
1993 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1994 "%s:LOGP in Progress. Ignore!!!", __func__);
1995 return -EAGAIN;
1996 }
1997
Jeff Johnson295189b2012-06-20 16:38:30 -07001998 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07001999 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002000 )
2001 {
2002 beacon_data_t *old,*new;
2003
2004 old = pAdapter->sessionCtx.ap.beacon;
2005
2006 if (old)
2007 return -EALREADY;
2008
2009 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2010
2011 if(status != VOS_STATUS_SUCCESS)
2012 {
2013 hddLog(VOS_TRACE_LEVEL_FATAL,
2014 "%s:Error!!! Allocating the new beacon\n",__func__);
2015 return -EINVAL;
2016 }
2017
2018 pAdapter->sessionCtx.ap.beacon = new;
2019
2020 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2021 }
2022
2023 EXIT();
2024 return status;
2025}
2026
2027static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2028 struct net_device *dev,
2029 struct beacon_parameters *params)
2030{
2031 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2032 int status=VOS_STATUS_SUCCESS;
2033
2034 ENTER();
2035
2036 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2037 __func__,pAdapter->device_mode);
2038
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002039 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2040 {
2041 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2042 "%s:LOGP in Progress. Ignore!!!", __func__);
2043 return -EAGAIN;
2044 }
2045
Jeff Johnson295189b2012-06-20 16:38:30 -07002046 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002047 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002048 )
2049 {
2050 beacon_data_t *old,*new;
2051
2052 old = pAdapter->sessionCtx.ap.beacon;
2053
2054 if (!old)
2055 return -ENOENT;
2056
2057 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2058
2059 if(status != VOS_STATUS_SUCCESS) {
2060 hddLog(VOS_TRACE_LEVEL_FATAL,
2061 "%s: Error!!! Allocating the new beacon\n",__func__);
2062 return -EINVAL;
2063 }
2064
2065 pAdapter->sessionCtx.ap.beacon = new;
2066
2067 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2068 }
2069
2070 EXIT();
2071 return status;
2072}
2073
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002074#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2075
2076#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002077static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2078 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002079#else
2080static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2081 struct net_device *dev)
2082#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002083{
2084 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002085 hdd_context_t *pHddCtx = NULL;
2086 hdd_scaninfo_t *pScanInfo = NULL;
2087 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002088 VOS_STATUS status = 0;
2089
2090 ENTER();
2091
2092 if (NULL == pAdapter)
2093 {
2094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002095 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002096 return -ENODEV;
2097 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002098 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2099 {
2100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2101 "%s:LOGP in Progress. Ignore!!!", __func__);
2102 return -EAGAIN;
2103 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002104
2105 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2106 if (NULL == pHddCtx)
2107 {
2108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002109 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002110 return -ENODEV;
2111 }
2112
2113 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2114 if (NULL == staAdapter)
2115 {
2116 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2117 if (NULL == staAdapter)
2118 {
2119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002120 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002121 return -ENODEV;
2122 }
2123 }
2124
2125 pScanInfo = &pHddCtx->scan_info;
2126
Jeff Johnson295189b2012-06-20 16:38:30 -07002127 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2128 {
2129 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2130 return -EAGAIN;
2131 }
2132
2133 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2134
2135 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2136 __func__,pAdapter->device_mode);
2137
Jeff Johnsone7245742012-09-05 17:12:55 -07002138 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2139 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002140 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002141 hdd_abort_mac_scan(staAdapter->pHddCtx);
2142 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002143 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002144 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2145 if (!status)
2146 {
2147 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002148 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002149 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002150 VOS_ASSERT(pScanInfo->mScanPending);
2151 return 0;
2152 }
2153 }
2154
Jeff Johnson295189b2012-06-20 16:38:30 -07002155 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002156 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002157 )
2158 {
2159 beacon_data_t *old;
2160
2161 old = pAdapter->sessionCtx.ap.beacon;
2162
2163 if (!old)
2164 return -ENOENT;
2165
Jeff Johnson295189b2012-06-20 16:38:30 -07002166 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002167
2168 mutex_lock(&pHddCtx->sap_lock);
2169 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2170 {
2171 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2172 {
2173 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2174
2175 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2176
2177 if (!VOS_IS_STATUS_SUCCESS(status))
2178 {
2179 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2180 ("ERROR: HDD vos wait for single_event failed!!\n"));
2181 VOS_ASSERT(0);
2182 }
2183 }
2184 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2185 }
2186 mutex_unlock(&pHddCtx->sap_lock);
2187
2188 if(status != VOS_STATUS_SUCCESS)
2189 {
2190 hddLog(VOS_TRACE_LEVEL_FATAL,
2191 "%s:Error!!! Stopping the BSS\n",__func__);
2192 return -EINVAL;
2193 }
2194
2195 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2196 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2197 ==eHAL_STATUS_FAILURE)
2198 {
2199 hddLog(LOGE,
2200 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2201 }
2202
2203 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2204 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2205 eANI_BOOLEAN_FALSE) )
2206 {
2207 hddLog(LOGE,
2208 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2209 }
2210
2211 // Reset WNI_CFG_PROBE_RSP Flags
2212 wlan_hdd_reset_prob_rspies(pAdapter);
2213
2214 pAdapter->sessionCtx.ap.beacon = NULL;
2215 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002216#ifdef WLAN_FEATURE_P2P_DEBUG
2217 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2218 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2219 {
2220 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2221 "GO got removed");
2222 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2223 }
2224#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002225 }
2226 EXIT();
2227 return status;
2228}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002229
2230#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2231
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302232static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2233 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002234 struct cfg80211_ap_settings *params)
2235{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302236 hdd_adapter_t *pAdapter;
2237 hdd_context_t *pHddCtx;
2238 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002239
2240 ENTER();
2241
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302242 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002243 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2245 "%s: Device is Null", __func__);
2246 return -ENODEV;
2247 }
2248
2249 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2250 if (NULL == pAdapter)
2251 {
2252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2253 "%s: HDD adapter is Null", __func__);
2254 return -ENODEV;
2255 }
2256
2257 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2258 {
2259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2260 "%s: HDD adapter magic is invalid", __func__);
2261 return -ENODEV;
2262 }
2263
2264 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2265 if (NULL == pHddCtx)
2266 {
2267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2268 "%s: HDD context is Null", __func__);
2269 return -ENODEV;
2270 }
2271
2272 if (pHddCtx->isLogpInProgress)
2273 {
2274 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2275 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002276 return -EAGAIN;
2277 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302278
2279 if (pHddCtx->isLoadUnloadInProgress)
2280 {
2281 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2282 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2283 return -EAGAIN;
2284 }
2285
2286 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2287 __func__, pAdapter->device_mode);
2288
2289 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002290 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002291 )
2292 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302293 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002294
2295 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302296
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002297 if (old)
2298 return -EALREADY;
2299
2300 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2301
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302302 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002303 {
2304 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302305 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002306 return -EINVAL;
2307 }
2308 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002309#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2310 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2311#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002312 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2313 params->ssid_len, params->hidden_ssid);
2314 }
2315
2316 EXIT();
2317 return status;
2318}
2319
2320
2321static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2322 struct net_device *dev,
2323 struct cfg80211_beacon_data *params)
2324{
2325 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2326 int status=VOS_STATUS_SUCCESS;
2327
2328 ENTER();
2329
2330 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2331 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002332 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2333 {
2334 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2335 return -EAGAIN;
2336 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002337
2338 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002339 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002340 )
2341 {
2342 beacon_data_t *old,*new;
2343
2344 old = pAdapter->sessionCtx.ap.beacon;
2345
2346 if (!old)
2347 return -ENOENT;
2348
2349 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2350
2351 if(status != VOS_STATUS_SUCCESS) {
2352 hddLog(VOS_TRACE_LEVEL_FATAL,
2353 "%s: Error!!! Allocating the new beacon\n",__func__);
2354 return -EINVAL;
2355 }
2356
2357 pAdapter->sessionCtx.ap.beacon = new;
2358
2359 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2360 }
2361
2362 EXIT();
2363 return status;
2364}
2365
2366#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2367
Jeff Johnson295189b2012-06-20 16:38:30 -07002368
2369static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2370 struct net_device *dev,
2371 struct bss_parameters *params)
2372{
2373 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2374
2375 ENTER();
2376
2377 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2378 __func__,pAdapter->device_mode);
2379
2380 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002381 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002382 )
2383 {
2384 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2385 * want to update this parameter */
2386 if (-1 != params->ap_isolate)
2387 {
2388 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2389 }
2390 }
2391
2392 EXIT();
2393 return 0;
2394}
2395
2396/*
2397 * FUNCTION: wlan_hdd_cfg80211_change_iface
2398 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2399 */
2400int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2401 struct net_device *ndev,
2402 enum nl80211_iftype type,
2403 u32 *flags,
2404 struct vif_params *params
2405 )
2406{
2407 struct wireless_dev *wdev;
2408 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2409 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002410 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002411 tCsrRoamProfile *pRoamProfile = NULL;
2412 eCsrRoamBssType LastBSSType;
2413 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2414 eMib_dot11DesiredBssType connectedBssType;
2415 VOS_STATUS status;
2416
2417 ENTER();
2418
2419 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2420 {
2421 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2422 return -EAGAIN;
2423 }
2424
2425 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2426 __func__, pAdapter->device_mode);
2427
2428 wdev = ndev->ieee80211_ptr;
2429
2430#ifdef WLAN_BTAMP_FEATURE
2431 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2432 (NL80211_IFTYPE_ADHOC == type)||
2433 (NL80211_IFTYPE_AP == type)||
2434 (NL80211_IFTYPE_P2P_GO == type))
2435 {
2436 pHddCtx->isAmpAllowed = VOS_FALSE;
2437 // stop AMP traffic
2438 status = WLANBAP_StopAmp();
2439 if(VOS_STATUS_SUCCESS != status )
2440 {
2441 pHddCtx->isAmpAllowed = VOS_TRUE;
2442 hddLog(VOS_TRACE_LEVEL_FATAL,
2443 "%s: Failed to stop AMP", __func__);
2444 return -EINVAL;
2445 }
2446 }
2447#endif //WLAN_BTAMP_FEATURE
2448 /* Reset the current device mode bit mask*/
2449 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2450
2451 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002452 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002453 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002454 )
2455 {
2456 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2457 pRoamProfile = &pWextState->roamProfile;
2458 LastBSSType = pRoamProfile->BSSType;
2459
2460 switch (type)
2461 {
2462 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002463 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002464 hddLog(VOS_TRACE_LEVEL_INFO,
2465 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2466 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002467#ifdef WLAN_FEATURE_11AC
2468 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2469 {
2470 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2471 }
2472#endif
2473 pRoamProfile->phyMode =
2474 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002475 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002476 //Check for sub-string p2p to confirm its a p2p interface
2477 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002478 {
2479 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2480 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2481 }
2482 else
2483 {
2484 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002486 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002487 break;
2488 case NL80211_IFTYPE_ADHOC:
2489 hddLog(VOS_TRACE_LEVEL_INFO,
2490 "%s: setting interface Type to ADHOC", __func__);
2491 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2492 pRoamProfile->phyMode =
2493 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2494 wdev->iftype = type;
2495 break;
2496
2497 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002498 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002499 {
2500 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2501 "%s: setting interface Type to %s", __func__,
2502 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2503
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002504 //Cancel any remain on channel for GO mode
2505 if (NL80211_IFTYPE_P2P_GO == type)
2506 {
2507 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2508 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002509 if (NL80211_IFTYPE_AP == type)
2510 {
2511 /* As Loading WLAN Driver one interface being created for p2p device
2512 * address. This will take one HW STA and the max number of clients
2513 * that can connect to softAP will be reduced by one. so while changing
2514 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2515 * interface as it is not required in SoftAP mode.
2516 */
2517
2518 // Get P2P Adapter
2519 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2520
2521 if (pP2pAdapter)
2522 {
2523 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2524 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2525 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2526 }
2527 }
2528
Jeff Johnson295189b2012-06-20 16:38:30 -07002529 //De-init the adapter.
2530 hdd_stop_adapter( pHddCtx, pAdapter );
2531 hdd_deinit_adapter( pHddCtx, pAdapter );
2532 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002533 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2534 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002535
2536 //Disable BMPS and IMPS if enabled
2537 //before starting Go
2538 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2539 {
2540 if(VOS_STATUS_E_FAILURE ==
2541 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2542 {
2543 //Fail to Exit BMPS
2544 VOS_ASSERT(0);
2545 }
2546 }
2547
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002548 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2549 (pConfig->apRandomBssidEnabled))
2550 {
2551 /* To meet Android requirements create a randomized
2552 MAC address of the form 02:1A:11:Fx:xx:xx */
2553 get_random_bytes(&ndev->dev_addr[3], 3);
2554 ndev->dev_addr[0] = 0x02;
2555 ndev->dev_addr[1] = 0x1A;
2556 ndev->dev_addr[2] = 0x11;
2557 ndev->dev_addr[3] |= 0xF0;
2558 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2559 VOS_MAC_ADDR_SIZE);
2560 pr_info("wlan: Generated HotSpot BSSID "
2561 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2562 ndev->dev_addr[0],
2563 ndev->dev_addr[1],
2564 ndev->dev_addr[2],
2565 ndev->dev_addr[3],
2566 ndev->dev_addr[4],
2567 ndev->dev_addr[5]);
2568 }
2569
Jeff Johnson295189b2012-06-20 16:38:30 -07002570 hdd_set_ap_ops( pAdapter->dev );
2571
2572 status = hdd_init_ap_mode(pAdapter);
2573 if(status != VOS_STATUS_SUCCESS)
2574 {
2575 hddLog(VOS_TRACE_LEVEL_FATAL,
2576 "%s: Error initializing the ap mode", __func__);
2577 return -EINVAL;
2578 }
2579 hdd_set_conparam(1);
2580
Jeff Johnson295189b2012-06-20 16:38:30 -07002581 /*interface type changed update in wiphy structure*/
2582 if(wdev)
2583 {
2584 wdev->iftype = type;
2585 pHddCtx->change_iface = type;
2586 }
2587 else
2588 {
2589 hddLog(VOS_TRACE_LEVEL_ERROR,
2590 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2591 return -EINVAL;
2592 }
2593 goto done;
2594 }
2595
2596 default:
2597 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2598 __func__);
2599 return -EOPNOTSUPP;
2600 }
2601 }
2602 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002603 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002604 )
2605 {
2606 switch(type)
2607 {
2608 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002609 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002610 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002611 hdd_stop_adapter( pHddCtx, pAdapter );
2612 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002613 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002614 //Check for sub-string p2p to confirm its a p2p interface
2615 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002616 {
2617 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2618 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2619 }
2620 else
2621 {
2622 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002623 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002624 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002625 hdd_set_conparam(0);
2626 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002627 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2628 hdd_set_station_ops( pAdapter->dev );
2629 status = hdd_init_station_mode( pAdapter );
2630 if( VOS_STATUS_SUCCESS != status )
2631 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002632 /* In case of JB, for P2P-GO, only change interface will be called,
2633 * This is the right place to enable back bmps_imps()
2634 */
2635 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002636 goto done;
2637 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002638 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002639 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002640 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2641 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002642 goto done;
2643 default:
2644 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2645 __func__);
2646 return -EOPNOTSUPP;
2647
2648 }
2649
2650 }
2651 else
2652 {
2653 return -EOPNOTSUPP;
2654 }
2655
2656
2657 if(pRoamProfile)
2658 {
2659 if ( LastBSSType != pRoamProfile->BSSType )
2660 {
2661 /*interface type changed update in wiphy structure*/
2662 wdev->iftype = type;
2663
2664 /*the BSS mode changed, We need to issue disconnect
2665 if connected or in IBSS disconnect state*/
2666 if ( hdd_connGetConnectedBssType(
2667 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2668 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2669 {
2670 /*need to issue a disconnect to CSR.*/
2671 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2672 if( eHAL_STATUS_SUCCESS ==
2673 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2674 pAdapter->sessionId,
2675 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2676 {
2677 wait_for_completion_interruptible_timeout(
2678 &pAdapter->disconnect_comp_var,
2679 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2680 }
2681 }
2682 }
2683 }
2684
2685done:
2686 /*set bitmask based on updated value*/
2687 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2688#ifdef WLAN_BTAMP_FEATURE
2689 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2690 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2691 {
2692 //we are ok to do AMP
2693 pHddCtx->isAmpAllowed = VOS_TRUE;
2694 }
2695#endif //WLAN_BTAMP_FEATURE
2696 EXIT();
2697 return 0;
2698}
2699
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002700#ifdef FEATURE_WLAN_TDLS
2701static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2702 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2703{
2704 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2705 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2706 VOS_STATUS status;
2707
2708 ENTER();
2709
2710 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
2711 {
2712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2713 "Invalid arguments");
2714 return -EINVAL;
2715 }
Hoonki Lee27511902013-03-14 18:19:06 -07002716
2717 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2718 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2719 {
2720 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2721 "%s: TDLS mode is disabled OR not enabled in FW."
2722 MAC_ADDRESS_STR " Request declined.",
2723 __func__, MAC_ADDR_ARRAY(mac));
2724 return -ENOTSUPP;
2725 }
2726
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002727 if (pHddCtx->isLogpInProgress)
2728 {
2729 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2730 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002731 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002732 return -EBUSY;
2733 }
2734
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002735 /* when self is on-going, we dont' want to change link_status */
2736 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2737 {
2738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2739 "%s: " MAC_ADDRESS_STR
2740 " TDLS setup is ongoing. Request declined.",
2741 __func__, MAC_ADDR_ARRAY(mac));
2742 return -EPERM;
2743 }
2744
2745 /* when others are on-going, we want to change link_status to idle */
2746 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002747 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2749 "%s: " MAC_ADDRESS_STR
2750 " TDLS setup is ongoing. Request declined.",
2751 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002752 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002753 }
2754
2755 /* first to check if we reached to maximum supported TDLS peer.
2756 TODO: for now, return -EPERM looks working fine,
2757 but need to check if any other errno fit into this category.*/
2758 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2759 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2761 "%s: " MAC_ADDRESS_STR
2762 " TDLS Max peer already connected. Request declined.",
2763 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002764 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002765 }
2766 else
2767 {
2768 hddTdlsPeer_t *pTdlsPeer;
2769 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2770 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
2771 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2773 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2774 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002775 return -EPERM;
2776 }
2777 }
2778
2779 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
2780
2781 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2782
2783 if (!update)
2784 {
2785 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2786 pAdapter->sessionId, mac);
2787 }
2788 else
2789 {
2790 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2791 pAdapter->sessionId, mac, StaParams);
2792 }
2793
2794 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2795 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2796
2797 if (!status)
2798 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002799 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002800 "%s: timeout waiting for tdls add station indication",
2801 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002802 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002803 }
2804 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2805 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002806 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002807 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002808 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002809 }
2810
2811 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002812
2813error:
2814 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2815 return -EPERM;
2816
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002817}
2818#endif
2819
Jeff Johnson295189b2012-06-20 16:38:30 -07002820static int wlan_hdd_change_station(struct wiphy *wiphy,
2821 struct net_device *dev,
2822 u8 *mac,
2823 struct station_parameters *params)
2824{
2825 VOS_STATUS status = VOS_STATUS_SUCCESS;
2826 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2827 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002828#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002829 tCsrStaParams StaParams = {0};
2830 u32 set;
2831 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002832#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002833 ENTER();
2834
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002835 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2836 {
2837 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2838 "%s:LOGP in Progress. Ignore!!!", __func__);
2839 return -EAGAIN;
2840 }
2841
Jeff Johnson295189b2012-06-20 16:38:30 -07002842 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2843
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002844#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002845 StaParams.capability = params->capability;
2846 StaParams.uapsd_queues = params->uapsd_queues;
2847 StaParams.max_sp = params->max_sp;
2848
2849 if (0 != params->ext_capab_len)
2850 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2851 sizeof(StaParams.extn_capability));
2852
2853 if (NULL != params->ht_capa)
2854 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2855
2856 StaParams.supported_rates_len = params->supported_rates_len;
2857
2858 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2859 * The supported_rates array , for all the structures propogating till Add Sta
2860 * to the firmware has to be modified , if the supplicant (ieee80211) is
2861 * modified to send more rates.
2862 */
2863
2864 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2865 */
2866 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2867 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2868
2869 if (0 != StaParams.supported_rates_len) {
2870 int i = 0;
2871 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2872 StaParams.supported_rates_len);
2873 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2874 "Supported Rates with Length %d", StaParams.supported_rates_len);
2875 for (i=0; i < StaParams.supported_rates_len; i++)
2876 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2877 "[%d]: %0x", i, StaParams.supported_rates[i]);
2878 }
2879
2880 if (NULL != params->vht_capa)
2881 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
2882
2883 set = params->sta_flags_set;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002884#endif
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002885
2886 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2887 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002888 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002889 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002890 {
2891 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2892 WLANTL_STA_AUTHENTICATED);
2893
2894 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002895 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002896 return -EINVAL;
2897 }
2898 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002899#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002900 else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) {
2901 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2902 if (0 != params->ext_capab_len ) {
2903 /*Define A Macro : TODO Sunil*/
2904 if ((1<<4) & StaParams.extn_capability[3]) {
2905 isBufSta = 1;
2906 }
2907 }
2908 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2909 "%s: TDLS Peer Parameters.", __func__);
2910 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2911 "uapsd_queues: %0x\n", params->uapsd_queues);
2912 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2913 "max_sp: %0x\n", params->max_sp);
2914 if (params->ht_capa) {
2915 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2916 "ht_capa->cap_info: %0x\n", params->ht_capa->cap_info);
2917 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2918 "ht_capa->ampdu_params_info: %0x\n",
2919 params->ht_capa->ampdu_params_info);
2920 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2921 "ht_capa->extended_capabilities: %0x\n",
2922 params->ht_capa->extended_ht_cap_info);
2923 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2924 "ht_capa->tx_BF_cap_info: %0x\n",
2925 params->ht_capa->tx_BF_cap_info);
2926 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2927 "ht_capa->antenna_selection_info: %0x\n",
2928 params->ht_capa->antenna_selection_info);
2929 }
2930 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2931 "params->capability: %0x\n",params->capability);
2932 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2933 "params->ext_capab_len: %0x\n",params->ext_capab_len);
2934 if (0 != params->ext_capab_len )
2935 {
2936 int i =0;
2937 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2938 "Extended capabilities:");
2939 for (i=0; i < params->ext_capab_len; i++)
2940 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2941 "[%d]: %0x", i, params->ext_capab[i]);
2942 }
2943 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
2944 // params->max_sp, isBufSta);
2945 if (VOS_STATUS_SUCCESS != status) {
2946 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2947 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
2948 return -EINVAL;
2949 }
2950 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2951 "ht_capa->cap_info: %0x\n", StaParams.HTCap.capInfo);
2952 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
2953
2954 if (VOS_STATUS_SUCCESS != status) {
2955 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2956 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
2957 return -EINVAL;
2958 }
2959 }
2960 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002961#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002962
Jeff Johnsone7245742012-09-05 17:12:55 -07002963 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002964 return status;
2965}
2966
2967/*
2968 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2969 * This function is used to get peer station index in IBSS mode
2970 */
2971static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2972{
2973 u8 idx = 0;
2974 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2975 ENTER();
2976 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2977 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2978 {
2979 if ( (0 !=
2980 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2981 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2982 temp, VOS_MAC_ADDR_SIZE)
2983 )
2984 {
2985 return idx;
2986 }
2987 }
2988 return idx;
2989}
2990
2991
2992/*
2993 * FUNCTION: wlan_hdd_cfg80211_add_key
2994 * This function is used to initialize the key information
2995 */
2996#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2997static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2998 struct net_device *ndev,
2999 u8 key_index, bool pairwise,
3000 const u8 *mac_addr,
3001 struct key_params *params
3002 )
3003#else
3004static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
3005 struct net_device *ndev,
3006 u8 key_index, const u8 *mac_addr,
3007 struct key_params *params
3008 )
3009#endif
3010{
3011 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3012 tCsrRoamSetKey setKey;
3013 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3014 int status = 0;
3015 v_U32_t roamId= 0xFF;
3016 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3017 hdd_hostapd_state_t *pHostapdState;
3018 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003019 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003020
3021 ENTER();
3022
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003023 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3024 {
3025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3026 "%s:LOGP in Progress. Ignore!!!", __func__);
3027 return -EAGAIN;
3028 }
3029
Jeff Johnson295189b2012-06-20 16:38:30 -07003030 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3031 __func__,pAdapter->device_mode);
3032
3033 if (CSR_MAX_NUM_KEY <= key_index)
3034 {
3035 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3036 key_index);
3037
3038 return -EINVAL;
3039 }
3040
3041 hddLog(VOS_TRACE_LEVEL_INFO,
3042 "%s: called with key index = %d & key length %d",
3043 __func__, key_index, params->key_len);
3044
3045 /*extract key idx, key len and key*/
3046 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3047 setKey.keyId = key_index;
3048 setKey.keyLength = params->key_len;
3049 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3050
3051 switch (params->cipher)
3052 {
3053 case WLAN_CIPHER_SUITE_WEP40:
3054 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3055 break;
3056
3057 case WLAN_CIPHER_SUITE_WEP104:
3058 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3059 break;
3060
3061 case WLAN_CIPHER_SUITE_TKIP:
3062 {
3063 u8 *pKey = &setKey.Key[0];
3064 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3065
3066 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3067
3068 /*Supplicant sends the 32bytes key in this order
3069
3070 |--------------|----------|----------|
3071 | Tk1 |TX-MIC | RX Mic |
3072 |--------------|----------|----------|
3073 <---16bytes---><--8bytes--><--8bytes-->
3074
3075 */
3076 /*Sme expects the 32 bytes key to be in the below order
3077
3078 |--------------|----------|----------|
3079 | Tk1 |RX-MIC | TX Mic |
3080 |--------------|----------|----------|
3081 <---16bytes---><--8bytes--><--8bytes-->
3082 */
3083 /* Copy the Temporal Key 1 (TK1) */
3084 vos_mem_copy(pKey, params->key,16);
3085
3086 /*Copy the rx mic first*/
3087 vos_mem_copy(&pKey[16],&params->key[24],8);
3088
3089 /*Copy the tx mic */
3090 vos_mem_copy(&pKey[24],&params->key[16],8);
3091
3092
3093 break;
3094 }
3095
3096 case WLAN_CIPHER_SUITE_CCMP:
3097 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3098 break;
3099
3100#ifdef FEATURE_WLAN_WAPI
3101 case WLAN_CIPHER_SUITE_SMS4:
3102 {
3103 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3104 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3105 params->key, params->key_len);
3106 return 0;
3107 }
3108#endif
3109#ifdef FEATURE_WLAN_CCX
3110 case WLAN_CIPHER_SUITE_KRK:
3111 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3112 break;
3113#endif
3114 default:
3115 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3116 __func__, params->cipher);
3117 return -EOPNOTSUPP;
3118 }
3119
3120 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3121 __func__, setKey.encType);
3122
3123
3124
3125 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003126 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003127 )
3128 {
3129
3130
3131 if (
3132#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3133 (!pairwise)
3134#else
3135 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3136#endif
3137 )
3138 {
3139 /* set group key*/
3140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003141 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003142 __func__, __LINE__);
3143 setKey.keyDirection = eSIR_RX_ONLY;
3144 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3145 }
3146 else
3147 {
3148 /* set pairwise key*/
3149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3150 "%s- %d: setting pairwise key",
3151 __func__, __LINE__);
3152 setKey.keyDirection = eSIR_TX_RX;
3153 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3154 }
3155
3156 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3157 if( pHostapdState->bssState == BSS_START )
3158 {
3159 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3160
3161 if ( status != eHAL_STATUS_SUCCESS )
3162 {
3163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3164 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3165 __LINE__, status );
3166 }
3167 }
3168
3169 /* Saving WEP keys */
3170 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3171 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3172 {
3173 //Save the wep key in ap context. Issue setkey after the BSS is started.
3174 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3175 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3176 }
3177 else
3178 {
3179 //Save the key in ap context. Issue setkey after the BSS is started.
3180 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3181 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3182 }
3183 }
3184 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003185 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003186 )
3187 {
3188 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3189 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3190
3191 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3192
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003193 pWextState->roamProfile.Keys.defaultIndex = key_index;
3194
3195
Jeff Johnson295189b2012-06-20 16:38:30 -07003196 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
3197 params->key, params->key_len);
3198
3199 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3200
3201 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3202 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3203 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3204 )
3205 &&
3206 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3207 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3208 )
3209 )
3210 {
3211 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3212 * interface, copy bssid for pairwise key and group macaddr for
3213 * group key initialization*/
3214
3215 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3216
3217 pWextState->roamProfile.negotiatedUCEncryptionType =
3218 pHddStaCtx->conn_info.ucEncryptionType =
3219 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3220 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3221 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3222
3223
3224 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3225 "%s: Negotiated encryption type %d", __func__,
3226 pWextState->roamProfile.negotiatedUCEncryptionType);
3227
3228 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3229 &pWextState->roamProfile, true);
3230 setKey.keyLength = 0;
3231 setKey.keyDirection = eSIR_TX_RX;
3232
3233#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3234 if (pairwise)
3235 {
3236#endif
3237 if (mac_addr)
3238 {
3239 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3240 }
3241 else
3242 {
3243 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3244 * and peerMacAddress in case of IBSS*/
3245 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3246 {
3247 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3248 if (HDD_MAX_NUM_IBSS_STA != staidx)
3249 {
3250 vos_mem_copy(setKey.peerMac,
3251 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3252 WNI_CFG_BSSID_LEN);
3253
3254 }
3255 else
3256 {
3257 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3258 __func__);
3259 return -EOPNOTSUPP;
3260 }
3261 }
3262 else
3263 {
3264 vos_mem_copy(setKey.peerMac,
3265 &pHddStaCtx->conn_info.bssId[0],
3266 WNI_CFG_BSSID_LEN);
3267 }
3268 }
3269#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3270 }
3271 else
3272 {
3273 /* set group key*/
3274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3275 "%s- %d: setting Group key",
3276 __func__, __LINE__);
3277 setKey.keyDirection = eSIR_RX_ONLY;
3278 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3279 }
3280#endif
3281 }
3282 else if (
3283#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3284 (!pairwise)
3285#else
3286 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3287#endif
3288 )
3289 {
3290 /* set group key*/
3291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3292 "%s- %d: setting Group key",
3293 __func__, __LINE__);
3294 setKey.keyDirection = eSIR_RX_ONLY;
3295 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3296 }
3297 else
3298 {
3299 /* set pairwise key*/
3300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3301 "%s- %d: setting pairwise key",
3302 __func__, __LINE__);
3303 setKey.keyDirection = eSIR_TX_RX;
3304 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3305 }
3306
3307 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3308 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3309 __func__, setKey.peerMac[0], setKey.peerMac[1],
3310 setKey.peerMac[2], setKey.peerMac[3],
3311 setKey.peerMac[4], setKey.peerMac[5],
3312 setKey.keyDirection);
3313
3314 vos_status = wlan_hdd_check_ula_done(pAdapter);
3315
3316 if ( vos_status != VOS_STATUS_SUCCESS )
3317 {
3318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3319 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3320 __LINE__, vos_status );
3321
3322 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3323
3324 return -EINVAL;
3325
3326 }
3327
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003328#ifdef WLAN_FEATURE_VOWIFI_11R
3329 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3330 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003331 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303332 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003333 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303334 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003335 }
3336#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003337
3338 /* issue set key request to SME*/
3339 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3340 pAdapter->sessionId, &setKey, &roamId );
3341
3342 if ( 0 != status )
3343 {
3344 hddLog(VOS_TRACE_LEVEL_ERROR,
3345 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3346 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3347 return -EINVAL;
3348 }
3349
3350
3351 /* in case of IBSS as there was no information available about WEP keys during
3352 * IBSS join, group key intialized with NULL key, so re-initialize group key
3353 * with correct value*/
3354 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3355 !( ( IW_AUTH_KEY_MGMT_802_1X
3356 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3357 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3358 )
3359 &&
3360 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3361 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3362 )
3363 )
3364 {
3365 setKey.keyDirection = eSIR_RX_ONLY;
3366 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3367
3368 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3369 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3370 __func__, setKey.peerMac[0], setKey.peerMac[1],
3371 setKey.peerMac[2], setKey.peerMac[3],
3372 setKey.peerMac[4], setKey.peerMac[5],
3373 setKey.keyDirection);
3374
3375 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3376 pAdapter->sessionId, &setKey, &roamId );
3377
3378 if ( 0 != status )
3379 {
3380 hddLog(VOS_TRACE_LEVEL_ERROR,
3381 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3382 __func__, status);
3383 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3384 return -EINVAL;
3385 }
3386 }
3387 }
3388
3389 return 0;
3390}
3391
3392/*
3393 * FUNCTION: wlan_hdd_cfg80211_get_key
3394 * This function is used to get the key information
3395 */
3396#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3397static int wlan_hdd_cfg80211_get_key(
3398 struct wiphy *wiphy,
3399 struct net_device *ndev,
3400 u8 key_index, bool pairwise,
3401 const u8 *mac_addr, void *cookie,
3402 void (*callback)(void *cookie, struct key_params*)
3403 )
3404#else
3405static int wlan_hdd_cfg80211_get_key(
3406 struct wiphy *wiphy,
3407 struct net_device *ndev,
3408 u8 key_index, const u8 *mac_addr, void *cookie,
3409 void (*callback)(void *cookie, struct key_params*)
3410 )
3411#endif
3412{
3413 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3414 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3415 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3416 struct key_params params;
3417
3418 ENTER();
3419
3420 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3421 __func__,pAdapter->device_mode);
3422
3423 memset(&params, 0, sizeof(params));
3424
3425 if (CSR_MAX_NUM_KEY <= key_index)
3426 {
3427 return -EINVAL;
3428 }
3429
3430 switch(pRoamProfile->EncryptionType.encryptionType[0])
3431 {
3432 case eCSR_ENCRYPT_TYPE_NONE:
3433 params.cipher = IW_AUTH_CIPHER_NONE;
3434 break;
3435
3436 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3437 case eCSR_ENCRYPT_TYPE_WEP40:
3438 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3439 break;
3440
3441 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3442 case eCSR_ENCRYPT_TYPE_WEP104:
3443 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3444 break;
3445
3446 case eCSR_ENCRYPT_TYPE_TKIP:
3447 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3448 break;
3449
3450 case eCSR_ENCRYPT_TYPE_AES:
3451 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3452 break;
3453
3454 default:
3455 params.cipher = IW_AUTH_CIPHER_NONE;
3456 break;
3457 }
3458
3459 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3460 params.seq_len = 0;
3461 params.seq = NULL;
3462 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3463 callback(cookie, &params);
3464 return 0;
3465}
3466
3467/*
3468 * FUNCTION: wlan_hdd_cfg80211_del_key
3469 * This function is used to delete the key information
3470 */
3471#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3472static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3473 struct net_device *ndev,
3474 u8 key_index,
3475 bool pairwise,
3476 const u8 *mac_addr
3477 )
3478#else
3479static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3480 struct net_device *ndev,
3481 u8 key_index,
3482 const u8 *mac_addr
3483 )
3484#endif
3485{
3486 int status = 0;
3487
3488 //This code needs to be revisited. There is sme_removeKey API, we should
3489 //plan to use that. After the change to use correct index in setkey,
3490 //it is observed that this is invalidating peer
3491 //key index whenever re-key is done. This is affecting data link.
3492 //It should be ok to ignore del_key.
3493#if 0
3494 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3495 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3496 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3497 tCsrRoamSetKey setKey;
3498 v_U32_t roamId= 0xFF;
3499
3500 ENTER();
3501
3502 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3503 __func__,pAdapter->device_mode);
3504
3505 if (CSR_MAX_NUM_KEY <= key_index)
3506 {
3507 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3508 key_index);
3509
3510 return -EINVAL;
3511 }
3512
3513 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3514 setKey.keyId = key_index;
3515
3516 if (mac_addr)
3517 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3518 else
3519 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3520
3521 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3522
3523 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003524 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003525 )
3526 {
3527
3528 hdd_hostapd_state_t *pHostapdState =
3529 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3530 if( pHostapdState->bssState == BSS_START)
3531 {
3532 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3533
3534 if ( status != eHAL_STATUS_SUCCESS )
3535 {
3536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3537 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3538 __LINE__, status );
3539 }
3540 }
3541 }
3542 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003543 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003544 )
3545 {
3546 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3547
3548 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3549
3550 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3551 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3552 __func__, setKey.peerMac[0], setKey.peerMac[1],
3553 setKey.peerMac[2], setKey.peerMac[3],
3554 setKey.peerMac[4], setKey.peerMac[5]);
3555 if(pAdapter->sessionCtx.station.conn_info.connState ==
3556 eConnectionState_Associated)
3557 {
3558 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3559 pAdapter->sessionId, &setKey, &roamId );
3560
3561 if ( 0 != status )
3562 {
3563 hddLog(VOS_TRACE_LEVEL_ERROR,
3564 "%s: sme_RoamSetKey failure, returned %d",
3565 __func__, status);
3566 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3567 return -EINVAL;
3568 }
3569 }
3570 }
3571#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003572 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003573 return status;
3574}
3575
3576/*
3577 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3578 * This function is used to set the default tx key index
3579 */
3580#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3581static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3582 struct net_device *ndev,
3583 u8 key_index,
3584 bool unicast, bool multicast)
3585#else
3586static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3587 struct net_device *ndev,
3588 u8 key_index)
3589#endif
3590{
3591 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3592 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3593 int status = 0;
3594 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3595
3596 ENTER();
3597
3598 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3599 __func__,pAdapter->device_mode, key_index);
3600
3601 if (CSR_MAX_NUM_KEY <= key_index)
3602 {
3603 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3604 key_index);
3605
3606 return -EINVAL;
3607 }
3608
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003609 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3610 {
3611 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3612 "%s:LOGP in Progress. Ignore!!!", __func__);
3613 return -EAGAIN;
3614 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003615
3616 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003617 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003618 )
3619 {
3620 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3621 (eCSR_ENCRYPT_TYPE_TKIP !=
3622 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3623 (eCSR_ENCRYPT_TYPE_AES !=
3624 pWextState->roamProfile.EncryptionType.encryptionType[0])
3625 )
3626 {
3627 /* if default key index is not same as previous one,
3628 * then update the default key index */
3629
3630 tCsrRoamSetKey setKey;
3631 v_U32_t roamId= 0xFF;
3632 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3633
3634 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3635 __func__, key_index);
3636
3637 Keys->defaultIndex = (u8)key_index;
3638 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3639 setKey.keyId = key_index;
3640 setKey.keyLength = Keys->KeyLength[key_index];
3641
3642 vos_mem_copy(&setKey.Key[0],
3643 &Keys->KeyMaterial[key_index][0],
3644 Keys->KeyLength[key_index]);
3645
3646 setKey.keyDirection = eSIR_TX_ONLY;
3647
3648 vos_mem_copy(setKey.peerMac,
3649 &pHddStaCtx->conn_info.bssId[0],
3650 WNI_CFG_BSSID_LEN);
3651
3652 setKey.encType =
3653 pWextState->roamProfile.EncryptionType.encryptionType[0];
3654
3655 /* issue set key request */
3656 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3657 pAdapter->sessionId, &setKey, &roamId );
3658
3659 if ( 0 != status )
3660 {
3661 hddLog(VOS_TRACE_LEVEL_ERROR,
3662 "%s: sme_RoamSetKey failed, returned %d", __func__,
3663 status);
3664 return -EINVAL;
3665 }
3666 }
3667 }
3668
3669 /* In SoftAp mode setting key direction for default mode */
3670 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3671 {
3672 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3673 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3674 (eCSR_ENCRYPT_TYPE_AES !=
3675 pWextState->roamProfile.EncryptionType.encryptionType[0])
3676 )
3677 {
3678 /* Saving key direction for default key index to TX default */
3679 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3680 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3681 }
3682 }
3683
3684 return status;
3685}
3686
Jeff Johnson295189b2012-06-20 16:38:30 -07003687/*
3688 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3689 * This function is used to inform the BSS details to nl80211 interface.
3690 */
3691static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3692 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3693{
3694 struct net_device *dev = pAdapter->dev;
3695 struct wireless_dev *wdev = dev->ieee80211_ptr;
3696 struct wiphy *wiphy = wdev->wiphy;
3697 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3698 int chan_no;
3699 int ie_length;
3700 const char *ie;
3701 unsigned int freq;
3702 struct ieee80211_channel *chan;
3703 int rssi = 0;
3704 struct cfg80211_bss *bss = NULL;
3705
3706 ENTER();
3707
3708 if( NULL == pBssDesc )
3709 {
3710 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3711 return bss;
3712 }
3713
3714 chan_no = pBssDesc->channelId;
3715 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3716 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3717
3718 if( NULL == ie )
3719 {
3720 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3721 return bss;
3722 }
3723
3724#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3725 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3726 {
3727 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3728 }
3729 else
3730 {
3731 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3732 }
3733#else
3734 freq = ieee80211_channel_to_frequency(chan_no);
3735#endif
3736
3737 chan = __ieee80211_get_channel(wiphy, freq);
3738
3739 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3740 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3741 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3742 if (bss == NULL)
3743 {
3744 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3745
3746 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3747 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3748 pBssDesc->capabilityInfo,
3749 pBssDesc->beaconInterval, ie, ie_length,
3750 rssi, GFP_KERNEL ));
3751}
3752 else
3753 {
3754 return bss;
3755 }
3756}
3757
3758
3759
3760/*
3761 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3762 * This function is used to inform the BSS details to nl80211 interface.
3763 */
3764struct cfg80211_bss*
3765wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3766 tSirBssDescription *bss_desc
3767 )
3768{
3769 /*
3770 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3771 already exists in bss data base of cfg80211 for that particular BSS ID.
3772 Using cfg80211_inform_bss_frame to update the bss entry instead of
3773 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3774 now there is no possibility to get the mgmt(probe response) frame from PE,
3775 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3776 cfg80211_inform_bss_frame.
3777 */
3778 struct net_device *dev = pAdapter->dev;
3779 struct wireless_dev *wdev = dev->ieee80211_ptr;
3780 struct wiphy *wiphy = wdev->wiphy;
3781 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003782#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3783 qcom_ie_age *qie_age = NULL;
3784 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3785#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003786 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003787#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003788 const char *ie =
3789 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3790 unsigned int freq;
3791 struct ieee80211_channel *chan;
3792 struct ieee80211_mgmt *mgmt =
3793 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3794 struct cfg80211_bss *bss_status = NULL;
3795 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3796 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003797#ifdef WLAN_OPEN_SOURCE
3798 struct timespec ts;
3799#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003800
3801 ENTER();
3802
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003803 if (!mgmt)
3804 return NULL;
3805
Jeff Johnson295189b2012-06-20 16:38:30 -07003806 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003807
3808#ifdef WLAN_OPEN_SOURCE
3809 /* Android does not want the timestamp from the frame.
3810 Instead it wants a monotonic increasing value */
3811 get_monotonic_boottime(&ts);
3812 mgmt->u.probe_resp.timestamp =
3813 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3814#else
3815 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003816 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3817 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003818
3819#endif
3820
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3822 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003823
3824#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3825 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3826 /* Assuming this is the last IE, copy at the end */
3827 ie_length -=sizeof(qcom_ie_age);
3828 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3829 qie_age->element_id = QCOM_VENDOR_IE_ID;
3830 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3831 qie_age->oui_1 = QCOM_OUI1;
3832 qie_age->oui_2 = QCOM_OUI2;
3833 qie_age->oui_3 = QCOM_OUI3;
3834 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3835 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3836#endif
3837
Jeff Johnson295189b2012-06-20 16:38:30 -07003838 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3839
3840 mgmt->frame_control |=
3841 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3842
3843#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3844 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3845 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3846 {
3847 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3848 }
3849 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3850 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3851
3852 {
3853 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3854 }
3855 else
3856 {
3857 kfree(mgmt);
3858 return NULL;
3859 }
3860#else
3861 freq = ieee80211_channel_to_frequency(chan_no);
3862#endif
3863 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003864 /*when the band is changed on the fly using the GUI, three things are done
3865 * 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)
3866 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3867 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3868 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3869 * and discards the channels correponding to previous band and calls back with zero bss results.
3870 * 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
3871 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3872 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3873 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3874 * So drop the bss and continue to next bss.
3875 */
3876 if(chan == NULL)
3877 {
3878 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3879 return NULL;
3880 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003881 /*To keep the rssi icon of the connected AP in the scan window
3882 *and the rssi icon of the wireless networks in sync
3883 * */
3884 if (( eConnectionState_Associated ==
3885 pAdapter->sessionCtx.station.conn_info.connState ) &&
3886 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3887 pAdapter->sessionCtx.station.conn_info.bssId,
3888 WNI_CFG_BSSID_LEN)))
3889 {
3890 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3891 rssi = (pAdapter->rssi * 100);
3892 }
3893 else
3894 {
3895 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3896 }
3897
3898 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3899 frame_len, rssi, GFP_KERNEL);
3900 kfree(mgmt);
3901 return bss_status;
3902}
3903
3904/*
3905 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3906 * This function is used to update the BSS data base of CFG8011
3907 */
3908struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3909 tCsrRoamInfo *pRoamInfo
3910 )
3911{
3912 tCsrRoamConnectedProfile roamProfile;
3913 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3914 struct cfg80211_bss *bss = NULL;
3915
3916 ENTER();
3917
3918 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3919 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3920
3921 if (NULL != roamProfile.pBssDesc)
3922 {
3923 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3924 &roamProfile);
3925
3926 if (NULL == bss)
3927 {
3928 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3929 __func__);
3930 }
3931
3932 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3933 }
3934 else
3935 {
3936 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3937 __func__);
3938 }
3939 return bss;
3940}
3941
3942/*
3943 * FUNCTION: wlan_hdd_cfg80211_update_bss
3944 */
3945static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3946 hdd_adapter_t *pAdapter
3947 )
3948{
3949 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3950 tCsrScanResultInfo *pScanResult;
3951 eHalStatus status = 0;
3952 tScanResultHandle pResult;
3953 struct cfg80211_bss *bss_status = NULL;
3954
3955 ENTER();
3956
3957 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3958 {
3959 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3960 return -EAGAIN;
3961 }
3962
3963 /*
3964 * start getting scan results and populate cgf80211 BSS database
3965 */
3966 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3967
3968 /* no scan results */
3969 if (NULL == pResult)
3970 {
3971 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3972 return status;
3973 }
3974
3975 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3976
3977 while (pScanResult)
3978 {
3979 /*
3980 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3981 * entry already exists in bss data base of cfg80211 for that
3982 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3983 * bss entry instead of cfg80211_inform_bss, But this call expects
3984 * mgmt packet as input. As of now there is no possibility to get
3985 * the mgmt(probe response) frame from PE, converting bss_desc to
3986 * ieee80211_mgmt(probe response) and passing to c
3987 * fg80211_inform_bss_frame.
3988 * */
3989
3990 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3991 &pScanResult->BssDescriptor);
3992
3993
3994 if (NULL == bss_status)
3995 {
3996 hddLog(VOS_TRACE_LEVEL_INFO,
3997 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3998 }
3999 else
4000 {
4001 cfg80211_put_bss(bss_status);
4002 }
4003
4004 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4005 }
4006
4007 sme_ScanResultPurge(hHal, pResult);
4008
4009 return 0;
4010}
4011
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004012void
4013hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4014{
4015 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004016 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4017 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4018 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004019} /****** end hddPrintMacAddr() ******/
4020
4021void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004022hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004023{
4024 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004025 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4026 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4027 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4028 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004029} /****** end hddPrintPmkId() ******/
4030
4031//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4032//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4033
4034//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4035//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4036
4037#define dump_bssid(bssid) \
4038 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004039 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4040 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4041 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004042 }
4043
4044#define dump_pmkid(pMac, pmkid) \
4045 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004046 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4047 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4048 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004049 }
4050
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004051#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004052/*
4053 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4054 * This function is used to notify the supplicant of a new PMKSA candidate.
4055 */
4056int wlan_hdd_cfg80211_pmksa_candidate_notify(
4057 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4058 int index, bool preauth )
4059{
Jeff Johnsone7245742012-09-05 17:12:55 -07004060#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004061 struct net_device *dev = pAdapter->dev;
4062
4063 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004064 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004065
4066 if( NULL == pRoamInfo )
4067 {
4068 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4069 return -EINVAL;
4070 }
4071
4072 dump_bssid(pRoamInfo->bssid);
4073 cfg80211_pmksa_candidate_notify(dev, index,
4074 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07004075#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004076 return 0;
4077}
4078#endif //FEATURE_WLAN_LFR
4079
Jeff Johnson295189b2012-06-20 16:38:30 -07004080/*
4081 * FUNCTION: hdd_cfg80211_scan_done_callback
4082 * scanning callback function, called after finishing scan
4083 *
4084 */
4085static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4086 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4087{
4088 struct net_device *dev = (struct net_device *) pContext;
4089 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4090 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004091 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4092 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004093 struct cfg80211_scan_request *req = NULL;
4094 int ret = 0;
4095
4096 ENTER();
4097
4098 hddLog(VOS_TRACE_LEVEL_INFO,
4099 "%s called with halHandle = %p, pContext = %p,"
4100 "scanID = %d, returned status = %d\n",
4101 __func__, halHandle, pContext, (int) scanId, (int) status);
4102
4103 //Block on scan req completion variable. Can't wait forever though.
4104 ret = wait_for_completion_interruptible_timeout(
4105 &pScanInfo->scan_req_completion_event,
4106 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4107 if (!ret)
4108 {
4109 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004110 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004111 }
4112
4113 if(pScanInfo->mScanPending != VOS_TRUE)
4114 {
4115 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004116 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004117 }
4118
4119 /* Check the scanId */
4120 if (pScanInfo->scanId != scanId)
4121 {
4122 hddLog(VOS_TRACE_LEVEL_INFO,
4123 "%s called with mismatched scanId pScanInfo->scanId = %d "
4124 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4125 (int) scanId);
4126 }
4127
Jeff Johnson295189b2012-06-20 16:38:30 -07004128 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4129 pAdapter);
4130
4131 if (0 > ret)
4132 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4133
4134
4135 /* If any client wait scan result through WEXT
4136 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004137 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004138 {
4139 /* The other scan request waiting for current scan finish
4140 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004141 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004142 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004143 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004144 }
4145 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004146 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 {
4148 struct net_device *dev = pAdapter->dev;
4149 union iwreq_data wrqu;
4150 int we_event;
4151 char *msg;
4152
4153 memset(&wrqu, '\0', sizeof(wrqu));
4154 we_event = SIOCGIWSCAN;
4155 msg = NULL;
4156 wireless_send_event(dev, we_event, &wrqu, msg);
4157 }
4158 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004159 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004160
4161 /* Get the Scan Req */
4162 req = pAdapter->request;
4163
4164 if (!req)
4165 {
4166 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004167 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004168 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004169 }
4170
4171 /*
4172 * setting up 0, just in case.
4173 */
4174 req->n_ssids = 0;
4175 req->n_channels = 0;
4176 req->ie = 0;
4177
Jeff Johnson295189b2012-06-20 16:38:30 -07004178 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004179 /* Scan is no longer pending */
4180 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004181
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004182 /*
4183 * cfg80211_scan_done informing NL80211 about completion
4184 * of scanning
4185 */
4186 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004187 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004188
Jeff Johnsone7245742012-09-05 17:12:55 -07004189allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004190 /* release the wake lock at the end of the scan*/
4191 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004192
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004193 /* Acquire wakelock to handle the case where APP's tries to suspend
4194 * immediatly after the driver gets connect request(i.e after scan)
4195 * from supplicant, this result in app's is suspending and not able
4196 * to process the connect request to AP */
4197 hdd_allow_suspend_timeout(100);
4198
Jeff Johnson295189b2012-06-20 16:38:30 -07004199 EXIT();
4200 return 0;
4201}
4202
4203/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004204 * FUNCTION: hdd_isScanAllowed
4205 * Go through each adapter and check if scan allowed
4206 *
4207 */
4208v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4209{
4210 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4211 hdd_station_ctx_t *pHddStaCtx = NULL;
4212 hdd_adapter_t *pAdapter = NULL;
4213 VOS_STATUS status = 0;
4214 v_U8_t staId = 0;
4215 v_U8_t *staMac = NULL;
4216
4217 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4218
4219 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4220 {
4221 pAdapter = pAdapterNode->pAdapter;
4222
4223 if( pAdapter )
4224 {
4225 hddLog(VOS_TRACE_LEVEL_INFO,
4226 "%s: Adapter with device mode %d exists",
4227 __func__, pAdapter->device_mode);
4228 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4229 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4230 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4231 {
4232 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4233 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4234 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4235 {
4236 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4237 hddLog(VOS_TRACE_LEVEL_ERROR,
4238 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4239 "middle of WPS/EAPOL exchange.", __func__,
4240 staMac[0], staMac[1], staMac[2],
4241 staMac[3], staMac[4], staMac[5]);
4242 return VOS_FALSE;
4243 }
4244 }
4245 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4246 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4247 {
4248 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4249 {
4250 if ((pAdapter->aStaInfo[staId].isUsed) &&
4251 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4252 {
4253 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4254
4255 hddLog(VOS_TRACE_LEVEL_ERROR,
4256 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4257 "middle of WPS/EAPOL exchange.", __func__,
4258 staMac[0], staMac[1], staMac[2],
4259 staMac[3], staMac[4], staMac[5]);
4260 return VOS_FALSE;
4261 }
4262 }
4263 }
4264 }
4265 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4266 pAdapterNode = pNext;
4267 }
4268 hddLog(VOS_TRACE_LEVEL_INFO,
4269 "%s: Scan allowed", __func__);
4270 return VOS_TRUE;
4271}
4272
4273/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004274 * FUNCTION: wlan_hdd_cfg80211_scan
4275 * this scan respond to scan trigger and update cfg80211 scan database
4276 * later, scan dump command can be used to recieve scan results
4277 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004278int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4279#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4280 struct net_device *dev,
4281#endif
4282 struct cfg80211_scan_request *request)
4283{
4284#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4285 struct net_device *dev = request->wdev->netdev;
4286#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004287 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4288 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4289 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4290 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4291 tCsrScanRequest scanRequest;
4292 tANI_U8 *channelList = NULL, i;
4293 v_U32_t scanId = 0;
4294 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004295 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004296 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004297
4298 ENTER();
4299
4300 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4301 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004302
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004303 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004304 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004305 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004306 {
4307 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004308 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4309 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004310 return -EBUSY;
4311 }
4312
Jeff Johnson295189b2012-06-20 16:38:30 -07004313#ifdef WLAN_BTAMP_FEATURE
4314 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004315 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004316 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004317 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004318 "%s: No scanning when AMP is on", __func__);
4319 return -EOPNOTSUPP;
4320 }
4321#endif
4322 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004323 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004324 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004325 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004326 "%s: Not scanning on device_mode = %d",
4327 __func__, pAdapter->device_mode);
4328 return -EOPNOTSUPP;
4329 }
4330
4331 if (TRUE == pScanInfo->mScanPending)
4332 {
4333 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004334 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004335 }
4336
4337 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4338 {
4339 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4340 "%s:LOGP in Progress. Ignore!!!", __func__);
4341 return -EAGAIN;
4342 }
4343
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004344 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4345 {
4346 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4347 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4348 return -EAGAIN;
4349 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004350 //Don't Allow Scan and return busy if Remain On
4351 //Channel and action frame is pending
4352 //Otherwise Cancel Remain On Channel and allow Scan
4353 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004354 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004355 {
4356 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4357 return -EBUSY;
4358 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004359#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004360 if (wlan_hdd_tdlsConnectedPeers(pAdapter))
Hoonki Lee93e67ff2013-03-19 15:49:25 -07004361 {
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004362 tANI_U8 staIdx;
4363
4364 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
4365 {
4366 if (pHddCtx->tdlsConnInfo[staIdx].staId)
4367 {
4368 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4369 ("scan: indicate TDLS teadown (staId %d)"), pHddCtx->tdlsConnInfo[staIdx].staId);
4370 }
4371#ifdef CONFIG_TDLS_IMPLICIT
4372 cfg80211_tdls_oper_request(pAdapter->dev,
4373 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes,
4374 NL80211_TDLS_TEARDOWN,
4375 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
4376 GFP_KERNEL);
4377#endif
4378 }
4379 return -EBUSY;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004380 }
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004381
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004382#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004383
Jeff Johnson295189b2012-06-20 16:38:30 -07004384 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4385 {
4386 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004387 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004388 return -EAGAIN;
4389 }
4390 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4391 {
4392 hddLog(VOS_TRACE_LEVEL_WARN,
4393 "%s: MAX TM Level Scan not allowed", __func__);
4394 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4395 return -EBUSY;
4396 }
4397 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4398
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004399 /* Check if scan is allowed at this point of time.
4400 */
4401 if (!hdd_isScanAllowed(pHddCtx))
4402 {
4403 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4404 return -EBUSY;
4405 }
4406
Jeff Johnson295189b2012-06-20 16:38:30 -07004407 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4408
4409 if (NULL != request)
4410 {
4411 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4412 (int)request->n_ssids);
4413
4414 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4415 * Becasue of this, driver is assuming that this is not wildcard scan and so
4416 * is not aging out the scan results.
4417 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004418 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004419 {
4420 request->n_ssids = 0;
4421 }
4422
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004423 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004424 {
4425 tCsrSSIDInfo *SsidInfo;
4426 int j;
4427 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4428 /* Allocate num_ssid tCsrSSIDInfo structure */
4429 SsidInfo = scanRequest.SSIDs.SSIDList =
4430 ( tCsrSSIDInfo *)vos_mem_malloc(
4431 request->n_ssids*sizeof(tCsrSSIDInfo));
4432
4433 if(NULL == scanRequest.SSIDs.SSIDList)
4434 {
4435 hddLog(VOS_TRACE_LEVEL_ERROR,
4436 "memory alloc failed SSIDInfo buffer");
4437 return -ENOMEM;
4438 }
4439
4440 /* copy all the ssid's and their length */
4441 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4442 {
4443 /* get the ssid length */
4444 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4445 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4446 SsidInfo->SSID.length);
4447 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4448 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4449 j, SsidInfo->SSID.ssId);
4450 }
4451 /* set the scan type to active */
4452 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4453 }
4454 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4455 {
4456 /* set the scan type to active */
4457 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4458 }
4459 else
4460 {
4461 /*Set the scan type to default type, in this case it is ACTIVE*/
4462 scanRequest.scanType = pScanInfo->scan_mode;
4463 }
4464 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4465 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4466 }
4467 else
4468 {
4469 /* set the scan type to active */
4470 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4471 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4472
4473 /* set min and max channel time to zero */
4474 scanRequest.minChnTime = 0;
4475 scanRequest.maxChnTime = 0;
4476 }
4477
4478 /* set BSSType to default type */
4479 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4480
4481 /*TODO: scan the requested channels only*/
4482
4483 /*Right now scanning all the channels */
4484 if( request )
4485 {
4486 if( request->n_channels )
4487 {
4488 channelList = vos_mem_malloc( request->n_channels );
4489 if( NULL == channelList )
4490 {
4491 status = -ENOMEM;
4492 goto free_mem;
4493 }
4494
4495 for( i = 0 ; i < request->n_channels ; i++ )
4496 channelList[i] = request->channels[i]->hw_value;
4497 }
4498
4499 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4500 scanRequest.ChannelInfo.ChannelList = channelList;
4501
4502 /* set requestType to full scan */
4503 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004504
4505 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4506 * search (Flush on both full scan and social scan but not on single
4507 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4508 */
4509
4510 /* Supplicant does single channel scan after 8-way handshake
4511 * and in that case driver shoudnt flush scan results. If
4512 * driver flushes the scan results here and unfortunately if
4513 * the AP doesnt respond to our probe req then association
4514 * fails which is not desired
4515 */
4516
4517 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4518 {
4519 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4520 pAdapter->sessionId );
4521 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004522
4523 if( request->ie_len )
4524 {
4525 /* save this for future association (join requires this) */
4526 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4527 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4528 pScanInfo->scanAddIE.length = request->ie_len;
4529
4530 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004531 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4532 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004533 )
4534 {
4535 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4536 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4537 }
4538
4539 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4540 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4541
Jeff Johnson295189b2012-06-20 16:38:30 -07004542 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4543 request->ie_len);
4544 if (pP2pIe != NULL)
4545 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004546#ifdef WLAN_FEATURE_P2P_DEBUG
4547 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4548 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4549 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4550 {
4551 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4552 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4553 "Go nego completed to Connection is started");
4554 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4555 "for 8way Handshake");
4556 }
4557 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4558 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4559 {
4560 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4561 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4562 "Disconnected state to Connection is started");
4563 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4564 "for 4way Handshake");
4565 }
4566#endif
4567
Jeff Johnsone7245742012-09-05 17:12:55 -07004568 /* no_cck will be set during p2p find to disable 11b rates */
4569 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004570 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004571 hddLog(VOS_TRACE_LEVEL_INFO,
4572 "%s: This is a P2P Search", __func__);
4573 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004574
Jeff Johnsone7245742012-09-05 17:12:55 -07004575 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4576 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004577 /* set requestType to P2P Discovery */
4578 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004579 }
4580
4581 /*
4582 Skip Dfs Channel in case of P2P Search
4583 if it is set in ini file
4584 */
4585 if(cfg_param->skipDfsChnlInP2pSearch)
4586 {
4587 scanRequest.skipDfsChnlInP2pSearch = 1;
4588 }
4589 else
4590 {
4591 scanRequest.skipDfsChnlInP2pSearch = 0;
4592 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004593
Jeff Johnson295189b2012-06-20 16:38:30 -07004594 }
4595 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004596 }
4597 }
4598
4599 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4600
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004601 /* acquire the wakelock to avoid the apps suspend during the scan. To
4602 * address the following issues.
4603 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4604 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4605 * for long time, this result in apps running at full power for long time.
4606 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4607 * be stuck in full power because of resume BMPS
4608 */
4609 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004610
4611 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004612 pAdapter->sessionId, &scanRequest, &scanId,
4613 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004614
Jeff Johnson295189b2012-06-20 16:38:30 -07004615 if (eHAL_STATUS_SUCCESS != status)
4616 {
4617 hddLog(VOS_TRACE_LEVEL_ERROR,
4618 "%s: sme_ScanRequest returned error %d", __func__, status);
4619 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004620 if(eHAL_STATUS_RESOURCES == status)
4621 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004622 hddLog(VOS_TRACE_LEVEL_INFO, "%s: HO is in progress.So defer the scan by informing busy",__func__);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004623 status = -EBUSY;
4624 } else {
4625 status = -EIO;
4626 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004627 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004628 goto free_mem;
4629 }
4630
4631 pScanInfo->mScanPending = TRUE;
4632 pAdapter->request = request;
4633 pScanInfo->scanId = scanId;
4634
4635 complete(&pScanInfo->scan_req_completion_event);
4636
4637free_mem:
4638 if( scanRequest.SSIDs.SSIDList )
4639 {
4640 vos_mem_free(scanRequest.SSIDs.SSIDList);
4641 }
4642
4643 if( channelList )
4644 vos_mem_free( channelList );
4645
4646 EXIT();
4647
4648 return status;
4649}
4650
4651/*
4652 * FUNCTION: wlan_hdd_cfg80211_connect_start
4653 * This function is used to start the association process
4654 */
4655int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004656 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004657{
4658 int status = 0;
4659 hdd_wext_state_t *pWextState;
4660 v_U32_t roamId;
4661 tCsrRoamProfile *pRoamProfile;
4662 eMib_dot11DesiredBssType connectedBssType;
4663 eCsrAuthType RSNAuthType;
4664
4665 ENTER();
4666
4667 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4668
4669 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4670 {
4671 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4672 return -EINVAL;
4673 }
4674
4675 pRoamProfile = &pWextState->roamProfile;
4676
4677 if (pRoamProfile)
4678 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004679 int ret = 0;
4680 hdd_station_ctx_t *pHddStaCtx;
4681 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4682 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4683
4684 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4685 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4686 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004687 {
4688 /* Issue disconnect to CSR */
4689 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4690 if( eHAL_STATUS_SUCCESS ==
4691 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4692 pAdapter->sessionId,
4693 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4694 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004695 ret = wait_for_completion_interruptible_timeout(
4696 &pAdapter->disconnect_comp_var,
4697 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4698 if (0 == ret)
4699 {
4700 VOS_ASSERT(0);
4701 }
4702 }
4703 }
4704 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4705 {
4706 ret = wait_for_completion_interruptible_timeout(
4707 &pAdapter->disconnect_comp_var,
4708 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4709 if (0 == ret)
4710 {
4711 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004712 }
4713 }
4714
4715 if (HDD_WMM_USER_MODE_NO_QOS ==
4716 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4717 {
4718 /*QoS not enabled in cfg file*/
4719 pRoamProfile->uapsd_mask = 0;
4720 }
4721 else
4722 {
4723 /*QoS enabled, update uapsd mask from cfg file*/
4724 pRoamProfile->uapsd_mask =
4725 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4726 }
4727
4728 pRoamProfile->SSIDs.numOfSSIDs = 1;
4729 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4730 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4731 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4732 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4733 ssid, ssid_len);
4734
4735 if (bssid)
4736 {
4737 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4738 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4739 WNI_CFG_BSSID_LEN);
4740 /* Save BSSID in seperate variable as well, as RoamProfile
4741 BSSID is getting zeroed out in the association process. And in
4742 case of join failure we should send valid BSSID to supplicant
4743 */
4744 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4745 WNI_CFG_BSSID_LEN);
4746 }
4747
4748 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4749 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4750 {
4751 /*set gen ie*/
4752 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4753 /*set auth*/
4754 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4755 }
4756 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4757 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4758 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4759 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4760 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4761 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4762 )
4763 {
4764 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4765 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4766 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4767 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4768 eCSR_AUTH_TYPE_AUTOSWITCH;
4769 pWextState->roamProfile.AuthType.authType[0] =
4770 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4771 }
4772#ifdef FEATURE_WLAN_WAPI
4773 if (pAdapter->wapi_info.nWapiMode)
4774 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004775 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004776 switch (pAdapter->wapi_info.wapiAuthMode)
4777 {
4778 case WAPI_AUTH_MODE_PSK:
4779 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004780 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 pAdapter->wapi_info.wapiAuthMode);
4782 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4783 break;
4784 }
4785 case WAPI_AUTH_MODE_CERT:
4786 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004787 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004788 pAdapter->wapi_info.wapiAuthMode);
4789 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4790 break;
4791 }
4792 } // End of switch
4793 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4794 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4795 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004796 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004797 pRoamProfile->AuthType.numEntries = 1;
4798 pRoamProfile->EncryptionType.numEntries = 1;
4799 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4800 pRoamProfile->mcEncryptionType.numEntries = 1;
4801 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4802 }
4803 }
4804#endif /* FEATURE_WLAN_WAPI */
4805 pRoamProfile->csrPersona = pAdapter->device_mode;
4806
Jeff Johnson32d95a32012-09-10 13:15:23 -07004807 if( operatingChannel )
4808 {
4809 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4810 pRoamProfile->ChannelInfo.numOfChannels = 1;
4811 }
4812
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004813 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4814 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4815 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4816 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004817 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4818 */
4819 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4820 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4821 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004822
Jeff Johnson295189b2012-06-20 16:38:30 -07004823 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4824 pAdapter->sessionId, pRoamProfile, &roamId);
4825
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004826 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304827 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4828
4829 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004830 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4831 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4832 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304833 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004834 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304835 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004836
4837 pRoamProfile->ChannelInfo.ChannelList = NULL;
4838 pRoamProfile->ChannelInfo.numOfChannels = 0;
4839
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 }
4841 else
4842 {
4843 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4844 return -EINVAL;
4845 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004846 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004847 return status;
4848}
4849
4850/*
4851 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4852 * This function is used to set the authentication type (OPEN/SHARED).
4853 *
4854 */
4855static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4856 enum nl80211_auth_type auth_type)
4857{
4858 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4859 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4860
4861 ENTER();
4862
4863 /*set authentication type*/
4864 switch (auth_type)
4865 {
4866 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4867 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004868#ifdef WLAN_FEATURE_VOWIFI_11R
4869 case NL80211_AUTHTYPE_FT:
4870#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004871 hddLog(VOS_TRACE_LEVEL_INFO,
4872 "%s: set authentication type to OPEN", __func__);
4873 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4874 break;
4875
4876 case NL80211_AUTHTYPE_SHARED_KEY:
4877 hddLog(VOS_TRACE_LEVEL_INFO,
4878 "%s: set authentication type to SHARED", __func__);
4879 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4880 break;
4881#ifdef FEATURE_WLAN_CCX
4882 case NL80211_AUTHTYPE_NETWORK_EAP:
4883 hddLog(VOS_TRACE_LEVEL_INFO,
4884 "%s: set authentication type to CCKM WPA", __func__);
4885 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4886 break;
4887#endif
4888
4889
4890 default:
4891 hddLog(VOS_TRACE_LEVEL_ERROR,
4892 "%s: Unsupported authentication type %d", __func__,
4893 auth_type);
4894 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4895 return -EINVAL;
4896 }
4897
4898 pWextState->roamProfile.AuthType.authType[0] =
4899 pHddStaCtx->conn_info.authType;
4900 return 0;
4901}
4902
4903/*
4904 * FUNCTION: wlan_hdd_set_akm_suite
4905 * This function is used to set the key mgmt type(PSK/8021x).
4906 *
4907 */
4908static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4909 u32 key_mgmt
4910 )
4911{
4912 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4913 ENTER();
4914
4915 /*set key mgmt type*/
4916 switch(key_mgmt)
4917 {
4918 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304919#ifdef WLAN_FEATURE_VOWIFI_11R
4920 case WLAN_AKM_SUITE_FT_PSK:
4921#endif
4922 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07004923 __func__);
4924 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4925 break;
4926
4927 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304928#ifdef WLAN_FEATURE_VOWIFI_11R
4929 case WLAN_AKM_SUITE_FT_8021X:
4930#endif
4931 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07004932 __func__);
4933 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4934 break;
4935#ifdef FEATURE_WLAN_CCX
4936#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4937#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4938 case WLAN_AKM_SUITE_CCKM:
4939 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4940 __func__);
4941 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4942 break;
4943#endif
4944
4945 default:
4946 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4947 __func__, key_mgmt);
4948 return -EINVAL;
4949
4950 }
4951 return 0;
4952}
4953
4954/*
4955 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4956 * This function is used to set the encryption type
4957 * (NONE/WEP40/WEP104/TKIP/CCMP).
4958 */
4959static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4960 u32 cipher,
4961 bool ucast
4962 )
4963{
4964 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4965 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4966 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4967
4968 ENTER();
4969
4970 if (!cipher)
4971 {
4972 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4973 __func__, cipher);
4974 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4975 }
4976 else
4977 {
4978
4979 /*set encryption method*/
4980 switch (cipher)
4981 {
4982 case IW_AUTH_CIPHER_NONE:
4983 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4984 break;
4985
4986 case WLAN_CIPHER_SUITE_WEP40:
4987 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4988 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4989 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4990 else
4991 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4992 break;
4993
4994 case WLAN_CIPHER_SUITE_WEP104:
4995 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4996 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4997 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4998 else
4999 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
5000 break;
5001
5002 case WLAN_CIPHER_SUITE_TKIP:
5003 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5004 break;
5005
5006 case WLAN_CIPHER_SUITE_CCMP:
5007 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5008 break;
5009#ifdef FEATURE_WLAN_WAPI
5010 case WLAN_CIPHER_SUITE_SMS4:
5011 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5012 break;
5013#endif
5014
5015#ifdef FEATURE_WLAN_CCX
5016 case WLAN_CIPHER_SUITE_KRK:
5017 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5018 break;
5019#endif
5020 default:
5021 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5022 __func__, cipher);
5023 return -EOPNOTSUPP;
5024 }
5025 }
5026
5027 if (ucast)
5028 {
5029 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5030 __func__, encryptionType);
5031 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5032 pWextState->roamProfile.EncryptionType.numEntries = 1;
5033 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5034 encryptionType;
5035 }
5036 else
5037 {
5038 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5039 __func__, encryptionType);
5040 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5041 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5042 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5043 }
5044
5045 return 0;
5046}
5047
5048
5049/*
5050 * FUNCTION: wlan_hdd_cfg80211_set_ie
5051 * This function is used to parse WPA/RSN IE's.
5052 */
5053int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5054 u8 *ie,
5055 size_t ie_len
5056 )
5057{
5058 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5059 u8 *genie = ie;
5060 v_U16_t remLen = ie_len;
5061#ifdef FEATURE_WLAN_WAPI
5062 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5063 u16 *tmp;
5064 v_U16_t akmsuiteCount;
5065 int *akmlist;
5066#endif
5067 ENTER();
5068
5069 /* clear previous assocAddIE */
5070 pWextState->assocAddIE.length = 0;
5071 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5072
5073 while (remLen >= 2)
5074 {
5075 v_U16_t eLen = 0;
5076 v_U8_t elementId;
5077 elementId = *genie++;
5078 eLen = *genie++;
5079 remLen -= 2;
5080
5081 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5082 __func__, elementId, eLen);
5083
5084 switch ( elementId )
5085 {
5086 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005087 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 -07005088 {
5089 hddLog(VOS_TRACE_LEVEL_ERROR,
5090 "%s: Invalid WPA IE", __func__);
5091 return -EINVAL;
5092 }
5093 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5094 {
5095 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5096 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5097 __func__, eLen + 2);
5098
5099 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5100 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005101 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5102 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 VOS_ASSERT(0);
5104 return -ENOMEM;
5105 }
5106 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5107 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5108 pWextState->assocAddIE.length += eLen + 2;
5109
5110 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5111 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5112 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5113 }
5114 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5115 {
5116 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5117 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5118 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5119 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5120 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5121 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5123 P2P_OUI_TYPE_SIZE))
5124 /*Consider P2P IE, only for P2P Client */
5125 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5126 {
5127 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5128 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5129 __func__, eLen + 2);
5130
5131 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5132 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005133 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5134 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005135 VOS_ASSERT(0);
5136 return -ENOMEM;
5137 }
5138 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5139 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5140 pWextState->assocAddIE.length += eLen + 2;
5141
5142 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5143 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5144 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005145#ifdef WLAN_FEATURE_WFD
5146 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5147 WFD_OUI_TYPE_SIZE))
5148 /*Consider WFD IE, only for P2P Client */
5149 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5150 {
5151 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5152 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5153 __func__, eLen + 2);
5154
5155 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5156 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005157 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5158 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 VOS_ASSERT(0);
5160 return -ENOMEM;
5161 }
5162 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5163 // WPS IE + P2P IE + WFD IE
5164 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5165 pWextState->assocAddIE.length += eLen + 2;
5166
5167 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5168 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5169 }
5170#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005171 /* Appending HS 2.0 Indication Element in Assiciation Request */
5172 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005173 HS20_OUI_TYPE_SIZE)) )
5174 {
5175 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5176 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5177 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005178
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005179 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5180 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005181 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5182 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005183 VOS_ASSERT(0);
5184 return -ENOMEM;
5185 }
5186 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5187 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005188
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005189 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5190 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5191 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005192
Jeff Johnson295189b2012-06-20 16:38:30 -07005193 break;
5194 case DOT11F_EID_RSN:
5195 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5196 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5197 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5198 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5199 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5200 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005201 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5202 case DOT11F_EID_EXTCAP:
5203 {
5204 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5205 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5206 __func__, eLen + 2);
5207
5208 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5209 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005210 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5211 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005212 VOS_ASSERT(0);
5213 return -ENOMEM;
5214 }
5215 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5216 pWextState->assocAddIE.length += eLen + 2;
5217
5218 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5219 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5220 break;
5221 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005222#ifdef FEATURE_WLAN_WAPI
5223 case WLAN_EID_WAPI:
5224 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5225 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5226 pAdapter->wapi_info.nWapiMode);
5227 tmp = (u16 *)ie;
5228 tmp = tmp + 2; // Skip element Id and Len, Version
5229 akmsuiteCount = WPA_GET_LE16(tmp);
5230 tmp = tmp + 1;
5231 akmlist = (int *)(tmp);
5232 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5233 {
5234 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5235 }
5236 else
5237 {
5238 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5239 VOS_ASSERT(0);
5240 return -EINVAL;
5241 }
5242
5243 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5244 {
5245 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005246 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005247 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5248 }
5249 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5250 {
5251 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005252 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005253 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5254 }
5255 break;
5256#endif
5257 default:
5258 hddLog (VOS_TRACE_LEVEL_ERROR,
5259 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005260 /* when Unknown IE is received we should break and continue
5261 * to the next IE in the buffer instead we were returning
5262 * so changing this to break */
5263 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005264 }
5265 genie += eLen;
5266 remLen -= eLen;
5267 }
5268 EXIT();
5269 return 0;
5270}
5271
5272/*
5273 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5274 * This function is used to initialize the security
5275 * parameters during connect operation.
5276 */
5277int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5278 struct cfg80211_connect_params *req
5279 )
5280{
5281 int status = 0;
5282 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5283 ENTER();
5284
5285 /*set wpa version*/
5286 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5287
5288 if (req->crypto.wpa_versions)
5289 {
5290 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5291 && ( (req->ie_len)
5292 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5293 // Make sure that it is including a WPA IE.
5294 /* Currently NL is putting WPA version 1 even for open,
5295 * since p2p ie is also put in same buffer.
5296 * */
5297 {
5298 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5299 }
5300 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5301 {
5302 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5303 }
5304 }
5305
5306 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5307 pWextState->wpaVersion);
5308
5309 /*set authentication type*/
5310 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5311
5312 if (0 > status)
5313 {
5314 hddLog(VOS_TRACE_LEVEL_ERROR,
5315 "%s: failed to set authentication type ", __func__);
5316 return status;
5317 }
5318
5319 /*set key mgmt type*/
5320 if (req->crypto.n_akm_suites)
5321 {
5322 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5323 if (0 > status)
5324 {
5325 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5326 __func__);
5327 return status;
5328 }
5329 }
5330
5331 /*set pairwise cipher type*/
5332 if (req->crypto.n_ciphers_pairwise)
5333 {
5334 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5335 req->crypto.ciphers_pairwise[0], true);
5336 if (0 > status)
5337 {
5338 hddLog(VOS_TRACE_LEVEL_ERROR,
5339 "%s: failed to set unicast cipher type", __func__);
5340 return status;
5341 }
5342 }
5343 else
5344 {
5345 /*Reset previous cipher suite to none*/
5346 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5347 if (0 > status)
5348 {
5349 hddLog(VOS_TRACE_LEVEL_ERROR,
5350 "%s: failed to set unicast cipher type", __func__);
5351 return status;
5352 }
5353 }
5354
5355 /*set group cipher type*/
5356 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5357 false);
5358
5359 if (0 > status)
5360 {
5361 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5362 __func__);
5363 return status;
5364 }
5365
5366 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5367 if (req->ie_len)
5368 {
5369 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5370 if ( 0 > status)
5371 {
5372 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5373 __func__);
5374 return status;
5375 }
5376 }
5377
5378 /*incase of WEP set default key information*/
5379 if (req->key && req->key_len)
5380 {
5381 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5382 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5383 )
5384 {
5385 if ( IW_AUTH_KEY_MGMT_802_1X
5386 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5387 {
5388 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5389 __func__);
5390 return -EOPNOTSUPP;
5391 }
5392 else
5393 {
5394 u8 key_len = req->key_len;
5395 u8 key_idx = req->key_idx;
5396
5397 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5398 && (CSR_MAX_NUM_KEY > key_idx)
5399 )
5400 {
5401 hddLog(VOS_TRACE_LEVEL_INFO,
5402 "%s: setting default wep key, key_idx = %hu key_len %hu",
5403 __func__, key_idx, key_len);
5404 vos_mem_copy(
5405 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5406 req->key, key_len);
5407 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5408 (u8)key_len;
5409 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5410 }
5411 }
5412 }
5413 }
5414
5415 return status;
5416}
5417
5418/*
5419 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5420 * This function is used to initialize the security
5421 * parameters during connect operation.
5422 */
5423static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5424 struct net_device *ndev,
5425 struct cfg80211_connect_params *req
5426 )
5427{
5428 int status = 0;
5429 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5430 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5431 hdd_context_t *pHddCtx = NULL;
5432
5433 ENTER();
5434
5435 hddLog(VOS_TRACE_LEVEL_INFO,
5436 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5437
5438 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5439 {
5440 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5441 "%s:LOGP in Progress. Ignore!!!", __func__);
5442 return -EAGAIN;
5443 }
5444
5445#ifdef WLAN_BTAMP_FEATURE
5446 //Infra connect not supported when AMP traffic is on.
5447 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5448 {
5449 hddLog(VOS_TRACE_LEVEL_ERROR,
5450 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005451 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 }
5453#endif
5454 /*initialise security parameters*/
5455 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5456
5457 if ( 0 > status)
5458 {
5459 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5460 __func__);
5461 return status;
5462 }
5463
5464 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005465 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005466 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5467 (vos_concurrent_sessions_running()))
5468 {
5469 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5470
5471 if (NULL != pVosContext)
5472 {
5473 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5474 if(NULL != pHddCtx)
5475 {
5476 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5477 }
5478 }
5479 }
5480
Mohit Khanna765234a2012-09-11 15:08:35 -07005481 if ( req->channel )
5482 {
5483 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5484 req->ssid_len, req->bssid,
5485 req->channel->hw_value);
5486 }
5487 else
5488 {
5489 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5490 req->ssid_len, req->bssid,
5491 0);
5492 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005493
5494 if (0 > status)
5495 {
5496 //ReEnable BMPS if disabled
5497 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5498 (NULL != pHddCtx))
5499 {
5500 //ReEnable Bmps and Imps back
5501 hdd_enable_bmps_imps(pHddCtx);
5502 }
5503
5504 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5505 return status;
5506 }
5507 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5508 EXIT();
5509 return status;
5510}
5511
5512
5513/*
5514 * FUNCTION: wlan_hdd_cfg80211_disconnect
5515 * This function is used to issue a disconnect request to SME
5516 */
5517static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5518 struct net_device *dev,
5519 u16 reason
5520 )
5521{
5522 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5523 tCsrRoamProfile *pRoamProfile =
5524 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5525 int status = 0;
5526 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005527#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005528 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005529 tANI_U8 staIdx;
5530#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005531
5532 ENTER();
5533
5534 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5535 __func__,pAdapter->device_mode);
5536
5537 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5538 __func__, reason);
5539
5540 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5541 {
5542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5543 "%s:LOGP in Progress. Ignore!!!",__func__);
5544 return -EAGAIN;
5545 }
5546 if (NULL != pRoamProfile)
5547 {
5548 /*issue disconnect request to SME, if station is in connected state*/
5549 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5550 {
5551 eCsrRoamDisconnectReason reasonCode =
5552 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5553 switch(reason)
5554 {
5555 case WLAN_REASON_MIC_FAILURE:
5556 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5557 break;
5558
5559 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5560 case WLAN_REASON_DISASSOC_AP_BUSY:
5561 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5562 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5563 break;
5564
5565 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5566 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5567 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5568 break;
5569
5570 case WLAN_REASON_DEAUTH_LEAVING:
5571 default:
5572 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5573 break;
5574 }
5575 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5576 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5577 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5578
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005579#ifdef FEATURE_WLAN_TDLS
5580 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005581 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005582 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005583 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5584 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005585 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005586 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005587 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005588 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005589 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005590 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005591 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005592 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005593 pAdapter->sessionId,
5594 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005595 }
5596 }
5597#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 /*issue disconnect*/
5599 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5600 pAdapter->sessionId, reasonCode);
5601
5602 if ( 0 != status)
5603 {
5604 hddLog(VOS_TRACE_LEVEL_ERROR,
5605 "%s csrRoamDisconnect failure, returned %d \n",
5606 __func__, (int)status );
5607 return -EINVAL;
5608 }
5609
5610 wait_for_completion_interruptible_timeout(
5611 &pAdapter->disconnect_comp_var,
5612 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5613
5614
5615 /*stop tx queues*/
5616 netif_tx_disable(dev);
5617 netif_carrier_off(dev);
5618 }
5619 }
5620 else
5621 {
5622 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5623 }
5624
5625 return status;
5626}
5627
5628/*
5629 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5630 * This function is used to initialize the security
5631 * settings in IBSS mode.
5632 */
5633static int wlan_hdd_cfg80211_set_privacy_ibss(
5634 hdd_adapter_t *pAdapter,
5635 struct cfg80211_ibss_params *params
5636 )
5637{
5638 int status = 0;
5639 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5640 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5641 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5642
5643 ENTER();
5644
5645 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5646
5647 if (params->ie_len && ( NULL != params->ie) )
5648 {
5649 if (WLAN_EID_RSN == params->ie[0])
5650 {
5651 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5652 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5653 }
5654 else
5655 {
5656 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5657 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5658 }
5659 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5660
5661 if (0 > status)
5662 {
5663 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5664 __func__);
5665 return status;
5666 }
5667 }
5668
5669 pWextState->roamProfile.AuthType.authType[0] =
5670 pHddStaCtx->conn_info.authType =
5671 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5672
5673 if (params->privacy)
5674 {
5675 /* Security enabled IBSS, At this time there is no information available
5676 * about the security paramters, so initialise the encryption type to
5677 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5678 * The correct security parameters will be updated later in
5679 * wlan_hdd_cfg80211_add_key */
5680 /* Hal expects encryption type to be set inorder
5681 *enable privacy bit in beacons */
5682
5683 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5684 }
5685
5686 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5687 pWextState->roamProfile.EncryptionType.numEntries = 1;
5688 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5689
5690 return status;
5691}
5692
5693/*
5694 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5695 * This function is used to create/join an IBSS
5696 */
5697static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5698 struct net_device *dev,
5699 struct cfg80211_ibss_params *params
5700 )
5701{
5702 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5703 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5704 tCsrRoamProfile *pRoamProfile;
5705 int status;
5706 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5707
5708 ENTER();
5709
5710 hddLog(VOS_TRACE_LEVEL_INFO,
5711 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5712
5713 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5714 {
5715 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5716 "%s:LOGP in Progress. Ignore!!!", __func__);
5717 return -EAGAIN;
5718 }
5719
5720 if (NULL == pWextState)
5721 {
5722 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5723 __func__);
5724 return -EIO;
5725 }
5726
5727 pRoamProfile = &pWextState->roamProfile;
5728
5729 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5730 {
5731 hddLog (VOS_TRACE_LEVEL_ERROR,
5732 "%s Interface type is not set to IBSS \n", __func__);
5733 return -EINVAL;
5734 }
5735
5736 /* Set Channel */
5737 if (NULL != params->channel)
5738 {
5739 u8 channelNum;
5740 if (IEEE80211_BAND_5GHZ == params->channel->band)
5741 {
5742 hddLog(VOS_TRACE_LEVEL_ERROR,
5743 "%s: IBSS join is called with unsupported band %d",
5744 __func__, params->channel->band);
5745 return -EOPNOTSUPP;
5746 }
5747
5748 /* Get channel number */
5749 channelNum =
5750 ieee80211_frequency_to_channel(params->channel->center_freq);
5751
5752 /*TODO: use macro*/
5753 if (14 >= channelNum)
5754 {
5755 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5756 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5757 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5758 int indx;
5759
5760 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5761 validChan, &numChans))
5762 {
5763 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5764 __func__);
5765 return -EOPNOTSUPP;
5766 }
5767
5768 for (indx = 0; indx < numChans; indx++)
5769 {
5770 if (channelNum == validChan[indx])
5771 {
5772 break;
5773 }
5774 }
5775 if (indx >= numChans)
5776 {
5777 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5778 __func__, channelNum);
5779 return -EINVAL;
5780 }
5781 /* Set the Operational Channel */
5782 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5783 channelNum);
5784 pRoamProfile->ChannelInfo.numOfChannels = 1;
5785 pHddStaCtx->conn_info.operationChannel = channelNum;
5786 pRoamProfile->ChannelInfo.ChannelList =
5787 &pHddStaCtx->conn_info.operationChannel;
5788 }
5789 else
5790 {
5791 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5792 __func__, channelNum);
5793 return -EINVAL;
5794 }
5795 }
5796
5797 /* Initialize security parameters */
5798 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5799 if (status < 0)
5800 {
5801 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5802 __func__);
5803 return status;
5804 }
5805
5806 /* Issue connect start */
5807 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005808 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005809
5810 if (0 > status)
5811 {
5812 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5813 return status;
5814 }
5815
5816 return 0;
5817}
5818
5819/*
5820 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5821 * This function is used to leave an IBSS
5822 */
5823static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5824 struct net_device *dev
5825 )
5826{
5827 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5828 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5829 tCsrRoamProfile *pRoamProfile;
5830
5831 ENTER();
5832
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005833 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5834 {
5835 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5836 "%s:LOGP in Progress. Ignore!!!", __func__);
5837 return -EAGAIN;
5838 }
5839
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5841 if (NULL == pWextState)
5842 {
5843 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5844 __func__);
5845 return -EIO;
5846 }
5847
5848 pRoamProfile = &pWextState->roamProfile;
5849
5850 /* Issue disconnect only if interface type is set to IBSS */
5851 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5852 {
5853 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5854 __func__);
5855 return -EINVAL;
5856 }
5857
5858 /* Issue Disconnect request */
5859 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5860 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5861 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5862
5863 return 0;
5864}
5865
5866/*
5867 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5868 * This function is used to set the phy parameters
5869 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5870 */
5871static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5872 u32 changed)
5873{
5874 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5875 tHalHandle hHal = pHddCtx->hHal;
5876
5877 ENTER();
5878
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005879 if ( pHddCtx->isLogpInProgress )
5880 {
5881 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5882 "%s:LOGP in Progress. Ignore!!!", __func__);
5883 return -EAGAIN;
5884 }
5885
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5887 {
5888 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5889 WNI_CFG_RTS_THRESHOLD_STAMAX :
5890 wiphy->rts_threshold;
5891
5892 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5893 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5894 {
5895 hddLog(VOS_TRACE_LEVEL_ERROR,
5896 "%s: Invalid RTS Threshold value %hu",
5897 __func__, rts_threshold);
5898 return -EINVAL;
5899 }
5900
5901 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5902 rts_threshold, ccmCfgSetCallback,
5903 eANI_BOOLEAN_TRUE))
5904 {
5905 hddLog(VOS_TRACE_LEVEL_ERROR,
5906 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5907 __func__, rts_threshold);
5908 return -EIO;
5909 }
5910
5911 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5912 rts_threshold);
5913 }
5914
5915 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5916 {
5917 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5918 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5919 wiphy->frag_threshold;
5920
5921 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5922 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5923 {
5924 hddLog(VOS_TRACE_LEVEL_ERROR,
5925 "%s: Invalid frag_threshold value %hu", __func__,
5926 frag_threshold);
5927 return -EINVAL;
5928 }
5929
5930 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5931 frag_threshold, ccmCfgSetCallback,
5932 eANI_BOOLEAN_TRUE))
5933 {
5934 hddLog(VOS_TRACE_LEVEL_ERROR,
5935 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5936 __func__, frag_threshold);
5937 return -EIO;
5938 }
5939
5940 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5941 frag_threshold);
5942 }
5943
5944 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5945 || (changed & WIPHY_PARAM_RETRY_LONG))
5946 {
5947 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5948 wiphy->retry_short :
5949 wiphy->retry_long;
5950
5951 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5952 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5953 {
5954 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5955 __func__, retry_value);
5956 return -EINVAL;
5957 }
5958
5959 if (changed & WIPHY_PARAM_RETRY_SHORT)
5960 {
5961 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5962 retry_value, ccmCfgSetCallback,
5963 eANI_BOOLEAN_TRUE))
5964 {
5965 hddLog(VOS_TRACE_LEVEL_ERROR,
5966 "%s: ccmCfgSetInt failed for long retry count %hu",
5967 __func__, retry_value);
5968 return -EIO;
5969 }
5970 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5971 __func__, retry_value);
5972 }
5973 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5974 {
5975 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5976 retry_value, ccmCfgSetCallback,
5977 eANI_BOOLEAN_TRUE))
5978 {
5979 hddLog(VOS_TRACE_LEVEL_ERROR,
5980 "%s: ccmCfgSetInt failed for short retry count %hu",
5981 __func__, retry_value);
5982 return -EIO;
5983 }
5984 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5985 __func__, retry_value);
5986 }
5987 }
5988
5989 return 0;
5990}
5991
5992/*
5993 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5994 * This function is used to set the txpower
5995 */
5996static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5997#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5998 enum tx_power_setting type,
5999#else
6000 enum nl80211_tx_power_setting type,
6001#endif
6002 int dbm)
6003{
6004 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6005 tHalHandle hHal = pHddCtx->hHal;
6006 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6007 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6008
6009 ENTER();
6010
6011 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6012 dbm, ccmCfgSetCallback,
6013 eANI_BOOLEAN_TRUE))
6014 {
6015 hddLog(VOS_TRACE_LEVEL_ERROR,
6016 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6017 return -EIO;
6018 }
6019
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006020 if ( pHddCtx->isLogpInProgress )
6021 {
6022 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6023 "%s:LOGP in Progress. Ignore!!!", __func__);
6024 return -EAGAIN;
6025 }
6026
Jeff Johnson295189b2012-06-20 16:38:30 -07006027 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6028 dbm);
6029
6030 switch(type)
6031 {
6032 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6033 /* Fall through */
6034 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6035 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6036 {
6037 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6038 __func__);
6039 return -EIO;
6040 }
6041 break;
6042 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6043 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6044 __func__);
6045 return -EOPNOTSUPP;
6046 break;
6047 default:
6048 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6049 __func__, type);
6050 return -EIO;
6051 }
6052
6053 return 0;
6054}
6055
6056/*
6057 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6058 * This function is used to read the txpower
6059 */
6060static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6061{
6062
6063 hdd_adapter_t *pAdapter;
6064 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6065
Jeff Johnsone7245742012-09-05 17:12:55 -07006066 ENTER();
6067
Jeff Johnson295189b2012-06-20 16:38:30 -07006068 if (NULL == pHddCtx)
6069 {
6070 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6071 *dbm = 0;
6072 return -ENOENT;
6073 }
6074
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006075 if ( pHddCtx->isLogpInProgress )
6076 {
6077 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6078 "%s:LOGP in Progress. Ignore!!!", __func__);
6079 return -EAGAIN;
6080 }
6081
Jeff Johnson295189b2012-06-20 16:38:30 -07006082 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6083 if (NULL == pAdapter)
6084 {
6085 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6086 return -ENOENT;
6087 }
6088
6089 wlan_hdd_get_classAstats(pAdapter);
6090 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6091
Jeff Johnsone7245742012-09-05 17:12:55 -07006092 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006093 return 0;
6094}
6095
6096static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6097 u8* mac, struct station_info *sinfo)
6098{
6099 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6100 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6101 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6102 tANI_U8 rate_flags;
6103
6104 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6105 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006106
6107 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6108 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6109 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6110 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6111 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6112 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6113 tANI_U16 maxRate = 0;
6114 tANI_U16 myRate;
6115 tANI_U16 currentRate = 0;
6116 tANI_U8 maxSpeedMCS = 0;
6117 tANI_U8 maxMCSIdx = 0;
6118 tANI_U8 rateFlag = 1;
6119 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006120 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006121
Jeff Johnsone7245742012-09-05 17:12:55 -07006122 ENTER();
6123
Jeff Johnson295189b2012-06-20 16:38:30 -07006124 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6125 (0 == ssidlen))
6126 {
6127 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6128 " Invalid ssidlen, %d", __func__, ssidlen);
6129 /*To keep GUI happy*/
6130 return 0;
6131 }
6132
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006133 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6134 {
6135 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6136 "%s:LOGP in Progress. Ignore!!!", __func__);
6137 return -EAGAIN;
6138 }
6139
Jeff Johnson295189b2012-06-20 16:38:30 -07006140 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6141 sinfo->filled |= STATION_INFO_SIGNAL;
6142
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006143 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6145
6146 //convert to the UI units of 100kbps
6147 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6148
6149#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006150 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x\n",
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 sinfo->signal,
6152 pCfg->reportMaxLinkSpeed,
6153 myRate,
6154 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006155 (int) pCfg->linkSpeedRssiMid,
6156 (int) pCfg->linkSpeedRssiLow,
6157 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07006158#endif //LINKSPEED_DEBUG_ENABLED
6159
6160 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6161 {
6162 // we do not want to necessarily report the current speed
6163 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6164 {
6165 // report the max possible speed
6166 rssidx = 0;
6167 }
6168 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6169 {
6170 // report the max possible speed with RSSI scaling
6171 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6172 {
6173 // report the max possible speed
6174 rssidx = 0;
6175 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006176 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006177 {
6178 // report middle speed
6179 rssidx = 1;
6180 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006181 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6182 {
6183 // report middle speed
6184 rssidx = 2;
6185 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006186 else
6187 {
6188 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006189 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 }
6191 }
6192 else
6193 {
6194 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6195 hddLog(VOS_TRACE_LEVEL_ERROR,
6196 "%s: Invalid value for reportMaxLinkSpeed: %u",
6197 __func__, pCfg->reportMaxLinkSpeed);
6198 rssidx = 0;
6199 }
6200
6201 maxRate = 0;
6202
6203 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306204 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6205 OperationalRates, &ORLeng))
6206 {
6207 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6208 /*To keep GUI happy*/
6209 return 0;
6210 }
6211
Jeff Johnson295189b2012-06-20 16:38:30 -07006212 for (i = 0; i < ORLeng; i++)
6213 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006214 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006215 {
6216 /* Validate Rate Set */
6217 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6218 {
6219 currentRate = supported_data_rate[j].supported_rate[rssidx];
6220 break;
6221 }
6222 }
6223 /* Update MAX rate */
6224 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6225 }
6226
6227 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306228 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6229 ExtendedRates, &ERLeng))
6230 {
6231 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6232 /*To keep GUI happy*/
6233 return 0;
6234 }
6235
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 for (i = 0; i < ERLeng; i++)
6237 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006238 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006239 {
6240 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6241 {
6242 currentRate = supported_data_rate[j].supported_rate[rssidx];
6243 break;
6244 }
6245 }
6246 /* Update MAX rate */
6247 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6248 }
6249
6250 /* Get MCS Rate Set -- but only if we are connected at MCS
6251 rates or if we are always reporting max speed or if we have
6252 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006253 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006254 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306255 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6256 MCSRates, &MCSLeng))
6257 {
6258 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6259 /*To keep GUI happy*/
6260 return 0;
6261 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006262 rateFlag = 0;
6263 if (rate_flags & eHAL_TX_RATE_HT40)
6264 {
6265 rateFlag |= 1;
6266 }
6267 if (rate_flags & eHAL_TX_RATE_SGI)
6268 {
6269 rateFlag |= 2;
6270 }
6271
6272 for (i = 0; i < MCSLeng; i++)
6273 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006274 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6275 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006276 {
6277 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6278 {
6279 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6280 break;
6281 }
6282 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006283 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006284 {
6285 maxRate = currentRate;
6286 maxSpeedMCS = 1;
6287 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6288 }
6289 }
6290 }
6291
6292 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006293 if (((maxRate < myRate) && (0 == rssidx)) ||
6294 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006295 {
6296 maxRate = myRate;
6297 if (rate_flags & eHAL_TX_RATE_LEGACY)
6298 {
6299 maxSpeedMCS = 0;
6300 }
6301 else
6302 {
6303 maxSpeedMCS = 1;
6304 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6305 }
6306 }
6307
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006308 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006309 {
6310 sinfo->txrate.legacy = maxRate;
6311#ifdef LINKSPEED_DEBUG_ENABLED
6312 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6313#endif //LINKSPEED_DEBUG_ENABLED
6314 }
6315 else
6316 {
6317 sinfo->txrate.mcs = maxMCSIdx;
6318 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6319 if (rate_flags & eHAL_TX_RATE_SGI)
6320 {
6321 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6322 }
6323 if (rate_flags & eHAL_TX_RATE_HT40)
6324 {
6325 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6326 }
6327#ifdef LINKSPEED_DEBUG_ENABLED
6328 pr_info("Reporting MCS rate %d flags %x\n",
6329 sinfo->txrate.mcs,
6330 sinfo->txrate.flags );
6331#endif //LINKSPEED_DEBUG_ENABLED
6332 }
6333 }
6334 else
6335 {
6336 // report current rate instead of max rate
6337
6338 if (rate_flags & eHAL_TX_RATE_LEGACY)
6339 {
6340 //provide to the UI in units of 100kbps
6341 sinfo->txrate.legacy = myRate;
6342#ifdef LINKSPEED_DEBUG_ENABLED
6343 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6344#endif //LINKSPEED_DEBUG_ENABLED
6345 }
6346 else
6347 {
6348 //must be MCS
6349 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6350 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6351 if (rate_flags & eHAL_TX_RATE_SGI)
6352 {
6353 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6354 }
6355 if (rate_flags & eHAL_TX_RATE_HT40)
6356 {
6357 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6358 }
6359#ifdef LINKSPEED_DEBUG_ENABLED
6360 pr_info("Reporting actual MCS rate %d flags %x\n",
6361 sinfo->txrate.mcs,
6362 sinfo->txrate.flags );
6363#endif //LINKSPEED_DEBUG_ENABLED
6364 }
6365 }
6366 sinfo->filled |= STATION_INFO_TX_BITRATE;
6367
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006368 sinfo->tx_packets =
6369 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6370 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6371 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6372 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6373
6374 sinfo->tx_retries =
6375 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6376 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6377 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6378 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6379
6380 sinfo->tx_failed =
6381 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6382 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6383 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6384 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6385
6386 sinfo->filled |=
6387 STATION_INFO_TX_PACKETS |
6388 STATION_INFO_TX_RETRIES |
6389 STATION_INFO_TX_FAILED;
6390
6391 EXIT();
6392 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006393}
6394
6395static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6396 struct net_device *dev, bool mode, v_SINT_t timeout)
6397{
6398 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6399 VOS_STATUS vos_status;
6400
Jeff Johnsone7245742012-09-05 17:12:55 -07006401 ENTER();
6402
Jeff Johnson295189b2012-06-20 16:38:30 -07006403 if (NULL == pAdapter)
6404 {
6405 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6406 return -ENODEV;
6407 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006408 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6409 {
6410 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6411 "%s:LOGP in Progress. Ignore!!!", __func__);
6412 return -EAGAIN;
6413 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006414
6415 /**The get power cmd from the supplicant gets updated by the nl only
6416 *on successful execution of the function call
6417 *we are oppositely mapped w.r.t mode in the driver
6418 **/
6419 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6420
Jeff Johnsone7245742012-09-05 17:12:55 -07006421 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006422 if (VOS_STATUS_E_FAILURE == vos_status)
6423 {
6424 return -EINVAL;
6425 }
6426 return 0;
6427}
6428
6429
6430#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6431static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6432 struct net_device *netdev,
6433 u8 key_index)
6434{
Jeff Johnsone7245742012-09-05 17:12:55 -07006435 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006436 return 0;
6437}
6438#endif //LINUX_VERSION_CODE
6439
6440#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6441static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6442 struct net_device *dev,
6443 struct ieee80211_txq_params *params)
6444{
Jeff Johnsone7245742012-09-05 17:12:55 -07006445 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006446 return 0;
6447}
6448#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6449static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6450 struct ieee80211_txq_params *params)
6451{
Jeff Johnsone7245742012-09-05 17:12:55 -07006452 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006453 return 0;
6454}
6455#endif //LINUX_VERSION_CODE
6456
6457static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6458 struct net_device *dev, u8 *mac)
6459{
6460 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006461 VOS_STATUS vos_status;
6462 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006463
Jeff Johnsone7245742012-09-05 17:12:55 -07006464 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006465 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6466 {
6467 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6468 return -EINVAL;
6469 }
6470
6471 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6472 {
6473 hddLog( LOGE,
6474 "%s: Wlan Load/Unload is in progress", __func__);
6475 return -EBUSY;
6476 }
6477
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006478 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6479 {
6480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6481 "%s:LOGP in Progress. Ignore!!!", __func__);
6482 return -EAGAIN;
6483 }
6484
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006486 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006487 )
6488 {
6489 if( NULL == mac )
6490 {
6491 v_U16_t i;
6492 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6493 {
6494 if(pAdapter->aStaInfo[i].isUsed)
6495 {
6496 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6497 hddLog(VOS_TRACE_LEVEL_INFO,
6498 "%s: Delete STA with MAC::"
6499 "%02x:%02x:%02x:%02x:%02x:%02x",
6500 __func__,
6501 macAddr[0], macAddr[1], macAddr[2],
6502 macAddr[3], macAddr[4], macAddr[5]);
6503 hdd_softap_sta_deauth(pAdapter, macAddr);
6504 }
6505 }
6506 }
6507 else
6508 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006509
6510 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6511 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6512 {
6513 hddLog(VOS_TRACE_LEVEL_INFO,
6514 "%s: Skip this DEL STA as this is not used::"
6515 "%02x:%02x:%02x:%02x:%02x:%02x",
6516 __func__,
6517 mac[0], mac[1], mac[2],
6518 mac[3], mac[4], mac[5]);
6519 return -ENOENT;
6520 }
6521
6522 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6523 {
6524 hddLog(VOS_TRACE_LEVEL_INFO,
6525 "%s: Skip this DEL STA as deauth is in progress::"
6526 "%02x:%02x:%02x:%02x:%02x:%02x",
6527 __func__,
6528 mac[0], mac[1], mac[2],
6529 mac[3], mac[4], mac[5]);
6530 return -ENOENT;
6531 }
6532
6533 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6534
Jeff Johnson295189b2012-06-20 16:38:30 -07006535 hddLog(VOS_TRACE_LEVEL_INFO,
6536 "%s: Delete STA with MAC::"
6537 "%02x:%02x:%02x:%02x:%02x:%02x",
6538 __func__,
6539 mac[0], mac[1], mac[2],
6540 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006541
6542 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6543 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6544 {
6545 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6546 hddLog(VOS_TRACE_LEVEL_INFO,
6547 "%s: STA removal failed for ::"
6548 "%02x:%02x:%02x:%02x:%02x:%02x",
6549 __func__,
6550 mac[0], mac[1], mac[2],
6551 mac[3], mac[4], mac[5]);
6552 return -ENOENT;
6553 }
6554
Jeff Johnson295189b2012-06-20 16:38:30 -07006555 }
6556 }
6557
6558 EXIT();
6559
6560 return 0;
6561}
6562
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006563static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6564 struct net_device *dev, u8 *mac, struct station_parameters *params)
6565{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006566 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006567#ifdef FEATURE_WLAN_TDLS
6568 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006569 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006570 mask = params->sta_flags_mask;
6571
6572 set = params->sta_flags_set;
6573
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006574#ifdef WLAN_FEATURE_TDLS_DEBUG
6575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6576 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6577 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6578#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006579
6580 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6581 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006582 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006583 }
6584 }
6585#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006586 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006587}
6588
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006589
6590#ifdef FEATURE_WLAN_LFR
6591static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006592 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006593{
6594#define MAX_PMKSAIDS_IN_CACHE 8
6595 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006596 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006597 tANI_U32 j=0;
6598 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6599 tHalHandle halHandle;
6600 eHalStatus result;
6601 tANI_U8 BSSIDMatched = 0;
6602
Jeff Johnsone7245742012-09-05 17:12:55 -07006603 ENTER();
6604
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006605 // Validate pAdapter
6606 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6607 {
6608 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6609 return -EINVAL;
6610 }
6611
6612 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6613 {
6614 hddLog( LOGE,
6615 "%s: Wlan Load/Unload is in progress", __func__);
6616 return -EBUSY;
6617 }
6618
6619 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6620 {
6621 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6622 "%s:LOGP in Progress. Ignore!!!", __func__);
6623 return -EAGAIN;
6624 }
6625
6626 // Retrieve halHandle
6627 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6628
6629 for (j = 0; j < i; j++)
6630 {
6631 if(vos_mem_compare(PMKIDCache[j].BSSID,
6632 pmksa->bssid, WNI_CFG_BSSID_LEN))
6633 {
6634 /* BSSID matched previous entry. Overwrite it. */
6635 BSSIDMatched = 1;
6636 vos_mem_copy(PMKIDCache[j].BSSID,
6637 pmksa->bssid, WNI_CFG_BSSID_LEN);
6638 vos_mem_copy(PMKIDCache[j].PMKID,
6639 pmksa->pmkid,
6640 CSR_RSN_PMKID_SIZE);
6641 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006642 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006643 dump_bssid(pmksa->bssid);
6644 dump_pmkid(halHandle, pmksa->pmkid);
6645 break;
6646 }
6647 }
6648
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006649 /* Check we compared all entries,if then take the first slot now */
6650 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6651
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006652 if (!BSSIDMatched)
6653 {
6654 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6655 vos_mem_copy(PMKIDCache[i].BSSID,
6656 pmksa->bssid, ETHER_ADDR_LEN);
6657 vos_mem_copy(PMKIDCache[i].PMKID,
6658 pmksa->pmkid,
6659 CSR_RSN_PMKID_SIZE);
6660 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006661 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006662 dump_bssid(pmksa->bssid);
6663 dump_pmkid(halHandle, pmksa->pmkid);
6664 // Increment the HDD Local Cache index
6665 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6666 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6667 }
6668
6669
6670 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6671 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006672 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006673 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006674 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006675 // Finally set the PMKSA ID Cache in CSR
6676 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6677 PMKIDCache,
6678 i );
6679 return 0;
6680}
6681
6682
6683static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006684 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006685{
Jeff Johnsone7245742012-09-05 17:12:55 -07006686 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006687 // TODO: Implement this later.
6688 return 0;
6689}
6690
6691static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6692{
Jeff Johnsone7245742012-09-05 17:12:55 -07006693 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006694 // TODO: Implement this later.
6695 return 0;
6696}
6697#endif
6698
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006699#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6700static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6701 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6702{
6703 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6704 hdd_station_ctx_t *pHddStaCtx;
6705
6706 if (NULL == pAdapter)
6707 {
6708 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6709 return -ENODEV;
6710 }
6711
6712 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6713
6714 // Added for debug on reception of Re-assoc Req.
6715 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6716 {
6717 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6718 ftie->ie_len);
6719 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6720 }
6721
6722#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6723 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6724 ftie->ie_len);
6725#endif
6726
6727 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05306728 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6729 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006730 ftie->ie_len);
6731 return 0;
6732}
6733#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006734
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006735#ifdef FEATURE_WLAN_TDLS
6736static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6737 u8 *peer, u8 action_code, u8 dialog_token,
6738 u16 status_code, const u8 *buf, size_t len)
6739{
6740
6741 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6742 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006743 u8 peerMac[6];
6744 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006745 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006746 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006747
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006748 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006749 {
6750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6751 "Invalid arguments");
6752 return -EINVAL;
6753 }
6754
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006755 if (pHddCtx->isLogpInProgress)
6756 {
6757 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6758 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006759 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006760 return -EBUSY;
6761 }
6762
Hoonki Lee27511902013-03-14 18:19:06 -07006763 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006764 {
Hoonki Lee27511902013-03-14 18:19:06 -07006765 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6766 "%s: TDLS mode is disabled OR not enabled in FW."
6767 MAC_ADDRESS_STR " action %d declined.",
6768 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006769 return -ENOTSUPP;
6770 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006771
Hoonki Lee27511902013-03-14 18:19:06 -07006772 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
6773 (SIR_MAC_TDLS_DIS_RSP == action_code))
6774 {
6775 wlan_hdd_tdls_set_cap (pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
6776 }
6777
6778 /* other than teardown frame, other mgmt frames are not sent if disabled */
6779 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6780 {
6781 /* if tdls_mode is disabled to respond to peer's request */
6782 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6783 {
6784 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6785 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006786 " TDLS mode is disabled. action %d declined.",
6787 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006788
6789 return -ENOTSUPP;
6790 }
6791 }
6792
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006793 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6794 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006795 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006796 {
6797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006798 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006799 " TDLS setup is ongoing. action %d declined.",
6800 __func__, MAC_ADDR_ARRAY(peer), action_code);
6801 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006802 }
6803 }
6804
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006805 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6806 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006807 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006808 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006809 {
6810 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6811 we return error code at 'add_station()'. Hence we have this
6812 check again in addtion to add_station().
6813 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006814 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006815 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6817 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006818 " TDLS Max peer already connected. action %d declined.",
6819 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006820 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006821 }
6822 else
6823 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006824 /* maximum reached. tweak to send error code to peer and return
6825 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006826 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6828 "%s: " MAC_ADDRESS_STR
6829 " TDLS Max peer already connected send response status %d",
6830 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006831 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006832 /* fall through to send setup resp with failure status
6833 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006834 }
6835 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006836 else
6837 {
6838 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006839 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006840 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6841 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006843 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
6844 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006845 return -EPERM;
6846 }
6847 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006848 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006849 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006850
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006851#ifdef WLAN_FEATURE_TDLS_DEBUG
6852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006853 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
6854 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
6855 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006856#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006857
Hoonki Leea34dd892013-02-05 22:56:02 -08006858 /*Except teardown responder will not be used so just make 0*/
6859 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006860 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006861 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006862 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
6863 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08006864 {
6865 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006866 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
6867 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08006868 dialog_token, status_code, len);
6869 return -EPERM;
6870 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006871 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006872
Gopichand Nakkala05922802013-03-14 12:23:19 -07006873 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6874 because we already know that this transaction will be failed,
6875 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6876 to be safe, do not change the state mahine.
6877 */
6878 if (max_sta_failed == 0 &&
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006879 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08006880 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_CONNECTING);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006881
6882 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6883
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006884 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006885 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006886
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006887 if (VOS_STATUS_SUCCESS != status)
6888 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006889 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6890 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006891 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006892 }
6893
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006894 /* not block discovery request, as it is called from timer callback */
6895 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006896 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006897 long rc;
6898
6899 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006900 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006901
Pervinder Singhb4638422013-03-04 22:51:36 -08006902 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006903 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006904 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08006905 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
6906 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006907 return -EPERM;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006908 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006909 }
6910
Gopichand Nakkala05922802013-03-14 12:23:19 -07006911 if (max_sta_failed)
6912 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006913
Hoonki Leea34dd892013-02-05 22:56:02 -08006914 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6915 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006916 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006917 }
6918 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6919 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006920 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006921 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006922
6923 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006924error:
6925 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6926 because we already know that this transaction will be failed,
6927 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6928 to be safe, do not change the state mahine.
6929 */
6930 if(max_sta_failed == 0 &&
6931 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6932 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
6933 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006934}
6935
6936static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6937 u8 *peer, enum nl80211_tdls_operation oper)
6938{
6939 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6940 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006941#ifdef WLAN_FEATURE_TDLS_DEBUG
6942 const char *tdls_oper_str[]= {
6943 "NL80211_TDLS_DISCOVERY_REQ",
6944 "NL80211_TDLS_SETUP",
6945 "NL80211_TDLS_TEARDOWN",
6946 "NL80211_TDLS_ENABLE_LINK",
6947 "NL80211_TDLS_DISABLE_LINK",
6948 "NL80211_TDLS_UNKONW_OPER"};
6949#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006950
6951 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6952 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006954 "Invalid arguments");
6955 return -EINVAL;
6956 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006957
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006958 if (pHddCtx->isLogpInProgress)
6959 {
6960 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6961 "%s:LOGP in Progress. Ignore!!!", __func__);
6962 return -EBUSY;
6963 }
6964
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006965#ifdef WLAN_FEATURE_TDLS_DEBUG
6966 if((int)oper > 4)
6967 oper = 5;
6968
6969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006970 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
6971 MAC_ADDR_ARRAY(peer), (int)oper,
6972 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006973#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006974
6975 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006976 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006977 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006979 "TDLS Disabled in INI OR not enabled in FW.\
6980 Cannot process TDLS commands \n");
6981 return -ENOTSUPP;
6982 }
6983
6984 switch (oper) {
6985 case NL80211_TDLS_ENABLE_LINK:
6986 {
Hoonki Lee387663d2013-02-05 18:08:43 -08006987 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006988 VOS_STATUS status;
6989
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006990 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006991
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006992 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6993 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
6994 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006995
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006996 if ( NULL == pTdlsPeer ) {
6997 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
6998 MAC_ADDRESS_STR " failed",
6999 __func__, MAC_ADDR_ARRAY(peer));
7000 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007001 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007002
7003 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
7004 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007005 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007006 /* start TDLS client registration with TL */
7007 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007008 if (VOS_STATUS_SUCCESS == status)
7009 {
7010 wlan_hdd_tdls_increment_peer_count(pAdapter);
7011 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007012 wlan_hdd_tdls_check_bmps(pAdapter);
7013 }
7014
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007015 }
7016 break;
7017 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007018 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007019 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007020
7021 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007022 {
7023 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7024 pAdapter->sessionId, peer );
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007025 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007026 }
7027 else
7028 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007029 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7030 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007031 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007032 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007033 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007034 case NL80211_TDLS_TEARDOWN:
7035 case NL80211_TDLS_SETUP:
7036 case NL80211_TDLS_DISCOVERY_REQ:
7037 /* We don't support in-driver setup/teardown/discovery */
7038 return -ENOTSUPP;
7039 default:
7040 return -ENOTSUPP;
7041 }
7042 return 0;
7043}
Chilam NG571c65a2013-01-19 12:27:36 +05307044
7045int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7046 struct net_device *dev, u8 *peer)
7047{
7048 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7049 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7050
7051 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7052 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7053}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007054#endif
7055
Jeff Johnson295189b2012-06-20 16:38:30 -07007056/* cfg80211_ops */
7057static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7058{
7059 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7060 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7061 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7062 .change_station = wlan_hdd_change_station,
7063#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7064 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7065 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7066 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007067#else
7068 .start_ap = wlan_hdd_cfg80211_start_ap,
7069 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7070 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007071#endif
7072 .change_bss = wlan_hdd_cfg80211_change_bss,
7073 .add_key = wlan_hdd_cfg80211_add_key,
7074 .get_key = wlan_hdd_cfg80211_get_key,
7075 .del_key = wlan_hdd_cfg80211_del_key,
7076 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007077#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007078 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007079#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007080 .scan = wlan_hdd_cfg80211_scan,
7081 .connect = wlan_hdd_cfg80211_connect,
7082 .disconnect = wlan_hdd_cfg80211_disconnect,
7083 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7084 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7085 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7086 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7087 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007088 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7089 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7090 .mgmt_tx = wlan_hdd_action,
7091#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7092 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7093 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7094 .set_txq_params = wlan_hdd_set_txq_params,
7095#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007096 .get_station = wlan_hdd_cfg80211_get_station,
7097 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7098 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007099 .add_station = wlan_hdd_cfg80211_add_station,
7100#ifdef FEATURE_WLAN_LFR
7101 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7102 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7103 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7104#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007105#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7106 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7107#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007108#ifdef FEATURE_WLAN_TDLS
7109 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7110 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7111#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007112};
7113