blob: 9a1c897c9995166fcf5b94287524f75ba5e00062 [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
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001013#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001014static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1015 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001016#else
1017static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1018 struct cfg80211_beacon_data *params)
1019#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001020{
1021 v_U8_t *genie;
1022 v_U8_t total_ielen = 0, ielen = 0;
1023 v_U8_t *pIe = NULL;
1024 v_U8_t addIE[1] = {0};
1025 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -07001026 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001027
1028 genie = vos_mem_malloc(MAX_GENIE_LEN);
1029
1030 if(genie == NULL) {
1031
1032 return -ENOMEM;
1033 }
1034
1035 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1036
1037 if(pIe)
1038 {
1039 /*Copy the wps IE*/
1040 ielen = pIe[1] + 2;
1041 if( ielen <=MAX_GENIE_LEN)
1042 {
1043 vos_mem_copy(genie, pIe, ielen);
1044 }
1045 else
1046 {
1047 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001048 ret = -EINVAL;
1049 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001050 }
1051 total_ielen = ielen;
1052 }
1053
1054#ifdef WLAN_FEATURE_WFD
1055 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1056
1057 if(pIe)
1058 {
1059 ielen = pIe[1] + 2;
1060 if(total_ielen + ielen <= MAX_GENIE_LEN) {
1061 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
1062 }
1063 else {
1064 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001065 ret = -EINVAL;
1066 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 }
1068 total_ielen += ielen;
1069 }
1070#endif
1071
Jeff Johnson295189b2012-06-20 16:38:30 -07001072 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1073
1074 if(pIe)
1075 {
1076 ielen = pIe[1] + 2;
1077 if(total_ielen + ielen <= MAX_GENIE_LEN)
1078 {
1079 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1080 }
1081 else
1082 {
1083 hddLog( VOS_TRACE_LEVEL_ERROR,
1084 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001085 ret = -EINVAL;
1086 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001087 }
1088 total_ielen += ielen;
1089 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001090
1091 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1092 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1093 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1094 {
1095 hddLog(LOGE,
1096 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001097 ret = -EINVAL;
1098 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001099 }
1100
1101 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1102 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1103 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1104 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1105 ==eHAL_STATUS_FAILURE)
1106 {
1107 hddLog(LOGE,
1108 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001109 ret = -EINVAL;
1110 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 }
1112
1113 // Added for ProResp IE
1114 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1115 {
1116 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1117 u8 probe_rsp_ie_len[3] = {0};
1118 u8 counter = 0;
1119 /* Check Probe Resp Length if it is greater then 255 then Store
1120 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1121 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1122 Store More then 255 bytes into One Variable.
1123 */
1124 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1125 {
1126 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1127 {
1128 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1129 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1130 }
1131 else
1132 {
1133 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1134 rem_probe_resp_ie_len = 0;
1135 }
1136 }
1137
1138 rem_probe_resp_ie_len = 0;
1139
1140 if (probe_rsp_ie_len[0] > 0)
1141 {
1142 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1143 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1144 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1145 probe_rsp_ie_len[0], NULL,
1146 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1147 {
1148 hddLog(LOGE,
1149 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001150 ret = -EINVAL;
1151 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001152 }
1153 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1154 }
1155
1156 if (probe_rsp_ie_len[1] > 0)
1157 {
1158 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1159 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1160 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1161 probe_rsp_ie_len[1], NULL,
1162 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1163 {
1164 hddLog(LOGE,
1165 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001166 ret = -EINVAL;
1167 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001168 }
1169 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1170 }
1171
1172 if (probe_rsp_ie_len[2] > 0)
1173 {
1174 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1175 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1176 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1177 probe_rsp_ie_len[2], NULL,
1178 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1179 {
1180 hddLog(LOGE,
1181 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001182 ret = -EINVAL;
1183 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001184 }
1185 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1186 }
1187
1188 if (probe_rsp_ie_len[1] == 0 )
1189 {
1190 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1191 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1192 eANI_BOOLEAN_FALSE) )
1193 {
1194 hddLog(LOGE,
1195 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1196 }
1197 }
1198
1199 if (probe_rsp_ie_len[2] == 0 )
1200 {
1201 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1202 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1203 eANI_BOOLEAN_FALSE) )
1204 {
1205 hddLog(LOGE,
1206 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1207 }
1208 }
1209
1210 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1211 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1212 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1213 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1214 == eHAL_STATUS_FAILURE)
1215 {
1216 hddLog(LOGE,
1217 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001218 ret = -EINVAL;
1219 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001220 }
1221 }
1222 else
1223 {
1224 // Reset WNI_CFG_PROBE_RSP Flags
1225 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1226
1227 hddLog(VOS_TRACE_LEVEL_INFO,
1228 "%s: No Probe Response IE received in set beacon",
1229 __func__);
1230 }
1231
1232 // Added for AssocResp IE
1233 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1234 {
1235 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1236 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1237 params->assocresp_ies_len, NULL,
1238 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1239 {
1240 hddLog(LOGE,
1241 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001242 ret = -EINVAL;
1243 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001244 }
1245
1246 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1247 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1248 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1249 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1250 == eHAL_STATUS_FAILURE)
1251 {
1252 hddLog(LOGE,
1253 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001254 ret = -EINVAL;
1255 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001256 }
1257 }
1258 else
1259 {
1260 hddLog(VOS_TRACE_LEVEL_INFO,
1261 "%s: No Assoc Response IE received in set beacon",
1262 __func__);
1263
1264 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1265 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1266 eANI_BOOLEAN_FALSE) )
1267 {
1268 hddLog(LOGE,
1269 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1270 }
1271 }
1272
Jeff Johnsone7245742012-09-05 17:12:55 -07001273done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001274 vos_mem_free(genie);
1275 return 0;
1276}
Jeff Johnson295189b2012-06-20 16:38:30 -07001277
1278/*
1279 * FUNCTION: wlan_hdd_validate_operation_channel
1280 * called by wlan_hdd_cfg80211_start_bss() and
1281 * wlan_hdd_cfg80211_set_channel()
1282 * This function validates whether given channel is part of valid
1283 * channel list.
1284 */
1285static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1286{
1287
1288 v_U32_t num_ch = 0;
1289 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1290 u32 indx = 0;
1291 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301292 v_U8_t fValidChannel = FALSE, count = 0;
1293 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07001294
1295 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1296
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301297 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07001298 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301299 /* Validate the channel */
1300 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07001301 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301302 if ( channel == rfChannels[count].channelNum )
1303 {
1304 fValidChannel = TRUE;
1305 break;
1306 }
1307 }
1308 if (fValidChannel != TRUE)
1309 {
1310 hddLog(VOS_TRACE_LEVEL_ERROR,
1311 "%s: Invalid Channel [%d]", __func__, channel);
1312 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001313 }
1314 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301315 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001316 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05301317 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1318 valid_ch, &num_ch))
1319 {
1320 hddLog(VOS_TRACE_LEVEL_ERROR,
1321 "%s: failed to get valid channel list", __func__);
1322 return VOS_STATUS_E_FAILURE;
1323 }
1324 for (indx = 0; indx < num_ch; indx++)
1325 {
1326 if (channel == valid_ch[indx])
1327 {
1328 break;
1329 }
1330 }
1331
1332 if (indx >= num_ch)
1333 {
1334 hddLog(VOS_TRACE_LEVEL_ERROR,
1335 "%s: Invalid Channel [%d]", __func__, channel);
1336 return VOS_STATUS_E_FAILURE;
1337 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 }
1339 return VOS_STATUS_SUCCESS;
1340
1341}
1342
Viral Modi3a32cc52013-02-08 11:14:52 -08001343/**
1344 * FUNCTION: wlan_hdd_cfg80211_set_channel
1345 * This function is used to set the channel number
1346 */
1347static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
1348 struct ieee80211_channel *chan,
1349 enum nl80211_channel_type channel_type
1350 )
1351{
1352 v_U32_t num_ch = 0;
1353 u32 channel = 0;
1354 hdd_adapter_t *pAdapter = NULL;
1355 int freq = chan->center_freq; /* freq is in MHZ */
1356
1357 ENTER();
1358
1359 if( NULL == dev )
1360 {
1361 hddLog(VOS_TRACE_LEVEL_ERROR,
1362 "%s: Called with dev = NULL.\n", __func__);
1363 return -ENODEV;
1364 }
1365 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1366
1367 hddLog(VOS_TRACE_LEVEL_INFO,
1368 "%s: device_mode = %d freq = %d \n",__func__,
1369 pAdapter->device_mode, chan->center_freq);
1370 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1371 {
1372 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1373 return -EAGAIN;
1374 }
1375
1376 /*
1377 * Do freq to chan conversion
1378 * TODO: for 11a
1379 */
1380
1381 channel = ieee80211_frequency_to_channel(freq);
1382
1383 /* Check freq range */
1384 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
1385 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
1386 {
1387 hddLog(VOS_TRACE_LEVEL_ERROR,
1388 "%s: Channel [%d] is outside valid range from %d to %d\n",
1389 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
1390 WNI_CFG_CURRENT_CHANNEL_STAMAX);
1391 return -EINVAL;
1392 }
1393
1394 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1395
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05301396 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
1397 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08001398 {
1399 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
1400 {
1401 hddLog(VOS_TRACE_LEVEL_ERROR,
1402 "%s: Invalid Channel [%d] \n", __func__, channel);
1403 return -EINVAL;
1404 }
1405 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1406 "%s: set channel to [%d] for device mode =%d",
1407 __func__, channel,pAdapter->device_mode);
1408 }
1409 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08001410 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08001411 )
1412 {
1413 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1414 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
1415 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1416
1417 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
1418 {
1419 /* Link is up then return cant set channel*/
1420 hddLog( VOS_TRACE_LEVEL_ERROR,
1421 "%s: IBSS Associated, can't set the channel\n", __func__);
1422 return -EINVAL;
1423 }
1424
1425 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
1426 pHddStaCtx->conn_info.operationChannel = channel;
1427 pRoamProfile->ChannelInfo.ChannelList =
1428 &pHddStaCtx->conn_info.operationChannel;
1429 }
1430 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08001431 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08001432 )
1433 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301434 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
1435 {
1436 if(VOS_STATUS_SUCCESS !=
1437 wlan_hdd_validate_operation_channel(pAdapter,channel))
1438 {
1439 hddLog(VOS_TRACE_LEVEL_ERROR,
1440 "%s: Invalid Channel [%d] \n", __func__, channel);
1441 return -EINVAL;
1442 }
1443 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1444 }
1445 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08001446 {
1447 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
1448
1449 /* If auto channel selection is configured as enable/ 1 then ignore
1450 channel set by supplicant
1451 */
1452 if ( cfg_param->apAutoChannelSelection )
1453 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301454 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
1455 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08001456 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
1457 "%s: set channel to auto channel (0) for device mode =%d",
1458 __func__, pAdapter->device_mode);
1459 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05301460 else
1461 {
1462 if(VOS_STATUS_SUCCESS !=
1463 wlan_hdd_validate_operation_channel(pAdapter,channel))
1464 {
1465 hddLog(VOS_TRACE_LEVEL_ERROR,
1466 "%s: Invalid Channel [%d] \n", __func__, channel);
1467 return -EINVAL;
1468 }
1469 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
1470 }
Viral Modi3a32cc52013-02-08 11:14:52 -08001471 }
1472 }
1473 else
1474 {
1475 hddLog(VOS_TRACE_LEVEL_FATAL,
1476 "%s: Invalid device mode failed to set valid channel", __func__);
1477 return -EINVAL;
1478 }
1479 EXIT();
1480 return 0;
1481}
1482
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301483/*
1484 * FUNCTION: wlan_hdd_select_cbmode
1485 * called by wlan_hdd_cfg80211_start_bss() and
1486 * This function selects the cbmode based on primary channel
1487 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001488VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301489{
1490 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001491 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1492 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1493
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301494 if(
1495#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001496 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1497 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301498#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001499 SapHw_mode != eSAP_DOT11_MODE_11n &&
1500 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301501 )
1502 {
1503 return VOS_STATUS_SUCCESS;
1504 }
1505
1506 if (!pConfigIni->nChannelBondingMode5GHz) {
1507 return VOS_STATUS_SUCCESS;
1508 }
1509
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001510 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301511 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1512
1513 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1514
1515#ifdef WLAN_FEATURE_11AC
1516
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001517 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1518 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301519 {
1520 if ( channel== 36 || channel == 52 || channel == 100 ||
1521 channel == 116 || channel == 149 )
1522 {
1523 smeConfig.csrConfig.channelBondingMode5GHz =
1524 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1525 }
1526 else if ( channel == 40 || channel == 56 || channel == 104 ||
1527 channel == 120 || channel == 153 )
1528 {
1529 smeConfig.csrConfig.channelBondingMode5GHz =
1530 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1531 }
1532 else if ( channel == 44 || channel == 60 || channel == 108 ||
1533 channel == 124 || channel == 157 )
1534 {
1535 smeConfig.csrConfig.channelBondingMode5GHz =
1536 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1537 }
1538 else if ( channel == 48 || channel == 64 || channel == 112 ||
1539 channel == 128 || channel == 161 )
1540 {
1541 smeConfig.csrConfig.channelBondingMode5GHz =
1542 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1543 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001544 else if ( channel == 165 )
1545 {
1546 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1547 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301548 }
1549#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001550 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1551 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301552 {
1553 if ( channel== 40 || channel == 48 || channel == 56 ||
1554 channel == 64 || channel == 104 || channel == 112 ||
1555 channel == 120 || channel == 128 || channel == 136 ||
1556 channel == 144 || channel == 153 || channel == 161 )
1557 {
1558 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1559 }
1560 else if ( channel== 36 || channel == 44 || channel == 52 ||
1561 channel == 60 || channel == 100 || channel == 108 ||
1562 channel == 116 || channel == 124 || channel == 132 ||
1563 channel == 140 || channel == 149 || channel == 157 )
1564 {
1565 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1566 }
Shailender Karmuchi84f11f02013-02-12 17:11:45 -08001567 else if ( channel == 165 )
1568 {
1569 smeConfig.csrConfig.channelBondingMode5GHz = 0;
1570 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301571 }
1572 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1573
1574 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1575 return VOS_STATUS_SUCCESS;
1576}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001577
Jeff Johnson295189b2012-06-20 16:38:30 -07001578#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1579static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1580 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001581#else
1582static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1583 struct cfg80211_beacon_data *params,
1584 const u8 *ssid, size_t ssid_len,
1585 enum nl80211_hidden_ssid hidden_ssid)
1586#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001587{
1588 tsap_Config_t *pConfig;
1589 beacon_data_t *pBeacon = NULL;
1590 struct ieee80211_mgmt *pMgmt_frame;
1591 v_U8_t *pIe=NULL;
1592 v_U16_t capab_info;
1593 eCsrAuthType RSNAuthType;
1594 eCsrEncryptionType RSNEncryptType;
1595 eCsrEncryptionType mcRSNEncryptType;
1596 int status = VOS_STATUS_SUCCESS;
1597 tpWLAN_SAPEventCB pSapEventCallback;
1598 hdd_hostapd_state_t *pHostapdState;
1599 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1600 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301601 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001602 struct qc_mac_acl_entry *acl_entry = NULL;
1603 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001604 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001605
1606 ENTER();
1607
1608 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1609
1610 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1611
1612 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1613
1614 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1615
1616 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1617
1618 //channel is already set in the set_channel Call back
1619 //pConfig->channel = pCommitConfig->channel;
1620
1621 /*Protection parameter to enable or disable*/
1622 pConfig->protEnabled =
1623 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1624
1625 pConfig->dtim_period = pBeacon->dtim_period;
1626
1627 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1628 pConfig->dtim_period);
1629
1630
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001631 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001632 {
1633 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001634 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001635 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001637 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001638 pConfig->ieee80211d = 1;
1639 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1640 sme_setRegInfo(hHal, pConfig->countryCode);
1641 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07001642 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001643 else
1644 {
1645 pConfig->ieee80211d = 0;
1646 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05301647 /*
1648 * If auto channel is configured i.e. channel is 0,
1649 * so skip channel validation.
1650 */
1651 if( AUTO_CHANNEL_SELECT != pConfig->channel )
1652 {
1653 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1654 {
1655 hddLog(VOS_TRACE_LEVEL_ERROR,
1656 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1657 return -EINVAL;
1658 }
1659 }
1660 else
1661 {
1662 if(1 != pHddCtx->is_dynamic_channel_range_set)
1663 {
1664 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1665 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
1666 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1667 }
1668 pHddCtx->is_dynamic_channel_range_set = 0;
1669 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001671 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 {
1673 pConfig->ieee80211d = 0;
1674 }
1675 pConfig->authType = eSAP_AUTO_SWITCH;
1676
1677 capab_info = pMgmt_frame->u.beacon.capab_info;
1678
1679 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1680 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1681
1682 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1683
1684 /*Set wps station to configured*/
1685 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1686
1687 if(pIe)
1688 {
1689 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1690 {
1691 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1692 return -EINVAL;
1693 }
1694 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1695 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001696 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001697 /* Check 15 bit of WPS IE as it contain information for wps state
1698 * WPS state
1699 */
1700 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1701 {
1702 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1703 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1704 {
1705 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1706 }
1707 }
1708 }
1709 else
1710 {
1711 pConfig->wps_state = SAP_WPS_DISABLED;
1712 }
1713 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1714
1715 pConfig->RSNWPAReqIELength = 0;
1716 pConfig->pRSNWPAReqIE = NULL;
1717 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1718 WLAN_EID_RSN);
1719 if(pIe && pIe[1])
1720 {
1721 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1722 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1723 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1724 /* The actual processing may eventually be more extensive than
1725 * this. Right now, just consume any PMKIDs that are sent in
1726 * by the app.
1727 * */
1728 status = hdd_softap_unpackIE(
1729 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1730 &RSNEncryptType,
1731 &mcRSNEncryptType,
1732 &RSNAuthType,
1733 pConfig->pRSNWPAReqIE[1]+2,
1734 pConfig->pRSNWPAReqIE );
1735
1736 if( VOS_STATUS_SUCCESS == status )
1737 {
1738 /* Now copy over all the security attributes you have
1739 * parsed out
1740 * */
1741 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1742 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1743 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1744 = RSNEncryptType;
1745 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1746 "EncryptionType = %d mcEncryptionType = %d\n"),
1747 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1748 }
1749 }
1750
1751 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1752 pBeacon->tail, pBeacon->tail_len);
1753
1754 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1755 {
1756 if (pConfig->pRSNWPAReqIE)
1757 {
1758 /*Mixed mode WPA/WPA2*/
1759 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1760 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1761 }
1762 else
1763 {
1764 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1765 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1766 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1767 status = hdd_softap_unpackIE(
1768 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1769 &RSNEncryptType,
1770 &mcRSNEncryptType,
1771 &RSNAuthType,
1772 pConfig->pRSNWPAReqIE[1]+2,
1773 pConfig->pRSNWPAReqIE );
1774
1775 if( VOS_STATUS_SUCCESS == status )
1776 {
1777 /* Now copy over all the security attributes you have
1778 * parsed out
1779 * */
1780 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1781 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1782 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1783 = RSNEncryptType;
1784 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1785 "EncryptionType = %d mcEncryptionType = %d\n"),
1786 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1787 }
1788 }
1789 }
1790
1791 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1792
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001793#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001794 if (params->ssid != NULL)
1795 {
1796 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1797 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1798 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1799 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1800 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001801#else
1802 if (ssid != NULL)
1803 {
1804 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1805 pConfig->SSIDinfo.ssid.length = ssid_len;
1806 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1807 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1808 }
1809#endif
1810
Jeff Johnson295189b2012-06-20 16:38:30 -07001811 vos_mem_copy(pConfig->self_macaddr.bytes,
1812 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1813
1814 /* default value */
1815 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1816 pConfig->num_accept_mac = 0;
1817 pConfig->num_deny_mac = 0;
1818
1819 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1820 pBeacon->tail, pBeacon->tail_len);
1821
1822 /* pIe for black list is following form:
1823 type : 1 byte
1824 length : 1 byte
1825 OUI : 4 bytes
1826 acl type : 1 byte
1827 no of mac addr in black list: 1 byte
1828 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1829 */
1830 if ((pIe != NULL) && (pIe[1] != 0))
1831 {
1832 pConfig->SapMacaddr_acl = pIe[6];
1833 pConfig->num_deny_mac = pIe[7];
1834 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1835 pIe[6], pIe[7]);
1836 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1837 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1838 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1839 for (i = 0; i < pConfig->num_deny_mac; i++)
1840 {
1841 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1842 acl_entry++;
1843 }
1844 }
1845 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1846 pBeacon->tail, pBeacon->tail_len);
1847
1848 /* pIe for white list is following form:
1849 type : 1 byte
1850 length : 1 byte
1851 OUI : 4 bytes
1852 acl type : 1 byte
1853 no of mac addr in white list: 1 byte
1854 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1855 */
1856 if ((pIe != NULL) && (pIe[1] != 0))
1857 {
1858 pConfig->SapMacaddr_acl = pIe[6];
1859 pConfig->num_accept_mac = pIe[7];
1860 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1861 pIe[6], pIe[7]);
1862 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1863 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1864 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1865 for (i = 0; i < pConfig->num_accept_mac; i++)
1866 {
1867 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1868 acl_entry++;
1869 }
1870 }
1871 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1872
Jeff Johnsone7245742012-09-05 17:12:55 -07001873#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001874 /* Overwrite the hostapd setting for HW mode only for 11ac.
1875 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1876 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1877 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1878 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1879 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1880 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1881 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001882 {
1883 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1884 }
1885#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301886
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001887 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1888 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001889 // ht_capab is not what the name conveys,this is used for protection bitmap
1890 pConfig->ht_capab =
1891 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1892
1893 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1894 {
1895 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1896 return -EINVAL;
1897 }
1898
1899 //Uapsd Enabled Bit
1900 pConfig->UapsdEnable =
1901 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1902 //Enable OBSS protection
1903 pConfig->obssProtEnabled =
1904 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1905
1906 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1907 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1908 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1909 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1910 (int)pConfig->channel);
1911 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1912 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1913 pConfig->authType);
1914 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1915 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1916 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1917 pConfig->protEnabled, pConfig->obssProtEnabled);
1918
1919 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1920 {
1921 //Bss already started. just return.
1922 //TODO Probably it should update some beacon params.
1923 hddLog( LOGE, "Bss Already started...Ignore the request");
1924 EXIT();
1925 return 0;
1926 }
1927
1928 pConfig->persona = pHostapdAdapter->device_mode;
1929
1930 pSapEventCallback = hdd_hostapd_SAPEventCB;
1931 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1932 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1933 {
1934 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1935 return -EINVAL;
1936 }
1937
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001938 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001939 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1940
1941 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1942
1943 if (!VOS_IS_STATUS_SUCCESS(status))
1944 {
1945 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1946 ("ERROR: HDD vos wait for single_event failed!!\n"));
1947 VOS_ASSERT(0);
1948 }
1949
1950 //Succesfully started Bss update the state bit.
1951 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1952
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001953#ifdef WLAN_FEATURE_P2P_DEBUG
1954 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1955 {
1956 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1957 {
1958 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1959 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001960 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001961 }
1962 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1963 {
1964 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1965 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001966 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001967 }
1968 }
1969#endif
1970
Jeff Johnson295189b2012-06-20 16:38:30 -07001971 pHostapdState->bCommit = TRUE;
1972 EXIT();
1973
1974 return 0;
1975}
1976
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001977#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001978static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1979 struct net_device *dev,
1980 struct beacon_parameters *params)
1981{
1982 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1983 int status=VOS_STATUS_SUCCESS;
1984
1985 ENTER();
1986
1987 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1988
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001989 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1990 {
1991 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1992 "%s:LOGP in Progress. Ignore!!!", __func__);
1993 return -EAGAIN;
1994 }
1995
Jeff Johnson295189b2012-06-20 16:38:30 -07001996 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07001997 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07001998 )
1999 {
2000 beacon_data_t *old,*new;
2001
2002 old = pAdapter->sessionCtx.ap.beacon;
2003
2004 if (old)
2005 return -EALREADY;
2006
2007 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2008
2009 if(status != VOS_STATUS_SUCCESS)
2010 {
2011 hddLog(VOS_TRACE_LEVEL_FATAL,
2012 "%s:Error!!! Allocating the new beacon\n",__func__);
2013 return -EINVAL;
2014 }
2015
2016 pAdapter->sessionCtx.ap.beacon = new;
2017
2018 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2019 }
2020
2021 EXIT();
2022 return status;
2023}
2024
2025static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
2026 struct net_device *dev,
2027 struct beacon_parameters *params)
2028{
2029 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2030 int status=VOS_STATUS_SUCCESS;
2031
2032 ENTER();
2033
2034 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2035 __func__,pAdapter->device_mode);
2036
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002037 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2038 {
2039 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2040 "%s:LOGP in Progress. Ignore!!!", __func__);
2041 return -EAGAIN;
2042 }
2043
Jeff Johnson295189b2012-06-20 16:38:30 -07002044 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002045 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002046 )
2047 {
2048 beacon_data_t *old,*new;
2049
2050 old = pAdapter->sessionCtx.ap.beacon;
2051
2052 if (!old)
2053 return -ENOENT;
2054
2055 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
2056
2057 if(status != VOS_STATUS_SUCCESS) {
2058 hddLog(VOS_TRACE_LEVEL_FATAL,
2059 "%s: Error!!! Allocating the new beacon\n",__func__);
2060 return -EINVAL;
2061 }
2062
2063 pAdapter->sessionCtx.ap.beacon = new;
2064
2065 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
2066 }
2067
2068 EXIT();
2069 return status;
2070}
2071
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002072#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
2073
2074#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002075static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
2076 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002077#else
2078static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
2079 struct net_device *dev)
2080#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002081{
2082 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07002083 hdd_context_t *pHddCtx = NULL;
2084 hdd_scaninfo_t *pScanInfo = NULL;
2085 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002086 VOS_STATUS status = 0;
2087
2088 ENTER();
2089
2090 if (NULL == pAdapter)
2091 {
2092 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002093 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002094 return -ENODEV;
2095 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002096 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2097 {
2098 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2099 "%s:LOGP in Progress. Ignore!!!", __func__);
2100 return -EAGAIN;
2101 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002102
2103 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2104 if (NULL == pHddCtx)
2105 {
2106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002107 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002108 return -ENODEV;
2109 }
2110
2111 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
2112 if (NULL == staAdapter)
2113 {
2114 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
2115 if (NULL == staAdapter)
2116 {
2117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002118 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002119 return -ENODEV;
2120 }
2121 }
2122
2123 pScanInfo = &pHddCtx->scan_info;
2124
Jeff Johnson295189b2012-06-20 16:38:30 -07002125 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2126 {
2127 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2128 return -EAGAIN;
2129 }
2130
2131 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2132
2133 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2134 __func__,pAdapter->device_mode);
2135
Jeff Johnsone7245742012-09-05 17:12:55 -07002136 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
2137 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002138 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07002139 hdd_abort_mac_scan(staAdapter->pHddCtx);
2140 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08002141 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002142 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2143 if (!status)
2144 {
2145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08002146 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002147 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002148 VOS_ASSERT(pScanInfo->mScanPending);
2149 return 0;
2150 }
2151 }
2152
Jeff Johnson295189b2012-06-20 16:38:30 -07002153 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002154 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002155 )
2156 {
2157 beacon_data_t *old;
2158
2159 old = pAdapter->sessionCtx.ap.beacon;
2160
2161 if (!old)
2162 return -ENOENT;
2163
Jeff Johnson295189b2012-06-20 16:38:30 -07002164 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002165
2166 mutex_lock(&pHddCtx->sap_lock);
2167 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2168 {
2169 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2170 {
2171 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2172
2173 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2174
2175 if (!VOS_IS_STATUS_SUCCESS(status))
2176 {
2177 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2178 ("ERROR: HDD vos wait for single_event failed!!\n"));
2179 VOS_ASSERT(0);
2180 }
2181 }
2182 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2183 }
2184 mutex_unlock(&pHddCtx->sap_lock);
2185
2186 if(status != VOS_STATUS_SUCCESS)
2187 {
2188 hddLog(VOS_TRACE_LEVEL_FATAL,
2189 "%s:Error!!! Stopping the BSS\n",__func__);
2190 return -EINVAL;
2191 }
2192
2193 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2194 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2195 ==eHAL_STATUS_FAILURE)
2196 {
2197 hddLog(LOGE,
2198 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2199 }
2200
2201 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2202 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2203 eANI_BOOLEAN_FALSE) )
2204 {
2205 hddLog(LOGE,
2206 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2207 }
2208
2209 // Reset WNI_CFG_PROBE_RSP Flags
2210 wlan_hdd_reset_prob_rspies(pAdapter);
2211
2212 pAdapter->sessionCtx.ap.beacon = NULL;
2213 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002214#ifdef WLAN_FEATURE_P2P_DEBUG
2215 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2216 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2217 {
2218 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2219 "GO got removed");
2220 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2221 }
2222#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002223 }
2224 EXIT();
2225 return status;
2226}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002227
2228#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2229
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302230static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2231 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002232 struct cfg80211_ap_settings *params)
2233{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302234 hdd_adapter_t *pAdapter;
2235 hdd_context_t *pHddCtx;
2236 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002237
2238 ENTER();
2239
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302240 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002241 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2243 "%s: Device is Null", __func__);
2244 return -ENODEV;
2245 }
2246
2247 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2248 if (NULL == pAdapter)
2249 {
2250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2251 "%s: HDD adapter is Null", __func__);
2252 return -ENODEV;
2253 }
2254
2255 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2256 {
2257 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2258 "%s: HDD adapter magic is invalid", __func__);
2259 return -ENODEV;
2260 }
2261
2262 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2263 if (NULL == pHddCtx)
2264 {
2265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2266 "%s: HDD context is Null", __func__);
2267 return -ENODEV;
2268 }
2269
2270 if (pHddCtx->isLogpInProgress)
2271 {
2272 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2273 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002274 return -EAGAIN;
2275 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302276
2277 if (pHddCtx->isLoadUnloadInProgress)
2278 {
2279 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2280 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2281 return -EAGAIN;
2282 }
2283
2284 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2285 __func__, pAdapter->device_mode);
2286
2287 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002288 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002289 )
2290 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302291 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002292
2293 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302294
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002295 if (old)
2296 return -EALREADY;
2297
2298 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2299
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302300 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002301 {
2302 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302303 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002304 return -EINVAL;
2305 }
2306 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08002307#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2308 wlan_hdd_cfg80211_set_channel(wiphy, dev, params->channel, params->channel_type);
2309#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002310 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2311 params->ssid_len, params->hidden_ssid);
2312 }
2313
2314 EXIT();
2315 return status;
2316}
2317
2318
2319static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2320 struct net_device *dev,
2321 struct cfg80211_beacon_data *params)
2322{
2323 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2324 int status=VOS_STATUS_SUCCESS;
2325
2326 ENTER();
2327
2328 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2329 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002330 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2331 {
2332 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2333 return -EAGAIN;
2334 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002335
2336 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002337 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002338 )
2339 {
2340 beacon_data_t *old,*new;
2341
2342 old = pAdapter->sessionCtx.ap.beacon;
2343
2344 if (!old)
2345 return -ENOENT;
2346
2347 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2348
2349 if(status != VOS_STATUS_SUCCESS) {
2350 hddLog(VOS_TRACE_LEVEL_FATAL,
2351 "%s: Error!!! Allocating the new beacon\n",__func__);
2352 return -EINVAL;
2353 }
2354
2355 pAdapter->sessionCtx.ap.beacon = new;
2356
2357 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2358 }
2359
2360 EXIT();
2361 return status;
2362}
2363
2364#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2365
Jeff Johnson295189b2012-06-20 16:38:30 -07002366
2367static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2368 struct net_device *dev,
2369 struct bss_parameters *params)
2370{
2371 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2372
2373 ENTER();
2374
2375 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2376 __func__,pAdapter->device_mode);
2377
2378 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002379 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002380 )
2381 {
2382 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2383 * want to update this parameter */
2384 if (-1 != params->ap_isolate)
2385 {
2386 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2387 }
2388 }
2389
2390 EXIT();
2391 return 0;
2392}
2393
2394/*
2395 * FUNCTION: wlan_hdd_cfg80211_change_iface
2396 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2397 */
2398int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2399 struct net_device *ndev,
2400 enum nl80211_iftype type,
2401 u32 *flags,
2402 struct vif_params *params
2403 )
2404{
2405 struct wireless_dev *wdev;
2406 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2407 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002408 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002409 tCsrRoamProfile *pRoamProfile = NULL;
2410 eCsrRoamBssType LastBSSType;
2411 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2412 eMib_dot11DesiredBssType connectedBssType;
2413 VOS_STATUS status;
2414
2415 ENTER();
2416
2417 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2418 {
2419 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2420 return -EAGAIN;
2421 }
2422
2423 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2424 __func__, pAdapter->device_mode);
2425
2426 wdev = ndev->ieee80211_ptr;
2427
2428#ifdef WLAN_BTAMP_FEATURE
2429 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2430 (NL80211_IFTYPE_ADHOC == type)||
2431 (NL80211_IFTYPE_AP == type)||
2432 (NL80211_IFTYPE_P2P_GO == type))
2433 {
2434 pHddCtx->isAmpAllowed = VOS_FALSE;
2435 // stop AMP traffic
2436 status = WLANBAP_StopAmp();
2437 if(VOS_STATUS_SUCCESS != status )
2438 {
2439 pHddCtx->isAmpAllowed = VOS_TRUE;
2440 hddLog(VOS_TRACE_LEVEL_FATAL,
2441 "%s: Failed to stop AMP", __func__);
2442 return -EINVAL;
2443 }
2444 }
2445#endif //WLAN_BTAMP_FEATURE
2446 /* Reset the current device mode bit mask*/
2447 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2448
2449 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07002450 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002451 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002452 )
2453 {
2454 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2455 pRoamProfile = &pWextState->roamProfile;
2456 LastBSSType = pRoamProfile->BSSType;
2457
2458 switch (type)
2459 {
2460 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002461 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002462 hddLog(VOS_TRACE_LEVEL_INFO,
2463 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2464 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002465#ifdef WLAN_FEATURE_11AC
2466 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2467 {
2468 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2469 }
2470#endif
2471 pRoamProfile->phyMode =
2472 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002473 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002474 //Check for sub-string p2p to confirm its a p2p interface
2475 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002476 {
2477 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2478 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2479 }
2480 else
2481 {
2482 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002483 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002484 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 break;
2486 case NL80211_IFTYPE_ADHOC:
2487 hddLog(VOS_TRACE_LEVEL_INFO,
2488 "%s: setting interface Type to ADHOC", __func__);
2489 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2490 pRoamProfile->phyMode =
2491 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2492 wdev->iftype = type;
2493 break;
2494
2495 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002496 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002497 {
2498 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2499 "%s: setting interface Type to %s", __func__,
2500 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2501
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002502 //Cancel any remain on channel for GO mode
2503 if (NL80211_IFTYPE_P2P_GO == type)
2504 {
2505 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2506 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002507 if (NL80211_IFTYPE_AP == type)
2508 {
2509 /* As Loading WLAN Driver one interface being created for p2p device
2510 * address. This will take one HW STA and the max number of clients
2511 * that can connect to softAP will be reduced by one. so while changing
2512 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2513 * interface as it is not required in SoftAP mode.
2514 */
2515
2516 // Get P2P Adapter
2517 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2518
2519 if (pP2pAdapter)
2520 {
2521 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2522 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2523 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2524 }
2525 }
2526
Jeff Johnson295189b2012-06-20 16:38:30 -07002527 //De-init the adapter.
2528 hdd_stop_adapter( pHddCtx, pAdapter );
2529 hdd_deinit_adapter( pHddCtx, pAdapter );
2530 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2532 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002533
2534 //Disable BMPS and IMPS if enabled
2535 //before starting Go
2536 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2537 {
2538 if(VOS_STATUS_E_FAILURE ==
2539 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2540 {
2541 //Fail to Exit BMPS
2542 VOS_ASSERT(0);
2543 }
2544 }
2545
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002546 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2547 (pConfig->apRandomBssidEnabled))
2548 {
2549 /* To meet Android requirements create a randomized
2550 MAC address of the form 02:1A:11:Fx:xx:xx */
2551 get_random_bytes(&ndev->dev_addr[3], 3);
2552 ndev->dev_addr[0] = 0x02;
2553 ndev->dev_addr[1] = 0x1A;
2554 ndev->dev_addr[2] = 0x11;
2555 ndev->dev_addr[3] |= 0xF0;
2556 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2557 VOS_MAC_ADDR_SIZE);
2558 pr_info("wlan: Generated HotSpot BSSID "
2559 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2560 ndev->dev_addr[0],
2561 ndev->dev_addr[1],
2562 ndev->dev_addr[2],
2563 ndev->dev_addr[3],
2564 ndev->dev_addr[4],
2565 ndev->dev_addr[5]);
2566 }
2567
Jeff Johnson295189b2012-06-20 16:38:30 -07002568 hdd_set_ap_ops( pAdapter->dev );
2569
2570 status = hdd_init_ap_mode(pAdapter);
2571 if(status != VOS_STATUS_SUCCESS)
2572 {
2573 hddLog(VOS_TRACE_LEVEL_FATAL,
2574 "%s: Error initializing the ap mode", __func__);
2575 return -EINVAL;
2576 }
2577 hdd_set_conparam(1);
2578
Jeff Johnson295189b2012-06-20 16:38:30 -07002579 /*interface type changed update in wiphy structure*/
2580 if(wdev)
2581 {
2582 wdev->iftype = type;
2583 pHddCtx->change_iface = type;
2584 }
2585 else
2586 {
2587 hddLog(VOS_TRACE_LEVEL_ERROR,
2588 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2589 return -EINVAL;
2590 }
2591 goto done;
2592 }
2593
2594 default:
2595 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2596 __func__);
2597 return -EOPNOTSUPP;
2598 }
2599 }
2600 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07002601 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07002602 )
2603 {
2604 switch(type)
2605 {
2606 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002607 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07002608 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002609 hdd_stop_adapter( pHddCtx, pAdapter );
2610 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002611 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002612 //Check for sub-string p2p to confirm its a p2p interface
2613 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002614 {
2615 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2616 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2617 }
2618 else
2619 {
2620 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002621 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002622 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002623 hdd_set_conparam(0);
2624 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002625 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2626 hdd_set_station_ops( pAdapter->dev );
2627 status = hdd_init_station_mode( pAdapter );
2628 if( VOS_STATUS_SUCCESS != status )
2629 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002630 /* In case of JB, for P2P-GO, only change interface will be called,
2631 * This is the right place to enable back bmps_imps()
2632 */
2633 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002634 goto done;
2635 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002636 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002637 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002638 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2639 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002640 goto done;
2641 default:
2642 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2643 __func__);
2644 return -EOPNOTSUPP;
2645
2646 }
2647
2648 }
2649 else
2650 {
2651 return -EOPNOTSUPP;
2652 }
2653
2654
2655 if(pRoamProfile)
2656 {
2657 if ( LastBSSType != pRoamProfile->BSSType )
2658 {
2659 /*interface type changed update in wiphy structure*/
2660 wdev->iftype = type;
2661
2662 /*the BSS mode changed, We need to issue disconnect
2663 if connected or in IBSS disconnect state*/
2664 if ( hdd_connGetConnectedBssType(
2665 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2666 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2667 {
2668 /*need to issue a disconnect to CSR.*/
2669 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2670 if( eHAL_STATUS_SUCCESS ==
2671 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2672 pAdapter->sessionId,
2673 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2674 {
2675 wait_for_completion_interruptible_timeout(
2676 &pAdapter->disconnect_comp_var,
2677 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2678 }
2679 }
2680 }
2681 }
2682
2683done:
2684 /*set bitmask based on updated value*/
2685 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2686#ifdef WLAN_BTAMP_FEATURE
2687 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2688 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2689 {
2690 //we are ok to do AMP
2691 pHddCtx->isAmpAllowed = VOS_TRUE;
2692 }
2693#endif //WLAN_BTAMP_FEATURE
2694 EXIT();
2695 return 0;
2696}
2697
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002698#ifdef FEATURE_WLAN_TDLS
2699static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
2700 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
2701{
2702 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2703 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2704 VOS_STATUS status;
2705
2706 ENTER();
2707
2708 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
2709 {
2710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2711 "Invalid arguments");
2712 return -EINVAL;
2713 }
Hoonki Lee27511902013-03-14 18:19:06 -07002714
2715 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
2716 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
2717 {
2718 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2719 "%s: TDLS mode is disabled OR not enabled in FW."
2720 MAC_ADDRESS_STR " Request declined.",
2721 __func__, MAC_ADDR_ARRAY(mac));
2722 return -ENOTSUPP;
2723 }
2724
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002725 if (pHddCtx->isLogpInProgress)
2726 {
2727 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2728 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07002729 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002730 return -EBUSY;
2731 }
2732
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002733 /* when self is on-going, we dont' want to change link_status */
2734 if ((0 == update) && wlan_hdd_tdls_is_peer_progress(pAdapter, mac))
2735 {
2736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2737 "%s: " MAC_ADDRESS_STR
2738 " TDLS setup is ongoing. Request declined.",
2739 __func__, MAC_ADDR_ARRAY(mac));
2740 return -EPERM;
2741 }
2742
2743 /* when others are on-going, we want to change link_status to idle */
2744 if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002745 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2747 "%s: " MAC_ADDRESS_STR
2748 " TDLS setup is ongoing. Request declined.",
2749 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002750 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002751 }
2752
2753 /* first to check if we reached to maximum supported TDLS peer.
2754 TODO: for now, return -EPERM looks working fine,
2755 but need to check if any other errno fit into this category.*/
2756 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
2757 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2759 "%s: " MAC_ADDRESS_STR
2760 " TDLS Max peer already connected. Request declined.",
2761 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07002762 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002763 }
2764 else
2765 {
2766 hddTdlsPeer_t *pTdlsPeer;
2767 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
2768 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
2769 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
2772 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002773 return -EPERM;
2774 }
2775 }
2776
2777 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
2778
2779 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
2780
2781 if (!update)
2782 {
2783 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2784 pAdapter->sessionId, mac);
2785 }
2786 else
2787 {
2788 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
2789 pAdapter->sessionId, mac, StaParams);
2790 }
2791
2792 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
2793 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
2794
2795 if (!status)
2796 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002797 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002798 "%s: timeout waiting for tdls add station indication",
2799 __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002800 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002801 }
2802 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
2803 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07002804 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002805 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07002806 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002807 }
2808
2809 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07002810
2811error:
2812 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
2813 return -EPERM;
2814
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002815}
2816#endif
2817
Jeff Johnson295189b2012-06-20 16:38:30 -07002818static int wlan_hdd_change_station(struct wiphy *wiphy,
2819 struct net_device *dev,
2820 u8 *mac,
2821 struct station_parameters *params)
2822{
2823 VOS_STATUS status = VOS_STATUS_SUCCESS;
2824 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2825 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002826#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002827 tCsrStaParams StaParams = {0};
2828 u32 set;
2829 tANI_U8 isBufSta = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002830#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002831 ENTER();
2832
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002833 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2834 {
2835 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2836 "%s:LOGP in Progress. Ignore!!!", __func__);
2837 return -EAGAIN;
2838 }
2839
Jeff Johnson295189b2012-06-20 16:38:30 -07002840 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2841
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002842#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002843 StaParams.capability = params->capability;
2844 StaParams.uapsd_queues = params->uapsd_queues;
2845 StaParams.max_sp = params->max_sp;
2846
2847 if (0 != params->ext_capab_len)
2848 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
2849 sizeof(StaParams.extn_capability));
2850
2851 if (NULL != params->ht_capa)
2852 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
2853
2854 StaParams.supported_rates_len = params->supported_rates_len;
2855
2856 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
2857 * The supported_rates array , for all the structures propogating till Add Sta
2858 * to the firmware has to be modified , if the supplicant (ieee80211) is
2859 * modified to send more rates.
2860 */
2861
2862 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
2863 */
2864 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
2865 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
2866
2867 if (0 != StaParams.supported_rates_len) {
2868 int i = 0;
2869 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
2870 StaParams.supported_rates_len);
2871 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2872 "Supported Rates with Length %d", StaParams.supported_rates_len);
2873 for (i=0; i < StaParams.supported_rates_len; i++)
2874 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2875 "[%d]: %0x", i, StaParams.supported_rates[i]);
2876 }
2877
2878 if (NULL != params->vht_capa)
2879 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
2880
2881 set = params->sta_flags_set;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002882#endif
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002883
2884 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2885 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07002886 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002887 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07002888 {
2889 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2890 WLANTL_STA_AUTHENTICATED);
2891
2892 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002893 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002894 return -EINVAL;
2895 }
2896 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002897#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08002898 else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) {
2899 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
2900 if (0 != params->ext_capab_len ) {
2901 /*Define A Macro : TODO Sunil*/
2902 if ((1<<4) & StaParams.extn_capability[3]) {
2903 isBufSta = 1;
2904 }
2905 }
2906 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2907 "%s: TDLS Peer Parameters.", __func__);
2908 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2909 "uapsd_queues: %0x\n", params->uapsd_queues);
2910 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2911 "max_sp: %0x\n", params->max_sp);
2912 if (params->ht_capa) {
2913 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2914 "ht_capa->cap_info: %0x\n", params->ht_capa->cap_info);
2915 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2916 "ht_capa->ampdu_params_info: %0x\n",
2917 params->ht_capa->ampdu_params_info);
2918 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2919 "ht_capa->extended_capabilities: %0x\n",
2920 params->ht_capa->extended_ht_cap_info);
2921 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2922 "ht_capa->tx_BF_cap_info: %0x\n",
2923 params->ht_capa->tx_BF_cap_info);
2924 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2925 "ht_capa->antenna_selection_info: %0x\n",
2926 params->ht_capa->antenna_selection_info);
2927 }
2928 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2929 "params->capability: %0x\n",params->capability);
2930 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2931 "params->ext_capab_len: %0x\n",params->ext_capab_len);
2932 if (0 != params->ext_capab_len )
2933 {
2934 int i =0;
2935 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2936 "Extended capabilities:");
2937 for (i=0; i < params->ext_capab_len; i++)
2938 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2939 "[%d]: %0x", i, params->ext_capab[i]);
2940 }
2941 //status = wlan_hdd_tdls_set_peer_caps( mac, params->uapsd_queues,
2942 // params->max_sp, isBufSta);
2943 if (VOS_STATUS_SUCCESS != status) {
2944 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2945 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
2946 return -EINVAL;
2947 }
2948 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
2949 "ht_capa->cap_info: %0x\n", StaParams.HTCap.capInfo);
2950 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
2951
2952 if (VOS_STATUS_SUCCESS != status) {
2953 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2954 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
2955 return -EINVAL;
2956 }
2957 }
2958 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07002959#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002960
Jeff Johnsone7245742012-09-05 17:12:55 -07002961 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002962 return status;
2963}
2964
2965/*
2966 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2967 * This function is used to get peer station index in IBSS mode
2968 */
2969static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2970{
2971 u8 idx = 0;
2972 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2973 ENTER();
2974 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2975 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2976 {
2977 if ( (0 !=
2978 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2979 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2980 temp, VOS_MAC_ADDR_SIZE)
2981 )
2982 {
2983 return idx;
2984 }
2985 }
2986 return idx;
2987}
2988
2989
2990/*
2991 * FUNCTION: wlan_hdd_cfg80211_add_key
2992 * This function is used to initialize the key information
2993 */
2994#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2995static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2996 struct net_device *ndev,
2997 u8 key_index, bool pairwise,
2998 const u8 *mac_addr,
2999 struct key_params *params
3000 )
3001#else
3002static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
3003 struct net_device *ndev,
3004 u8 key_index, const u8 *mac_addr,
3005 struct key_params *params
3006 )
3007#endif
3008{
3009 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3010 tCsrRoamSetKey setKey;
3011 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3012 int status = 0;
3013 v_U32_t roamId= 0xFF;
3014 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3015 hdd_hostapd_state_t *pHostapdState;
3016 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003017 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003018
3019 ENTER();
3020
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003021 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3022 {
3023 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3024 "%s:LOGP in Progress. Ignore!!!", __func__);
3025 return -EAGAIN;
3026 }
3027
Jeff Johnson295189b2012-06-20 16:38:30 -07003028 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3029 __func__,pAdapter->device_mode);
3030
3031 if (CSR_MAX_NUM_KEY <= key_index)
3032 {
3033 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3034 key_index);
3035
3036 return -EINVAL;
3037 }
3038
3039 hddLog(VOS_TRACE_LEVEL_INFO,
3040 "%s: called with key index = %d & key length %d",
3041 __func__, key_index, params->key_len);
3042
3043 /*extract key idx, key len and key*/
3044 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3045 setKey.keyId = key_index;
3046 setKey.keyLength = params->key_len;
3047 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
3048
3049 switch (params->cipher)
3050 {
3051 case WLAN_CIPHER_SUITE_WEP40:
3052 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
3053 break;
3054
3055 case WLAN_CIPHER_SUITE_WEP104:
3056 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
3057 break;
3058
3059 case WLAN_CIPHER_SUITE_TKIP:
3060 {
3061 u8 *pKey = &setKey.Key[0];
3062 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
3063
3064 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
3065
3066 /*Supplicant sends the 32bytes key in this order
3067
3068 |--------------|----------|----------|
3069 | Tk1 |TX-MIC | RX Mic |
3070 |--------------|----------|----------|
3071 <---16bytes---><--8bytes--><--8bytes-->
3072
3073 */
3074 /*Sme expects the 32 bytes key to be in the below order
3075
3076 |--------------|----------|----------|
3077 | Tk1 |RX-MIC | TX Mic |
3078 |--------------|----------|----------|
3079 <---16bytes---><--8bytes--><--8bytes-->
3080 */
3081 /* Copy the Temporal Key 1 (TK1) */
3082 vos_mem_copy(pKey, params->key,16);
3083
3084 /*Copy the rx mic first*/
3085 vos_mem_copy(&pKey[16],&params->key[24],8);
3086
3087 /*Copy the tx mic */
3088 vos_mem_copy(&pKey[24],&params->key[16],8);
3089
3090
3091 break;
3092 }
3093
3094 case WLAN_CIPHER_SUITE_CCMP:
3095 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
3096 break;
3097
3098#ifdef FEATURE_WLAN_WAPI
3099 case WLAN_CIPHER_SUITE_SMS4:
3100 {
3101 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3102 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
3103 params->key, params->key_len);
3104 return 0;
3105 }
3106#endif
3107#ifdef FEATURE_WLAN_CCX
3108 case WLAN_CIPHER_SUITE_KRK:
3109 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
3110 break;
3111#endif
3112 default:
3113 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
3114 __func__, params->cipher);
3115 return -EOPNOTSUPP;
3116 }
3117
3118 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
3119 __func__, setKey.encType);
3120
3121
3122
3123 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003124 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003125 )
3126 {
3127
3128
3129 if (
3130#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3131 (!pairwise)
3132#else
3133 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3134#endif
3135 )
3136 {
3137 /* set group key*/
3138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08003139 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07003140 __func__, __LINE__);
3141 setKey.keyDirection = eSIR_RX_ONLY;
3142 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3143 }
3144 else
3145 {
3146 /* set pairwise key*/
3147 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3148 "%s- %d: setting pairwise key",
3149 __func__, __LINE__);
3150 setKey.keyDirection = eSIR_TX_RX;
3151 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3152 }
3153
3154 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3155 if( pHostapdState->bssState == BSS_START )
3156 {
3157 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3158
3159 if ( status != eHAL_STATUS_SUCCESS )
3160 {
3161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3162 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3163 __LINE__, status );
3164 }
3165 }
3166
3167 /* Saving WEP keys */
3168 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
3169 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
3170 {
3171 //Save the wep key in ap context. Issue setkey after the BSS is started.
3172 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3173 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
3174 }
3175 else
3176 {
3177 //Save the key in ap context. Issue setkey after the BSS is started.
3178 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3179 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
3180 }
3181 }
3182 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003183 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003184 )
3185 {
3186 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3187 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3188
3189 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
3190
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08003191 pWextState->roamProfile.Keys.defaultIndex = key_index;
3192
3193
Jeff Johnson295189b2012-06-20 16:38:30 -07003194 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
3195 params->key, params->key_len);
3196
3197 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3198
3199 if (!( ( IW_AUTH_KEY_MGMT_802_1X
3200 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3201 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3202 )
3203 &&
3204 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3205 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3206 )
3207 )
3208 {
3209 /* in case of static WEP, macaddr/bssid is not coming from nl80211
3210 * interface, copy bssid for pairwise key and group macaddr for
3211 * group key initialization*/
3212
3213 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
3214
3215 pWextState->roamProfile.negotiatedUCEncryptionType =
3216 pHddStaCtx->conn_info.ucEncryptionType =
3217 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
3218 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
3219 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
3220
3221
3222 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3223 "%s: Negotiated encryption type %d", __func__,
3224 pWextState->roamProfile.negotiatedUCEncryptionType);
3225
3226 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
3227 &pWextState->roamProfile, true);
3228 setKey.keyLength = 0;
3229 setKey.keyDirection = eSIR_TX_RX;
3230
3231#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3232 if (pairwise)
3233 {
3234#endif
3235 if (mac_addr)
3236 {
3237 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3238 }
3239 else
3240 {
3241 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
3242 * and peerMacAddress in case of IBSS*/
3243 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
3244 {
3245 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
3246 if (HDD_MAX_NUM_IBSS_STA != staidx)
3247 {
3248 vos_mem_copy(setKey.peerMac,
3249 &pHddStaCtx->conn_info.peerMacAddress[staidx],
3250 WNI_CFG_BSSID_LEN);
3251
3252 }
3253 else
3254 {
3255 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
3256 __func__);
3257 return -EOPNOTSUPP;
3258 }
3259 }
3260 else
3261 {
3262 vos_mem_copy(setKey.peerMac,
3263 &pHddStaCtx->conn_info.bssId[0],
3264 WNI_CFG_BSSID_LEN);
3265 }
3266 }
3267#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3268 }
3269 else
3270 {
3271 /* set group key*/
3272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3273 "%s- %d: setting Group key",
3274 __func__, __LINE__);
3275 setKey.keyDirection = eSIR_RX_ONLY;
3276 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3277 }
3278#endif
3279 }
3280 else if (
3281#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3282 (!pairwise)
3283#else
3284 (!mac_addr || is_broadcast_ether_addr(mac_addr))
3285#endif
3286 )
3287 {
3288 /* set group key*/
3289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3290 "%s- %d: setting Group key",
3291 __func__, __LINE__);
3292 setKey.keyDirection = eSIR_RX_ONLY;
3293 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3294 }
3295 else
3296 {
3297 /* set pairwise key*/
3298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3299 "%s- %d: setting pairwise key",
3300 __func__, __LINE__);
3301 setKey.keyDirection = eSIR_TX_RX;
3302 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3303 }
3304
3305 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3306 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3307 __func__, setKey.peerMac[0], setKey.peerMac[1],
3308 setKey.peerMac[2], setKey.peerMac[3],
3309 setKey.peerMac[4], setKey.peerMac[5],
3310 setKey.keyDirection);
3311
3312 vos_status = wlan_hdd_check_ula_done(pAdapter);
3313
3314 if ( vos_status != VOS_STATUS_SUCCESS )
3315 {
3316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3317 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
3318 __LINE__, vos_status );
3319
3320 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3321
3322 return -EINVAL;
3323
3324 }
3325
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003326#ifdef WLAN_FEATURE_VOWIFI_11R
3327 /* The supplicant may attempt to set the PTK once pre-authentication is done.
3328 Save the key in the UMAC and include it in the ADD BSS request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003329 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303330 if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003331 {
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05303332 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07003333 }
3334#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003335
3336 /* issue set key request to SME*/
3337 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3338 pAdapter->sessionId, &setKey, &roamId );
3339
3340 if ( 0 != status )
3341 {
3342 hddLog(VOS_TRACE_LEVEL_ERROR,
3343 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3344 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3345 return -EINVAL;
3346 }
3347
3348
3349 /* in case of IBSS as there was no information available about WEP keys during
3350 * IBSS join, group key intialized with NULL key, so re-initialize group key
3351 * with correct value*/
3352 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3353 !( ( IW_AUTH_KEY_MGMT_802_1X
3354 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3355 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3356 )
3357 &&
3358 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3359 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3360 )
3361 )
3362 {
3363 setKey.keyDirection = eSIR_RX_ONLY;
3364 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3365
3366 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3367 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3368 __func__, setKey.peerMac[0], setKey.peerMac[1],
3369 setKey.peerMac[2], setKey.peerMac[3],
3370 setKey.peerMac[4], setKey.peerMac[5],
3371 setKey.keyDirection);
3372
3373 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3374 pAdapter->sessionId, &setKey, &roamId );
3375
3376 if ( 0 != status )
3377 {
3378 hddLog(VOS_TRACE_LEVEL_ERROR,
3379 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3380 __func__, status);
3381 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3382 return -EINVAL;
3383 }
3384 }
3385 }
3386
3387 return 0;
3388}
3389
3390/*
3391 * FUNCTION: wlan_hdd_cfg80211_get_key
3392 * This function is used to get the key information
3393 */
3394#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3395static int wlan_hdd_cfg80211_get_key(
3396 struct wiphy *wiphy,
3397 struct net_device *ndev,
3398 u8 key_index, bool pairwise,
3399 const u8 *mac_addr, void *cookie,
3400 void (*callback)(void *cookie, struct key_params*)
3401 )
3402#else
3403static int wlan_hdd_cfg80211_get_key(
3404 struct wiphy *wiphy,
3405 struct net_device *ndev,
3406 u8 key_index, const u8 *mac_addr, void *cookie,
3407 void (*callback)(void *cookie, struct key_params*)
3408 )
3409#endif
3410{
3411 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3412 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3413 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3414 struct key_params params;
3415
3416 ENTER();
3417
3418 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3419 __func__,pAdapter->device_mode);
3420
3421 memset(&params, 0, sizeof(params));
3422
3423 if (CSR_MAX_NUM_KEY <= key_index)
3424 {
3425 return -EINVAL;
3426 }
3427
3428 switch(pRoamProfile->EncryptionType.encryptionType[0])
3429 {
3430 case eCSR_ENCRYPT_TYPE_NONE:
3431 params.cipher = IW_AUTH_CIPHER_NONE;
3432 break;
3433
3434 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3435 case eCSR_ENCRYPT_TYPE_WEP40:
3436 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3437 break;
3438
3439 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3440 case eCSR_ENCRYPT_TYPE_WEP104:
3441 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3442 break;
3443
3444 case eCSR_ENCRYPT_TYPE_TKIP:
3445 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3446 break;
3447
3448 case eCSR_ENCRYPT_TYPE_AES:
3449 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3450 break;
3451
3452 default:
3453 params.cipher = IW_AUTH_CIPHER_NONE;
3454 break;
3455 }
3456
3457 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3458 params.seq_len = 0;
3459 params.seq = NULL;
3460 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3461 callback(cookie, &params);
3462 return 0;
3463}
3464
3465/*
3466 * FUNCTION: wlan_hdd_cfg80211_del_key
3467 * This function is used to delete the key information
3468 */
3469#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3470static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3471 struct net_device *ndev,
3472 u8 key_index,
3473 bool pairwise,
3474 const u8 *mac_addr
3475 )
3476#else
3477static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3478 struct net_device *ndev,
3479 u8 key_index,
3480 const u8 *mac_addr
3481 )
3482#endif
3483{
3484 int status = 0;
3485
3486 //This code needs to be revisited. There is sme_removeKey API, we should
3487 //plan to use that. After the change to use correct index in setkey,
3488 //it is observed that this is invalidating peer
3489 //key index whenever re-key is done. This is affecting data link.
3490 //It should be ok to ignore del_key.
3491#if 0
3492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3493 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3494 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3495 tCsrRoamSetKey setKey;
3496 v_U32_t roamId= 0xFF;
3497
3498 ENTER();
3499
3500 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3501 __func__,pAdapter->device_mode);
3502
3503 if (CSR_MAX_NUM_KEY <= key_index)
3504 {
3505 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3506 key_index);
3507
3508 return -EINVAL;
3509 }
3510
3511 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3512 setKey.keyId = key_index;
3513
3514 if (mac_addr)
3515 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3516 else
3517 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3518
3519 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3520
3521 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07003522 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07003523 )
3524 {
3525
3526 hdd_hostapd_state_t *pHostapdState =
3527 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3528 if( pHostapdState->bssState == BSS_START)
3529 {
3530 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3531
3532 if ( status != eHAL_STATUS_SUCCESS )
3533 {
3534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3535 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3536 __LINE__, status );
3537 }
3538 }
3539 }
3540 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003541 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003542 )
3543 {
3544 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3545
3546 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3547
3548 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3549 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3550 __func__, setKey.peerMac[0], setKey.peerMac[1],
3551 setKey.peerMac[2], setKey.peerMac[3],
3552 setKey.peerMac[4], setKey.peerMac[5]);
3553 if(pAdapter->sessionCtx.station.conn_info.connState ==
3554 eConnectionState_Associated)
3555 {
3556 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3557 pAdapter->sessionId, &setKey, &roamId );
3558
3559 if ( 0 != status )
3560 {
3561 hddLog(VOS_TRACE_LEVEL_ERROR,
3562 "%s: sme_RoamSetKey failure, returned %d",
3563 __func__, status);
3564 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3565 return -EINVAL;
3566 }
3567 }
3568 }
3569#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003570 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003571 return status;
3572}
3573
3574/*
3575 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3576 * This function is used to set the default tx key index
3577 */
3578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3579static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3580 struct net_device *ndev,
3581 u8 key_index,
3582 bool unicast, bool multicast)
3583#else
3584static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3585 struct net_device *ndev,
3586 u8 key_index)
3587#endif
3588{
3589 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3590 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3591 int status = 0;
3592 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3593
3594 ENTER();
3595
3596 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3597 __func__,pAdapter->device_mode, key_index);
3598
3599 if (CSR_MAX_NUM_KEY <= key_index)
3600 {
3601 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3602 key_index);
3603
3604 return -EINVAL;
3605 }
3606
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003607 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3608 {
3609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3610 "%s:LOGP in Progress. Ignore!!!", __func__);
3611 return -EAGAIN;
3612 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003613
3614 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07003615 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07003616 )
3617 {
3618 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3619 (eCSR_ENCRYPT_TYPE_TKIP !=
3620 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3621 (eCSR_ENCRYPT_TYPE_AES !=
3622 pWextState->roamProfile.EncryptionType.encryptionType[0])
3623 )
3624 {
3625 /* if default key index is not same as previous one,
3626 * then update the default key index */
3627
3628 tCsrRoamSetKey setKey;
3629 v_U32_t roamId= 0xFF;
3630 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3631
3632 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3633 __func__, key_index);
3634
3635 Keys->defaultIndex = (u8)key_index;
3636 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3637 setKey.keyId = key_index;
3638 setKey.keyLength = Keys->KeyLength[key_index];
3639
3640 vos_mem_copy(&setKey.Key[0],
3641 &Keys->KeyMaterial[key_index][0],
3642 Keys->KeyLength[key_index]);
3643
3644 setKey.keyDirection = eSIR_TX_ONLY;
3645
3646 vos_mem_copy(setKey.peerMac,
3647 &pHddStaCtx->conn_info.bssId[0],
3648 WNI_CFG_BSSID_LEN);
3649
3650 setKey.encType =
3651 pWextState->roamProfile.EncryptionType.encryptionType[0];
3652
3653 /* issue set key request */
3654 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3655 pAdapter->sessionId, &setKey, &roamId );
3656
3657 if ( 0 != status )
3658 {
3659 hddLog(VOS_TRACE_LEVEL_ERROR,
3660 "%s: sme_RoamSetKey failed, returned %d", __func__,
3661 status);
3662 return -EINVAL;
3663 }
3664 }
3665 }
3666
3667 /* In SoftAp mode setting key direction for default mode */
3668 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3669 {
3670 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3671 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3672 (eCSR_ENCRYPT_TYPE_AES !=
3673 pWextState->roamProfile.EncryptionType.encryptionType[0])
3674 )
3675 {
3676 /* Saving key direction for default key index to TX default */
3677 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3678 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3679 }
3680 }
3681
3682 return status;
3683}
3684
Jeff Johnson295189b2012-06-20 16:38:30 -07003685/*
3686 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3687 * This function is used to inform the BSS details to nl80211 interface.
3688 */
3689static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3690 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3691{
3692 struct net_device *dev = pAdapter->dev;
3693 struct wireless_dev *wdev = dev->ieee80211_ptr;
3694 struct wiphy *wiphy = wdev->wiphy;
3695 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3696 int chan_no;
3697 int ie_length;
3698 const char *ie;
3699 unsigned int freq;
3700 struct ieee80211_channel *chan;
3701 int rssi = 0;
3702 struct cfg80211_bss *bss = NULL;
3703
3704 ENTER();
3705
3706 if( NULL == pBssDesc )
3707 {
3708 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3709 return bss;
3710 }
3711
3712 chan_no = pBssDesc->channelId;
3713 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3714 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3715
3716 if( NULL == ie )
3717 {
3718 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3719 return bss;
3720 }
3721
3722#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3723 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3724 {
3725 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3726 }
3727 else
3728 {
3729 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3730 }
3731#else
3732 freq = ieee80211_channel_to_frequency(chan_no);
3733#endif
3734
3735 chan = __ieee80211_get_channel(wiphy, freq);
3736
3737 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3738 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3739 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3740 if (bss == NULL)
3741 {
3742 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3743
3744 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3745 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3746 pBssDesc->capabilityInfo,
3747 pBssDesc->beaconInterval, ie, ie_length,
3748 rssi, GFP_KERNEL ));
3749}
3750 else
3751 {
3752 return bss;
3753 }
3754}
3755
3756
3757
3758/*
3759 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3760 * This function is used to inform the BSS details to nl80211 interface.
3761 */
3762struct cfg80211_bss*
3763wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3764 tSirBssDescription *bss_desc
3765 )
3766{
3767 /*
3768 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3769 already exists in bss data base of cfg80211 for that particular BSS ID.
3770 Using cfg80211_inform_bss_frame to update the bss entry instead of
3771 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3772 now there is no possibility to get the mgmt(probe response) frame from PE,
3773 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3774 cfg80211_inform_bss_frame.
3775 */
3776 struct net_device *dev = pAdapter->dev;
3777 struct wireless_dev *wdev = dev->ieee80211_ptr;
3778 struct wiphy *wiphy = wdev->wiphy;
3779 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003780#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3781 qcom_ie_age *qie_age = NULL;
3782 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3783#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003784 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003785#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003786 const char *ie =
3787 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3788 unsigned int freq;
3789 struct ieee80211_channel *chan;
3790 struct ieee80211_mgmt *mgmt =
3791 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3792 struct cfg80211_bss *bss_status = NULL;
3793 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3794 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003795#ifdef WLAN_OPEN_SOURCE
3796 struct timespec ts;
3797#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003798
3799 ENTER();
3800
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003801 if (!mgmt)
3802 return NULL;
3803
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003805
3806#ifdef WLAN_OPEN_SOURCE
3807 /* Android does not want the timestamp from the frame.
3808 Instead it wants a monotonic increasing value */
3809 get_monotonic_boottime(&ts);
3810 mgmt->u.probe_resp.timestamp =
3811 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3812#else
3813 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003814 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3815 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003816
3817#endif
3818
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3820 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003821
3822#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3823 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3824 /* Assuming this is the last IE, copy at the end */
3825 ie_length -=sizeof(qcom_ie_age);
3826 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3827 qie_age->element_id = QCOM_VENDOR_IE_ID;
3828 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3829 qie_age->oui_1 = QCOM_OUI1;
3830 qie_age->oui_2 = QCOM_OUI2;
3831 qie_age->oui_3 = QCOM_OUI3;
3832 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3833 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3834#endif
3835
Jeff Johnson295189b2012-06-20 16:38:30 -07003836 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3837
3838 mgmt->frame_control |=
3839 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3840
3841#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3842 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3843 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3844 {
3845 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3846 }
3847 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3848 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3849
3850 {
3851 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3852 }
3853 else
3854 {
3855 kfree(mgmt);
3856 return NULL;
3857 }
3858#else
3859 freq = ieee80211_channel_to_frequency(chan_no);
3860#endif
3861 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003862 /*when the band is changed on the fly using the GUI, three things are done
3863 * 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)
3864 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3865 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3866 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3867 * and discards the channels correponding to previous band and calls back with zero bss results.
3868 * 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
3869 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3870 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3871 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3872 * So drop the bss and continue to next bss.
3873 */
3874 if(chan == NULL)
3875 {
3876 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3877 return NULL;
3878 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003879 /*To keep the rssi icon of the connected AP in the scan window
3880 *and the rssi icon of the wireless networks in sync
3881 * */
3882 if (( eConnectionState_Associated ==
3883 pAdapter->sessionCtx.station.conn_info.connState ) &&
3884 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3885 pAdapter->sessionCtx.station.conn_info.bssId,
3886 WNI_CFG_BSSID_LEN)))
3887 {
3888 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3889 rssi = (pAdapter->rssi * 100);
3890 }
3891 else
3892 {
3893 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3894 }
3895
3896 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3897 frame_len, rssi, GFP_KERNEL);
3898 kfree(mgmt);
3899 return bss_status;
3900}
3901
3902/*
3903 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3904 * This function is used to update the BSS data base of CFG8011
3905 */
3906struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3907 tCsrRoamInfo *pRoamInfo
3908 )
3909{
3910 tCsrRoamConnectedProfile roamProfile;
3911 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3912 struct cfg80211_bss *bss = NULL;
3913
3914 ENTER();
3915
3916 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3917 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3918
3919 if (NULL != roamProfile.pBssDesc)
3920 {
3921 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3922 &roamProfile);
3923
3924 if (NULL == bss)
3925 {
3926 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3927 __func__);
3928 }
3929
3930 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3931 }
3932 else
3933 {
3934 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3935 __func__);
3936 }
3937 return bss;
3938}
3939
3940/*
3941 * FUNCTION: wlan_hdd_cfg80211_update_bss
3942 */
3943static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3944 hdd_adapter_t *pAdapter
3945 )
3946{
3947 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3948 tCsrScanResultInfo *pScanResult;
3949 eHalStatus status = 0;
3950 tScanResultHandle pResult;
3951 struct cfg80211_bss *bss_status = NULL;
3952
3953 ENTER();
3954
3955 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3956 {
3957 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3958 return -EAGAIN;
3959 }
3960
3961 /*
3962 * start getting scan results and populate cgf80211 BSS database
3963 */
3964 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3965
3966 /* no scan results */
3967 if (NULL == pResult)
3968 {
3969 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3970 return status;
3971 }
3972
3973 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3974
3975 while (pScanResult)
3976 {
3977 /*
3978 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3979 * entry already exists in bss data base of cfg80211 for that
3980 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3981 * bss entry instead of cfg80211_inform_bss, But this call expects
3982 * mgmt packet as input. As of now there is no possibility to get
3983 * the mgmt(probe response) frame from PE, converting bss_desc to
3984 * ieee80211_mgmt(probe response) and passing to c
3985 * fg80211_inform_bss_frame.
3986 * */
3987
3988 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3989 &pScanResult->BssDescriptor);
3990
3991
3992 if (NULL == bss_status)
3993 {
3994 hddLog(VOS_TRACE_LEVEL_INFO,
3995 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3996 }
3997 else
3998 {
3999 cfg80211_put_bss(bss_status);
4000 }
4001
4002 pScanResult = sme_ScanResultGetNext(hHal, pResult);
4003 }
4004
4005 sme_ScanResultPurge(hHal, pResult);
4006
4007 return 0;
4008}
4009
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004010void
4011hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
4012{
4013 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004014 "%02X:%02X:%02X:%02X:%02X:%02X\n",
4015 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
4016 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004017} /****** end hddPrintMacAddr() ******/
4018
4019void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004020hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004021{
4022 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004023 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
4024 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
4025 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
4026 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004027} /****** end hddPrintPmkId() ******/
4028
4029//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
4030//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
4031
4032//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
4033//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
4034
4035#define dump_bssid(bssid) \
4036 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004037 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
4038 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
4039 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004040 }
4041
4042#define dump_pmkid(pMac, pmkid) \
4043 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07004044 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
4045 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
4046 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004047 }
4048
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004049#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004050/*
4051 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
4052 * This function is used to notify the supplicant of a new PMKSA candidate.
4053 */
4054int wlan_hdd_cfg80211_pmksa_candidate_notify(
4055 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
4056 int index, bool preauth )
4057{
Jeff Johnsone7245742012-09-05 17:12:55 -07004058#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004059 struct net_device *dev = pAdapter->dev;
4060
4061 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07004062 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004063
4064 if( NULL == pRoamInfo )
4065 {
4066 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
4067 return -EINVAL;
4068 }
4069
4070 dump_bssid(pRoamInfo->bssid);
4071 cfg80211_pmksa_candidate_notify(dev, index,
4072 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07004073#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004074 return 0;
4075}
4076#endif //FEATURE_WLAN_LFR
4077
Jeff Johnson295189b2012-06-20 16:38:30 -07004078/*
4079 * FUNCTION: hdd_cfg80211_scan_done_callback
4080 * scanning callback function, called after finishing scan
4081 *
4082 */
4083static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
4084 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
4085{
4086 struct net_device *dev = (struct net_device *) pContext;
4087 //struct wireless_dev *wdev = dev->ieee80211_ptr;
4088 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004089 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4090 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004091 struct cfg80211_scan_request *req = NULL;
4092 int ret = 0;
4093
4094 ENTER();
4095
4096 hddLog(VOS_TRACE_LEVEL_INFO,
4097 "%s called with halHandle = %p, pContext = %p,"
4098 "scanID = %d, returned status = %d\n",
4099 __func__, halHandle, pContext, (int) scanId, (int) status);
4100
4101 //Block on scan req completion variable. Can't wait forever though.
4102 ret = wait_for_completion_interruptible_timeout(
4103 &pScanInfo->scan_req_completion_event,
4104 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
4105 if (!ret)
4106 {
4107 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004108 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004109 }
4110
4111 if(pScanInfo->mScanPending != VOS_TRUE)
4112 {
4113 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07004114 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004115 }
4116
4117 /* Check the scanId */
4118 if (pScanInfo->scanId != scanId)
4119 {
4120 hddLog(VOS_TRACE_LEVEL_INFO,
4121 "%s called with mismatched scanId pScanInfo->scanId = %d "
4122 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
4123 (int) scanId);
4124 }
4125
Jeff Johnson295189b2012-06-20 16:38:30 -07004126 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
4127 pAdapter);
4128
4129 if (0 > ret)
4130 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
4131
4132
4133 /* If any client wait scan result through WEXT
4134 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004135 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07004136 {
4137 /* The other scan request waiting for current scan finish
4138 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004139 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004141 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004142 }
4143 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004144 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 {
4146 struct net_device *dev = pAdapter->dev;
4147 union iwreq_data wrqu;
4148 int we_event;
4149 char *msg;
4150
4151 memset(&wrqu, '\0', sizeof(wrqu));
4152 we_event = SIOCGIWSCAN;
4153 msg = NULL;
4154 wireless_send_event(dev, we_event, &wrqu, msg);
4155 }
4156 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004157 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004158
4159 /* Get the Scan Req */
4160 req = pAdapter->request;
4161
4162 if (!req)
4163 {
4164 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004165 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07004166 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07004167 }
4168
4169 /*
4170 * setting up 0, just in case.
4171 */
4172 req->n_ssids = 0;
4173 req->n_channels = 0;
4174 req->ie = 0;
4175
Jeff Johnson295189b2012-06-20 16:38:30 -07004176 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004177 /* Scan is no longer pending */
4178 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004179
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07004180 /*
4181 * cfg80211_scan_done informing NL80211 about completion
4182 * of scanning
4183 */
4184 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004185 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004186
Jeff Johnsone7245742012-09-05 17:12:55 -07004187allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004188 /* release the wake lock at the end of the scan*/
4189 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004190
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004191 /* Acquire wakelock to handle the case where APP's tries to suspend
4192 * immediatly after the driver gets connect request(i.e after scan)
4193 * from supplicant, this result in app's is suspending and not able
4194 * to process the connect request to AP */
4195 hdd_allow_suspend_timeout(100);
4196
Jeff Johnson295189b2012-06-20 16:38:30 -07004197 EXIT();
4198 return 0;
4199}
4200
4201/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004202 * FUNCTION: hdd_isScanAllowed
4203 * Go through each adapter and check if scan allowed
4204 *
4205 */
4206v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4207{
4208 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4209 hdd_station_ctx_t *pHddStaCtx = NULL;
4210 hdd_adapter_t *pAdapter = NULL;
4211 VOS_STATUS status = 0;
4212 v_U8_t staId = 0;
4213 v_U8_t *staMac = NULL;
4214
4215 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4216
4217 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4218 {
4219 pAdapter = pAdapterNode->pAdapter;
4220
4221 if( pAdapter )
4222 {
4223 hddLog(VOS_TRACE_LEVEL_INFO,
4224 "%s: Adapter with device mode %d exists",
4225 __func__, pAdapter->device_mode);
4226 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4227 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4228 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4229 {
4230 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4231 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4232 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4233 {
4234 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4235 hddLog(VOS_TRACE_LEVEL_ERROR,
4236 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4237 "middle of WPS/EAPOL exchange.", __func__,
4238 staMac[0], staMac[1], staMac[2],
4239 staMac[3], staMac[4], staMac[5]);
4240 return VOS_FALSE;
4241 }
4242 }
4243 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4244 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4245 {
4246 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4247 {
4248 if ((pAdapter->aStaInfo[staId].isUsed) &&
4249 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4250 {
4251 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4252
4253 hddLog(VOS_TRACE_LEVEL_ERROR,
4254 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4255 "middle of WPS/EAPOL exchange.", __func__,
4256 staMac[0], staMac[1], staMac[2],
4257 staMac[3], staMac[4], staMac[5]);
4258 return VOS_FALSE;
4259 }
4260 }
4261 }
4262 }
4263 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4264 pAdapterNode = pNext;
4265 }
4266 hddLog(VOS_TRACE_LEVEL_INFO,
4267 "%s: Scan allowed", __func__);
4268 return VOS_TRUE;
4269}
4270
4271/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004272 * FUNCTION: wlan_hdd_cfg80211_scan
4273 * this scan respond to scan trigger and update cfg80211 scan database
4274 * later, scan dump command can be used to recieve scan results
4275 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004276int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4277#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4278 struct net_device *dev,
4279#endif
4280 struct cfg80211_scan_request *request)
4281{
4282#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4283 struct net_device *dev = request->wdev->netdev;
4284#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004285 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4286 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4287 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4288 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4289 tCsrScanRequest scanRequest;
4290 tANI_U8 *channelList = NULL, i;
4291 v_U32_t scanId = 0;
4292 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004293 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004294 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004295
4296 ENTER();
4297
4298 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4299 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004300
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004301 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004302 (eConnectionState_Connecting ==
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004303 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004304 {
4305 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004306 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4307 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004308 return -EBUSY;
4309 }
4310
Jeff Johnson295189b2012-06-20 16:38:30 -07004311#ifdef WLAN_BTAMP_FEATURE
4312 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004313 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07004314 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004315 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004316 "%s: No scanning when AMP is on", __func__);
4317 return -EOPNOTSUPP;
4318 }
4319#endif
4320 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004321 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07004322 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004323 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004324 "%s: Not scanning on device_mode = %d",
4325 __func__, pAdapter->device_mode);
4326 return -EOPNOTSUPP;
4327 }
4328
4329 if (TRUE == pScanInfo->mScanPending)
4330 {
4331 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004332 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07004333 }
4334
4335 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4336 {
4337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4338 "%s:LOGP in Progress. Ignore!!!", __func__);
4339 return -EAGAIN;
4340 }
4341
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004342 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4343 {
4344 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4345 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4346 return -EAGAIN;
4347 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004348 //Don't Allow Scan and return busy if Remain On
4349 //Channel and action frame is pending
4350 //Otherwise Cancel Remain On Channel and allow Scan
4351 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004352 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07004353 {
4354 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4355 return -EBUSY;
4356 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004357#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004358 if (wlan_hdd_tdlsConnectedPeers(pAdapter))
Hoonki Lee93e67ff2013-03-19 15:49:25 -07004359 {
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004360 tANI_U8 staIdx;
4361
4362 for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
4363 {
4364 if (pHddCtx->tdlsConnInfo[staIdx].staId)
4365 {
4366 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4367 ("scan: indicate TDLS teadown (staId %d)"), pHddCtx->tdlsConnInfo[staIdx].staId);
4368 }
4369#ifdef CONFIG_TDLS_IMPLICIT
4370 cfg80211_tdls_oper_request(pAdapter->dev,
4371 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes,
4372 NL80211_TDLS_TEARDOWN,
4373 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON,
4374 GFP_KERNEL);
4375#endif
4376 }
4377 return -EBUSY;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004378 }
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07004379
Gopichand Nakkala681989c2013-03-06 22:27:48 -08004380#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07004381
Jeff Johnson295189b2012-06-20 16:38:30 -07004382 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4383 {
4384 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004385 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004386 return -EAGAIN;
4387 }
4388 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4389 {
4390 hddLog(VOS_TRACE_LEVEL_WARN,
4391 "%s: MAX TM Level Scan not allowed", __func__);
4392 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4393 return -EBUSY;
4394 }
4395 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4396
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004397 /* Check if scan is allowed at this point of time.
4398 */
4399 if (!hdd_isScanAllowed(pHddCtx))
4400 {
4401 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4402 return -EBUSY;
4403 }
4404
Jeff Johnson295189b2012-06-20 16:38:30 -07004405 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4406
4407 if (NULL != request)
4408 {
4409 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4410 (int)request->n_ssids);
4411
4412 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4413 * Becasue of this, driver is assuming that this is not wildcard scan and so
4414 * is not aging out the scan results.
4415 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004416 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004417 {
4418 request->n_ssids = 0;
4419 }
4420
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004421 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004422 {
4423 tCsrSSIDInfo *SsidInfo;
4424 int j;
4425 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4426 /* Allocate num_ssid tCsrSSIDInfo structure */
4427 SsidInfo = scanRequest.SSIDs.SSIDList =
4428 ( tCsrSSIDInfo *)vos_mem_malloc(
4429 request->n_ssids*sizeof(tCsrSSIDInfo));
4430
4431 if(NULL == scanRequest.SSIDs.SSIDList)
4432 {
4433 hddLog(VOS_TRACE_LEVEL_ERROR,
4434 "memory alloc failed SSIDInfo buffer");
4435 return -ENOMEM;
4436 }
4437
4438 /* copy all the ssid's and their length */
4439 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4440 {
4441 /* get the ssid length */
4442 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4443 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4444 SsidInfo->SSID.length);
4445 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4446 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4447 j, SsidInfo->SSID.ssId);
4448 }
4449 /* set the scan type to active */
4450 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4451 }
4452 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4453 {
4454 /* set the scan type to active */
4455 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4456 }
4457 else
4458 {
4459 /*Set the scan type to default type, in this case it is ACTIVE*/
4460 scanRequest.scanType = pScanInfo->scan_mode;
4461 }
4462 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4463 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4464 }
4465 else
4466 {
4467 /* set the scan type to active */
4468 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4469 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4470
4471 /* set min and max channel time to zero */
4472 scanRequest.minChnTime = 0;
4473 scanRequest.maxChnTime = 0;
4474 }
4475
4476 /* set BSSType to default type */
4477 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4478
4479 /*TODO: scan the requested channels only*/
4480
4481 /*Right now scanning all the channels */
4482 if( request )
4483 {
4484 if( request->n_channels )
4485 {
4486 channelList = vos_mem_malloc( request->n_channels );
4487 if( NULL == channelList )
4488 {
4489 status = -ENOMEM;
4490 goto free_mem;
4491 }
4492
4493 for( i = 0 ; i < request->n_channels ; i++ )
4494 channelList[i] = request->channels[i]->hw_value;
4495 }
4496
4497 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4498 scanRequest.ChannelInfo.ChannelList = channelList;
4499
4500 /* set requestType to full scan */
4501 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004502
4503 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4504 * search (Flush on both full scan and social scan but not on single
4505 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4506 */
4507
4508 /* Supplicant does single channel scan after 8-way handshake
4509 * and in that case driver shoudnt flush scan results. If
4510 * driver flushes the scan results here and unfortunately if
4511 * the AP doesnt respond to our probe req then association
4512 * fails which is not desired
4513 */
4514
4515 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4516 {
4517 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4518 pAdapter->sessionId );
4519 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004520
4521 if( request->ie_len )
4522 {
4523 /* save this for future association (join requires this) */
4524 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4525 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4526 pScanInfo->scanAddIE.length = request->ie_len;
4527
4528 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004529 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4530 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004531 )
4532 {
4533 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4534 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4535 }
4536
4537 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4538 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4539
Jeff Johnson295189b2012-06-20 16:38:30 -07004540 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4541 request->ie_len);
4542 if (pP2pIe != NULL)
4543 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004544#ifdef WLAN_FEATURE_P2P_DEBUG
4545 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4546 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4547 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4548 {
4549 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4550 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4551 "Go nego completed to Connection is started");
4552 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4553 "for 8way Handshake");
4554 }
4555 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4556 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4557 {
4558 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4559 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4560 "Disconnected state to Connection is started");
4561 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4562 "for 4way Handshake");
4563 }
4564#endif
4565
Jeff Johnsone7245742012-09-05 17:12:55 -07004566 /* no_cck will be set during p2p find to disable 11b rates */
4567 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004568 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004569 hddLog(VOS_TRACE_LEVEL_INFO,
4570 "%s: This is a P2P Search", __func__);
4571 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004572
Jeff Johnsone7245742012-09-05 17:12:55 -07004573 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4574 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004575 /* set requestType to P2P Discovery */
4576 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004577 }
4578
4579 /*
4580 Skip Dfs Channel in case of P2P Search
4581 if it is set in ini file
4582 */
4583 if(cfg_param->skipDfsChnlInP2pSearch)
4584 {
4585 scanRequest.skipDfsChnlInP2pSearch = 1;
4586 }
4587 else
4588 {
4589 scanRequest.skipDfsChnlInP2pSearch = 0;
4590 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004591
Jeff Johnson295189b2012-06-20 16:38:30 -07004592 }
4593 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004594 }
4595 }
4596
4597 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4598
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004599 /* acquire the wakelock to avoid the apps suspend during the scan. To
4600 * address the following issues.
4601 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4602 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4603 * for long time, this result in apps running at full power for long time.
4604 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4605 * be stuck in full power because of resume BMPS
4606 */
4607 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004608
4609 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004610 pAdapter->sessionId, &scanRequest, &scanId,
4611 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004612
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 if (eHAL_STATUS_SUCCESS != status)
4614 {
4615 hddLog(VOS_TRACE_LEVEL_ERROR,
4616 "%s: sme_ScanRequest returned error %d", __func__, status);
4617 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004618 if(eHAL_STATUS_RESOURCES == status)
4619 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004620 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 -07004621 status = -EBUSY;
4622 } else {
4623 status = -EIO;
4624 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004625 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004626 goto free_mem;
4627 }
4628
4629 pScanInfo->mScanPending = TRUE;
4630 pAdapter->request = request;
4631 pScanInfo->scanId = scanId;
4632
4633 complete(&pScanInfo->scan_req_completion_event);
4634
4635free_mem:
4636 if( scanRequest.SSIDs.SSIDList )
4637 {
4638 vos_mem_free(scanRequest.SSIDs.SSIDList);
4639 }
4640
4641 if( channelList )
4642 vos_mem_free( channelList );
4643
4644 EXIT();
4645
4646 return status;
4647}
4648
4649/*
4650 * FUNCTION: wlan_hdd_cfg80211_connect_start
4651 * This function is used to start the association process
4652 */
4653int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004654 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004655{
4656 int status = 0;
4657 hdd_wext_state_t *pWextState;
4658 v_U32_t roamId;
4659 tCsrRoamProfile *pRoamProfile;
4660 eMib_dot11DesiredBssType connectedBssType;
4661 eCsrAuthType RSNAuthType;
4662
4663 ENTER();
4664
4665 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4666
4667 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4668 {
4669 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4670 return -EINVAL;
4671 }
4672
4673 pRoamProfile = &pWextState->roamProfile;
4674
4675 if (pRoamProfile)
4676 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004677 int ret = 0;
4678 hdd_station_ctx_t *pHddStaCtx;
4679 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4680 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4681
4682 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4683 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4684 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004685 {
4686 /* Issue disconnect to CSR */
4687 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4688 if( eHAL_STATUS_SUCCESS ==
4689 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4690 pAdapter->sessionId,
4691 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4692 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004693 ret = wait_for_completion_interruptible_timeout(
4694 &pAdapter->disconnect_comp_var,
4695 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4696 if (0 == ret)
4697 {
4698 VOS_ASSERT(0);
4699 }
4700 }
4701 }
4702 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4703 {
4704 ret = wait_for_completion_interruptible_timeout(
4705 &pAdapter->disconnect_comp_var,
4706 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4707 if (0 == ret)
4708 {
4709 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004710 }
4711 }
4712
4713 if (HDD_WMM_USER_MODE_NO_QOS ==
4714 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4715 {
4716 /*QoS not enabled in cfg file*/
4717 pRoamProfile->uapsd_mask = 0;
4718 }
4719 else
4720 {
4721 /*QoS enabled, update uapsd mask from cfg file*/
4722 pRoamProfile->uapsd_mask =
4723 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4724 }
4725
4726 pRoamProfile->SSIDs.numOfSSIDs = 1;
4727 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4728 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4729 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4730 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4731 ssid, ssid_len);
4732
4733 if (bssid)
4734 {
4735 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4736 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4737 WNI_CFG_BSSID_LEN);
4738 /* Save BSSID in seperate variable as well, as RoamProfile
4739 BSSID is getting zeroed out in the association process. And in
4740 case of join failure we should send valid BSSID to supplicant
4741 */
4742 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4743 WNI_CFG_BSSID_LEN);
4744 }
4745
4746 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4747 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4748 {
4749 /*set gen ie*/
4750 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4751 /*set auth*/
4752 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4753 }
4754 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4755 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4756 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4757 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4758 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4759 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4760 )
4761 {
4762 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4763 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4764 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4765 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4766 eCSR_AUTH_TYPE_AUTOSWITCH;
4767 pWextState->roamProfile.AuthType.authType[0] =
4768 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4769 }
4770#ifdef FEATURE_WLAN_WAPI
4771 if (pAdapter->wapi_info.nWapiMode)
4772 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004773 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004774 switch (pAdapter->wapi_info.wapiAuthMode)
4775 {
4776 case WAPI_AUTH_MODE_PSK:
4777 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004778 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004779 pAdapter->wapi_info.wapiAuthMode);
4780 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4781 break;
4782 }
4783 case WAPI_AUTH_MODE_CERT:
4784 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004785 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004786 pAdapter->wapi_info.wapiAuthMode);
4787 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4788 break;
4789 }
4790 } // End of switch
4791 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4792 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4793 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004794 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004795 pRoamProfile->AuthType.numEntries = 1;
4796 pRoamProfile->EncryptionType.numEntries = 1;
4797 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4798 pRoamProfile->mcEncryptionType.numEntries = 1;
4799 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4800 }
4801 }
4802#endif /* FEATURE_WLAN_WAPI */
4803 pRoamProfile->csrPersona = pAdapter->device_mode;
4804
Jeff Johnson32d95a32012-09-10 13:15:23 -07004805 if( operatingChannel )
4806 {
4807 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4808 pRoamProfile->ChannelInfo.numOfChannels = 1;
4809 }
4810
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004811 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4812 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4813 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4814 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004815 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4816 */
4817 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4818 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4819 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004820
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4822 pAdapter->sessionId, pRoamProfile, &roamId);
4823
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004824 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304825 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4826
4827 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004828 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4829 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4830 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304831 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004832 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304833 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004834
4835 pRoamProfile->ChannelInfo.ChannelList = NULL;
4836 pRoamProfile->ChannelInfo.numOfChannels = 0;
4837
Jeff Johnson295189b2012-06-20 16:38:30 -07004838 }
4839 else
4840 {
4841 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4842 return -EINVAL;
4843 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004844 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004845 return status;
4846}
4847
4848/*
4849 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4850 * This function is used to set the authentication type (OPEN/SHARED).
4851 *
4852 */
4853static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4854 enum nl80211_auth_type auth_type)
4855{
4856 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4857 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4858
4859 ENTER();
4860
4861 /*set authentication type*/
4862 switch (auth_type)
4863 {
4864 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4865 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004866#ifdef WLAN_FEATURE_VOWIFI_11R
4867 case NL80211_AUTHTYPE_FT:
4868#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004869 hddLog(VOS_TRACE_LEVEL_INFO,
4870 "%s: set authentication type to OPEN", __func__);
4871 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4872 break;
4873
4874 case NL80211_AUTHTYPE_SHARED_KEY:
4875 hddLog(VOS_TRACE_LEVEL_INFO,
4876 "%s: set authentication type to SHARED", __func__);
4877 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4878 break;
4879#ifdef FEATURE_WLAN_CCX
4880 case NL80211_AUTHTYPE_NETWORK_EAP:
4881 hddLog(VOS_TRACE_LEVEL_INFO,
4882 "%s: set authentication type to CCKM WPA", __func__);
4883 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4884 break;
4885#endif
4886
4887
4888 default:
4889 hddLog(VOS_TRACE_LEVEL_ERROR,
4890 "%s: Unsupported authentication type %d", __func__,
4891 auth_type);
4892 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4893 return -EINVAL;
4894 }
4895
4896 pWextState->roamProfile.AuthType.authType[0] =
4897 pHddStaCtx->conn_info.authType;
4898 return 0;
4899}
4900
4901/*
4902 * FUNCTION: wlan_hdd_set_akm_suite
4903 * This function is used to set the key mgmt type(PSK/8021x).
4904 *
4905 */
4906static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4907 u32 key_mgmt
4908 )
4909{
4910 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4911 ENTER();
4912
4913 /*set key mgmt type*/
4914 switch(key_mgmt)
4915 {
4916 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304917#ifdef WLAN_FEATURE_VOWIFI_11R
4918 case WLAN_AKM_SUITE_FT_PSK:
4919#endif
4920 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07004921 __func__);
4922 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4923 break;
4924
4925 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05304926#ifdef WLAN_FEATURE_VOWIFI_11R
4927 case WLAN_AKM_SUITE_FT_8021X:
4928#endif
4929 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07004930 __func__);
4931 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4932 break;
4933#ifdef FEATURE_WLAN_CCX
4934#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4935#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4936 case WLAN_AKM_SUITE_CCKM:
4937 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4938 __func__);
4939 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4940 break;
4941#endif
4942
4943 default:
4944 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4945 __func__, key_mgmt);
4946 return -EINVAL;
4947
4948 }
4949 return 0;
4950}
4951
4952/*
4953 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4954 * This function is used to set the encryption type
4955 * (NONE/WEP40/WEP104/TKIP/CCMP).
4956 */
4957static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4958 u32 cipher,
4959 bool ucast
4960 )
4961{
4962 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4963 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4964 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4965
4966 ENTER();
4967
4968 if (!cipher)
4969 {
4970 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4971 __func__, cipher);
4972 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4973 }
4974 else
4975 {
4976
4977 /*set encryption method*/
4978 switch (cipher)
4979 {
4980 case IW_AUTH_CIPHER_NONE:
4981 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4982 break;
4983
4984 case WLAN_CIPHER_SUITE_WEP40:
4985 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4986 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4987 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4988 else
4989 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4990 break;
4991
4992 case WLAN_CIPHER_SUITE_WEP104:
4993 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4994 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4995 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4996 else
4997 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4998 break;
4999
5000 case WLAN_CIPHER_SUITE_TKIP:
5001 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5002 break;
5003
5004 case WLAN_CIPHER_SUITE_CCMP:
5005 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5006 break;
5007#ifdef FEATURE_WLAN_WAPI
5008 case WLAN_CIPHER_SUITE_SMS4:
5009 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
5010 break;
5011#endif
5012
5013#ifdef FEATURE_WLAN_CCX
5014 case WLAN_CIPHER_SUITE_KRK:
5015 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
5016 break;
5017#endif
5018 default:
5019 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
5020 __func__, cipher);
5021 return -EOPNOTSUPP;
5022 }
5023 }
5024
5025 if (ucast)
5026 {
5027 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
5028 __func__, encryptionType);
5029 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5030 pWextState->roamProfile.EncryptionType.numEntries = 1;
5031 pWextState->roamProfile.EncryptionType.encryptionType[0] =
5032 encryptionType;
5033 }
5034 else
5035 {
5036 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
5037 __func__, encryptionType);
5038 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
5039 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
5040 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
5041 }
5042
5043 return 0;
5044}
5045
5046
5047/*
5048 * FUNCTION: wlan_hdd_cfg80211_set_ie
5049 * This function is used to parse WPA/RSN IE's.
5050 */
5051int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
5052 u8 *ie,
5053 size_t ie_len
5054 )
5055{
5056 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5057 u8 *genie = ie;
5058 v_U16_t remLen = ie_len;
5059#ifdef FEATURE_WLAN_WAPI
5060 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
5061 u16 *tmp;
5062 v_U16_t akmsuiteCount;
5063 int *akmlist;
5064#endif
5065 ENTER();
5066
5067 /* clear previous assocAddIE */
5068 pWextState->assocAddIE.length = 0;
5069 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
5070
5071 while (remLen >= 2)
5072 {
5073 v_U16_t eLen = 0;
5074 v_U8_t elementId;
5075 elementId = *genie++;
5076 eLen = *genie++;
5077 remLen -= 2;
5078
5079 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
5080 __func__, elementId, eLen);
5081
5082 switch ( elementId )
5083 {
5084 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005085 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 -07005086 {
5087 hddLog(VOS_TRACE_LEVEL_ERROR,
5088 "%s: Invalid WPA IE", __func__);
5089 return -EINVAL;
5090 }
5091 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
5092 {
5093 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5094 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
5095 __func__, eLen + 2);
5096
5097 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5098 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005099 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
5100 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005101 VOS_ASSERT(0);
5102 return -ENOMEM;
5103 }
5104 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5105 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5106 pWextState->assocAddIE.length += eLen + 2;
5107
5108 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
5109 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5110 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5111 }
5112 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
5113 {
5114 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
5115 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5116 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
5117 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
5118 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
5119 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005120 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
5121 P2P_OUI_TYPE_SIZE))
5122 /*Consider P2P IE, only for P2P Client */
5123 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5124 {
5125 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5126 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
5127 __func__, eLen + 2);
5128
5129 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5130 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005131 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5132 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 VOS_ASSERT(0);
5134 return -ENOMEM;
5135 }
5136 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
5137 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5138 pWextState->assocAddIE.length += eLen + 2;
5139
5140 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5141 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5142 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005143#ifdef WLAN_FEATURE_WFD
5144 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
5145 WFD_OUI_TYPE_SIZE))
5146 /*Consider WFD IE, only for P2P Client */
5147 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5148 {
5149 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5150 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
5151 __func__, eLen + 2);
5152
5153 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5154 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005155 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5156 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07005157 VOS_ASSERT(0);
5158 return -ENOMEM;
5159 }
5160 // WFD IE is saved to Additional IE ; it should be accumulated to handle
5161 // WPS IE + P2P IE + WFD IE
5162 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5163 pWextState->assocAddIE.length += eLen + 2;
5164
5165 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5166 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5167 }
5168#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005169 /* Appending HS 2.0 Indication Element in Assiciation Request */
5170 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005171 HS20_OUI_TYPE_SIZE)) )
5172 {
5173 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5174 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
5175 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005176
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005177 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5178 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005179 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5180 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005181 VOS_ASSERT(0);
5182 return -ENOMEM;
5183 }
5184 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5185 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005186
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07005187 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5188 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5189 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005190
Jeff Johnson295189b2012-06-20 16:38:30 -07005191 break;
5192 case DOT11F_EID_RSN:
5193 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
5194 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
5195 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
5196 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
5197 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
5198 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005199 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
5200 case DOT11F_EID_EXTCAP:
5201 {
5202 v_U16_t curAddIELen = pWextState->assocAddIE.length;
5203 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
5204 __func__, eLen + 2);
5205
5206 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
5207 {
Jeff Johnson902c9832012-12-10 14:28:09 -08005208 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
5209 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005210 VOS_ASSERT(0);
5211 return -ENOMEM;
5212 }
5213 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
5214 pWextState->assocAddIE.length += eLen + 2;
5215
5216 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
5217 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
5218 break;
5219 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005220#ifdef FEATURE_WLAN_WAPI
5221 case WLAN_EID_WAPI:
5222 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5223 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5224 pAdapter->wapi_info.nWapiMode);
5225 tmp = (u16 *)ie;
5226 tmp = tmp + 2; // Skip element Id and Len, Version
5227 akmsuiteCount = WPA_GET_LE16(tmp);
5228 tmp = tmp + 1;
5229 akmlist = (int *)(tmp);
5230 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5231 {
5232 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5233 }
5234 else
5235 {
5236 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5237 VOS_ASSERT(0);
5238 return -EINVAL;
5239 }
5240
5241 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5242 {
5243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005244 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005245 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5246 }
5247 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5248 {
5249 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005250 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005251 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5252 }
5253 break;
5254#endif
5255 default:
5256 hddLog (VOS_TRACE_LEVEL_ERROR,
5257 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005258 /* when Unknown IE is received we should break and continue
5259 * to the next IE in the buffer instead we were returning
5260 * so changing this to break */
5261 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 }
5263 genie += eLen;
5264 remLen -= eLen;
5265 }
5266 EXIT();
5267 return 0;
5268}
5269
5270/*
5271 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5272 * This function is used to initialize the security
5273 * parameters during connect operation.
5274 */
5275int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5276 struct cfg80211_connect_params *req
5277 )
5278{
5279 int status = 0;
5280 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5281 ENTER();
5282
5283 /*set wpa version*/
5284 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5285
5286 if (req->crypto.wpa_versions)
5287 {
5288 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5289 && ( (req->ie_len)
5290 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5291 // Make sure that it is including a WPA IE.
5292 /* Currently NL is putting WPA version 1 even for open,
5293 * since p2p ie is also put in same buffer.
5294 * */
5295 {
5296 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5297 }
5298 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5299 {
5300 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5301 }
5302 }
5303
5304 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5305 pWextState->wpaVersion);
5306
5307 /*set authentication type*/
5308 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5309
5310 if (0 > status)
5311 {
5312 hddLog(VOS_TRACE_LEVEL_ERROR,
5313 "%s: failed to set authentication type ", __func__);
5314 return status;
5315 }
5316
5317 /*set key mgmt type*/
5318 if (req->crypto.n_akm_suites)
5319 {
5320 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5321 if (0 > status)
5322 {
5323 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5324 __func__);
5325 return status;
5326 }
5327 }
5328
5329 /*set pairwise cipher type*/
5330 if (req->crypto.n_ciphers_pairwise)
5331 {
5332 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5333 req->crypto.ciphers_pairwise[0], true);
5334 if (0 > status)
5335 {
5336 hddLog(VOS_TRACE_LEVEL_ERROR,
5337 "%s: failed to set unicast cipher type", __func__);
5338 return status;
5339 }
5340 }
5341 else
5342 {
5343 /*Reset previous cipher suite to none*/
5344 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5345 if (0 > status)
5346 {
5347 hddLog(VOS_TRACE_LEVEL_ERROR,
5348 "%s: failed to set unicast cipher type", __func__);
5349 return status;
5350 }
5351 }
5352
5353 /*set group cipher type*/
5354 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5355 false);
5356
5357 if (0 > status)
5358 {
5359 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5360 __func__);
5361 return status;
5362 }
5363
5364 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5365 if (req->ie_len)
5366 {
5367 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5368 if ( 0 > status)
5369 {
5370 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5371 __func__);
5372 return status;
5373 }
5374 }
5375
5376 /*incase of WEP set default key information*/
5377 if (req->key && req->key_len)
5378 {
5379 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5380 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5381 )
5382 {
5383 if ( IW_AUTH_KEY_MGMT_802_1X
5384 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5385 {
5386 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5387 __func__);
5388 return -EOPNOTSUPP;
5389 }
5390 else
5391 {
5392 u8 key_len = req->key_len;
5393 u8 key_idx = req->key_idx;
5394
5395 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5396 && (CSR_MAX_NUM_KEY > key_idx)
5397 )
5398 {
5399 hddLog(VOS_TRACE_LEVEL_INFO,
5400 "%s: setting default wep key, key_idx = %hu key_len %hu",
5401 __func__, key_idx, key_len);
5402 vos_mem_copy(
5403 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5404 req->key, key_len);
5405 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5406 (u8)key_len;
5407 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5408 }
5409 }
5410 }
5411 }
5412
5413 return status;
5414}
5415
5416/*
5417 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5418 * This function is used to initialize the security
5419 * parameters during connect operation.
5420 */
5421static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5422 struct net_device *ndev,
5423 struct cfg80211_connect_params *req
5424 )
5425{
5426 int status = 0;
5427 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5428 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5429 hdd_context_t *pHddCtx = NULL;
5430
5431 ENTER();
5432
5433 hddLog(VOS_TRACE_LEVEL_INFO,
5434 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5435
5436 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5437 {
5438 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5439 "%s:LOGP in Progress. Ignore!!!", __func__);
5440 return -EAGAIN;
5441 }
5442
5443#ifdef WLAN_BTAMP_FEATURE
5444 //Infra connect not supported when AMP traffic is on.
5445 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5446 {
5447 hddLog(VOS_TRACE_LEVEL_ERROR,
5448 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005449 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005450 }
5451#endif
5452 /*initialise security parameters*/
5453 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5454
5455 if ( 0 > status)
5456 {
5457 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5458 __func__);
5459 return status;
5460 }
5461
5462 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005463 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5465 (vos_concurrent_sessions_running()))
5466 {
5467 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5468
5469 if (NULL != pVosContext)
5470 {
5471 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5472 if(NULL != pHddCtx)
5473 {
5474 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5475 }
5476 }
5477 }
5478
Mohit Khanna765234a2012-09-11 15:08:35 -07005479 if ( req->channel )
5480 {
5481 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5482 req->ssid_len, req->bssid,
5483 req->channel->hw_value);
5484 }
5485 else
5486 {
5487 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5488 req->ssid_len, req->bssid,
5489 0);
5490 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005491
5492 if (0 > status)
5493 {
5494 //ReEnable BMPS if disabled
5495 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5496 (NULL != pHddCtx))
5497 {
5498 //ReEnable Bmps and Imps back
5499 hdd_enable_bmps_imps(pHddCtx);
5500 }
5501
5502 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5503 return status;
5504 }
5505 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5506 EXIT();
5507 return status;
5508}
5509
5510
5511/*
5512 * FUNCTION: wlan_hdd_cfg80211_disconnect
5513 * This function is used to issue a disconnect request to SME
5514 */
5515static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5516 struct net_device *dev,
5517 u16 reason
5518 )
5519{
5520 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5521 tCsrRoamProfile *pRoamProfile =
5522 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5523 int status = 0;
5524 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005525#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005526 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005527 tANI_U8 staIdx;
5528#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005529
5530 ENTER();
5531
5532 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5533 __func__,pAdapter->device_mode);
5534
5535 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5536 __func__, reason);
5537
5538 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5539 {
5540 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5541 "%s:LOGP in Progress. Ignore!!!",__func__);
5542 return -EAGAIN;
5543 }
5544 if (NULL != pRoamProfile)
5545 {
5546 /*issue disconnect request to SME, if station is in connected state*/
5547 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5548 {
5549 eCsrRoamDisconnectReason reasonCode =
5550 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5551 switch(reason)
5552 {
5553 case WLAN_REASON_MIC_FAILURE:
5554 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5555 break;
5556
5557 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5558 case WLAN_REASON_DISASSOC_AP_BUSY:
5559 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5560 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5561 break;
5562
5563 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5564 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5565 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5566 break;
5567
5568 case WLAN_REASON_DEAUTH_LEAVING:
5569 default:
5570 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5571 break;
5572 }
5573 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5574 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5575 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5576
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005577#ifdef FEATURE_WLAN_TDLS
5578 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005579 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005580 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005581 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
5582 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005583 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005584 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005585 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005586 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005587 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005588 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07005589 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005590 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005591 pAdapter->sessionId,
5592 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -08005593 }
5594 }
5595#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005596 /*issue disconnect*/
5597 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5598 pAdapter->sessionId, reasonCode);
5599
5600 if ( 0 != status)
5601 {
5602 hddLog(VOS_TRACE_LEVEL_ERROR,
5603 "%s csrRoamDisconnect failure, returned %d \n",
5604 __func__, (int)status );
5605 return -EINVAL;
5606 }
5607
5608 wait_for_completion_interruptible_timeout(
5609 &pAdapter->disconnect_comp_var,
5610 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5611
5612
5613 /*stop tx queues*/
5614 netif_tx_disable(dev);
5615 netif_carrier_off(dev);
5616 }
5617 }
5618 else
5619 {
5620 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5621 }
5622
5623 return status;
5624}
5625
5626/*
5627 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5628 * This function is used to initialize the security
5629 * settings in IBSS mode.
5630 */
5631static int wlan_hdd_cfg80211_set_privacy_ibss(
5632 hdd_adapter_t *pAdapter,
5633 struct cfg80211_ibss_params *params
5634 )
5635{
5636 int status = 0;
5637 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5638 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5639 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5640
5641 ENTER();
5642
5643 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5644
5645 if (params->ie_len && ( NULL != params->ie) )
5646 {
5647 if (WLAN_EID_RSN == params->ie[0])
5648 {
5649 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5650 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5651 }
5652 else
5653 {
5654 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5655 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5656 }
5657 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5658
5659 if (0 > status)
5660 {
5661 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5662 __func__);
5663 return status;
5664 }
5665 }
5666
5667 pWextState->roamProfile.AuthType.authType[0] =
5668 pHddStaCtx->conn_info.authType =
5669 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5670
5671 if (params->privacy)
5672 {
5673 /* Security enabled IBSS, At this time there is no information available
5674 * about the security paramters, so initialise the encryption type to
5675 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5676 * The correct security parameters will be updated later in
5677 * wlan_hdd_cfg80211_add_key */
5678 /* Hal expects encryption type to be set inorder
5679 *enable privacy bit in beacons */
5680
5681 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5682 }
5683
5684 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5685 pWextState->roamProfile.EncryptionType.numEntries = 1;
5686 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5687
5688 return status;
5689}
5690
5691/*
5692 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5693 * This function is used to create/join an IBSS
5694 */
5695static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5696 struct net_device *dev,
5697 struct cfg80211_ibss_params *params
5698 )
5699{
5700 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5701 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5702 tCsrRoamProfile *pRoamProfile;
5703 int status;
5704 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5705
5706 ENTER();
5707
5708 hddLog(VOS_TRACE_LEVEL_INFO,
5709 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5710
5711 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5712 {
5713 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5714 "%s:LOGP in Progress. Ignore!!!", __func__);
5715 return -EAGAIN;
5716 }
5717
5718 if (NULL == pWextState)
5719 {
5720 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5721 __func__);
5722 return -EIO;
5723 }
5724
5725 pRoamProfile = &pWextState->roamProfile;
5726
5727 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5728 {
5729 hddLog (VOS_TRACE_LEVEL_ERROR,
5730 "%s Interface type is not set to IBSS \n", __func__);
5731 return -EINVAL;
5732 }
5733
5734 /* Set Channel */
5735 if (NULL != params->channel)
5736 {
5737 u8 channelNum;
5738 if (IEEE80211_BAND_5GHZ == params->channel->band)
5739 {
5740 hddLog(VOS_TRACE_LEVEL_ERROR,
5741 "%s: IBSS join is called with unsupported band %d",
5742 __func__, params->channel->band);
5743 return -EOPNOTSUPP;
5744 }
5745
5746 /* Get channel number */
5747 channelNum =
5748 ieee80211_frequency_to_channel(params->channel->center_freq);
5749
5750 /*TODO: use macro*/
5751 if (14 >= channelNum)
5752 {
5753 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5754 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5755 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5756 int indx;
5757
5758 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5759 validChan, &numChans))
5760 {
5761 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5762 __func__);
5763 return -EOPNOTSUPP;
5764 }
5765
5766 for (indx = 0; indx < numChans; indx++)
5767 {
5768 if (channelNum == validChan[indx])
5769 {
5770 break;
5771 }
5772 }
5773 if (indx >= numChans)
5774 {
5775 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5776 __func__, channelNum);
5777 return -EINVAL;
5778 }
5779 /* Set the Operational Channel */
5780 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5781 channelNum);
5782 pRoamProfile->ChannelInfo.numOfChannels = 1;
5783 pHddStaCtx->conn_info.operationChannel = channelNum;
5784 pRoamProfile->ChannelInfo.ChannelList =
5785 &pHddStaCtx->conn_info.operationChannel;
5786 }
5787 else
5788 {
5789 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5790 __func__, channelNum);
5791 return -EINVAL;
5792 }
5793 }
5794
5795 /* Initialize security parameters */
5796 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5797 if (status < 0)
5798 {
5799 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5800 __func__);
5801 return status;
5802 }
5803
5804 /* Issue connect start */
5805 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005806 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005807
5808 if (0 > status)
5809 {
5810 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5811 return status;
5812 }
5813
5814 return 0;
5815}
5816
5817/*
5818 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5819 * This function is used to leave an IBSS
5820 */
5821static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5822 struct net_device *dev
5823 )
5824{
5825 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5826 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5827 tCsrRoamProfile *pRoamProfile;
5828
5829 ENTER();
5830
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005831 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5832 {
5833 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5834 "%s:LOGP in Progress. Ignore!!!", __func__);
5835 return -EAGAIN;
5836 }
5837
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5839 if (NULL == pWextState)
5840 {
5841 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5842 __func__);
5843 return -EIO;
5844 }
5845
5846 pRoamProfile = &pWextState->roamProfile;
5847
5848 /* Issue disconnect only if interface type is set to IBSS */
5849 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5850 {
5851 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5852 __func__);
5853 return -EINVAL;
5854 }
5855
5856 /* Issue Disconnect request */
5857 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5858 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5859 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5860
5861 return 0;
5862}
5863
5864/*
5865 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5866 * This function is used to set the phy parameters
5867 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5868 */
5869static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5870 u32 changed)
5871{
5872 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5873 tHalHandle hHal = pHddCtx->hHal;
5874
5875 ENTER();
5876
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005877 if ( pHddCtx->isLogpInProgress )
5878 {
5879 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5880 "%s:LOGP in Progress. Ignore!!!", __func__);
5881 return -EAGAIN;
5882 }
5883
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5885 {
5886 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5887 WNI_CFG_RTS_THRESHOLD_STAMAX :
5888 wiphy->rts_threshold;
5889
5890 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5891 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5892 {
5893 hddLog(VOS_TRACE_LEVEL_ERROR,
5894 "%s: Invalid RTS Threshold value %hu",
5895 __func__, rts_threshold);
5896 return -EINVAL;
5897 }
5898
5899 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5900 rts_threshold, ccmCfgSetCallback,
5901 eANI_BOOLEAN_TRUE))
5902 {
5903 hddLog(VOS_TRACE_LEVEL_ERROR,
5904 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5905 __func__, rts_threshold);
5906 return -EIO;
5907 }
5908
5909 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5910 rts_threshold);
5911 }
5912
5913 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5914 {
5915 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5916 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5917 wiphy->frag_threshold;
5918
5919 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5920 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5921 {
5922 hddLog(VOS_TRACE_LEVEL_ERROR,
5923 "%s: Invalid frag_threshold value %hu", __func__,
5924 frag_threshold);
5925 return -EINVAL;
5926 }
5927
5928 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5929 frag_threshold, ccmCfgSetCallback,
5930 eANI_BOOLEAN_TRUE))
5931 {
5932 hddLog(VOS_TRACE_LEVEL_ERROR,
5933 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5934 __func__, frag_threshold);
5935 return -EIO;
5936 }
5937
5938 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5939 frag_threshold);
5940 }
5941
5942 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5943 || (changed & WIPHY_PARAM_RETRY_LONG))
5944 {
5945 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5946 wiphy->retry_short :
5947 wiphy->retry_long;
5948
5949 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5950 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5951 {
5952 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5953 __func__, retry_value);
5954 return -EINVAL;
5955 }
5956
5957 if (changed & WIPHY_PARAM_RETRY_SHORT)
5958 {
5959 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5960 retry_value, ccmCfgSetCallback,
5961 eANI_BOOLEAN_TRUE))
5962 {
5963 hddLog(VOS_TRACE_LEVEL_ERROR,
5964 "%s: ccmCfgSetInt failed for long retry count %hu",
5965 __func__, retry_value);
5966 return -EIO;
5967 }
5968 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5969 __func__, retry_value);
5970 }
5971 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5972 {
5973 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5974 retry_value, ccmCfgSetCallback,
5975 eANI_BOOLEAN_TRUE))
5976 {
5977 hddLog(VOS_TRACE_LEVEL_ERROR,
5978 "%s: ccmCfgSetInt failed for short retry count %hu",
5979 __func__, retry_value);
5980 return -EIO;
5981 }
5982 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5983 __func__, retry_value);
5984 }
5985 }
5986
5987 return 0;
5988}
5989
5990/*
5991 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5992 * This function is used to set the txpower
5993 */
5994static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5995#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5996 enum tx_power_setting type,
5997#else
5998 enum nl80211_tx_power_setting type,
5999#endif
6000 int dbm)
6001{
6002 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6003 tHalHandle hHal = pHddCtx->hHal;
6004 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6005 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
6006
6007 ENTER();
6008
6009 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
6010 dbm, ccmCfgSetCallback,
6011 eANI_BOOLEAN_TRUE))
6012 {
6013 hddLog(VOS_TRACE_LEVEL_ERROR,
6014 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
6015 return -EIO;
6016 }
6017
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006018 if ( pHddCtx->isLogpInProgress )
6019 {
6020 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6021 "%s:LOGP in Progress. Ignore!!!", __func__);
6022 return -EAGAIN;
6023 }
6024
Jeff Johnson295189b2012-06-20 16:38:30 -07006025 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
6026 dbm);
6027
6028 switch(type)
6029 {
6030 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
6031 /* Fall through */
6032 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
6033 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
6034 {
6035 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
6036 __func__);
6037 return -EIO;
6038 }
6039 break;
6040 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
6041 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
6042 __func__);
6043 return -EOPNOTSUPP;
6044 break;
6045 default:
6046 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
6047 __func__, type);
6048 return -EIO;
6049 }
6050
6051 return 0;
6052}
6053
6054/*
6055 * FUNCTION: wlan_hdd_cfg80211_get_txpower
6056 * This function is used to read the txpower
6057 */
6058static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
6059{
6060
6061 hdd_adapter_t *pAdapter;
6062 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6063
Jeff Johnsone7245742012-09-05 17:12:55 -07006064 ENTER();
6065
Jeff Johnson295189b2012-06-20 16:38:30 -07006066 if (NULL == pHddCtx)
6067 {
6068 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
6069 *dbm = 0;
6070 return -ENOENT;
6071 }
6072
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006073 if ( pHddCtx->isLogpInProgress )
6074 {
6075 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6076 "%s:LOGP in Progress. Ignore!!!", __func__);
6077 return -EAGAIN;
6078 }
6079
Jeff Johnson295189b2012-06-20 16:38:30 -07006080 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6081 if (NULL == pAdapter)
6082 {
6083 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
6084 return -ENOENT;
6085 }
6086
6087 wlan_hdd_get_classAstats(pAdapter);
6088 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
6089
Jeff Johnsone7245742012-09-05 17:12:55 -07006090 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006091 return 0;
6092}
6093
6094static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6095 u8* mac, struct station_info *sinfo)
6096{
6097 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6098 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6099 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
6100 tANI_U8 rate_flags;
6101
6102 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
6103 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006104
6105 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
6106 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
6107 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
6108 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
6109 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
6110 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
6111 tANI_U16 maxRate = 0;
6112 tANI_U16 myRate;
6113 tANI_U16 currentRate = 0;
6114 tANI_U8 maxSpeedMCS = 0;
6115 tANI_U8 maxMCSIdx = 0;
6116 tANI_U8 rateFlag = 1;
6117 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006118 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07006119
Jeff Johnsone7245742012-09-05 17:12:55 -07006120 ENTER();
6121
Jeff Johnson295189b2012-06-20 16:38:30 -07006122 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
6123 (0 == ssidlen))
6124 {
6125 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
6126 " Invalid ssidlen, %d", __func__, ssidlen);
6127 /*To keep GUI happy*/
6128 return 0;
6129 }
6130
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006131 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6132 {
6133 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6134 "%s:LOGP in Progress. Ignore!!!", __func__);
6135 return -EAGAIN;
6136 }
6137
Jeff Johnson295189b2012-06-20 16:38:30 -07006138 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
6139 sinfo->filled |= STATION_INFO_SIGNAL;
6140
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006141 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006142 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
6143
6144 //convert to the UI units of 100kbps
6145 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
6146
6147#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006148 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 -07006149 sinfo->signal,
6150 pCfg->reportMaxLinkSpeed,
6151 myRate,
6152 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006153 (int) pCfg->linkSpeedRssiMid,
6154 (int) pCfg->linkSpeedRssiLow,
6155 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07006156#endif //LINKSPEED_DEBUG_ENABLED
6157
6158 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
6159 {
6160 // we do not want to necessarily report the current speed
6161 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
6162 {
6163 // report the max possible speed
6164 rssidx = 0;
6165 }
6166 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
6167 {
6168 // report the max possible speed with RSSI scaling
6169 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
6170 {
6171 // report the max possible speed
6172 rssidx = 0;
6173 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006174 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 {
6176 // report middle speed
6177 rssidx = 1;
6178 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006179 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
6180 {
6181 // report middle speed
6182 rssidx = 2;
6183 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006184 else
6185 {
6186 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006187 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07006188 }
6189 }
6190 else
6191 {
6192 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
6193 hddLog(VOS_TRACE_LEVEL_ERROR,
6194 "%s: Invalid value for reportMaxLinkSpeed: %u",
6195 __func__, pCfg->reportMaxLinkSpeed);
6196 rssidx = 0;
6197 }
6198
6199 maxRate = 0;
6200
6201 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306202 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
6203 OperationalRates, &ORLeng))
6204 {
6205 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6206 /*To keep GUI happy*/
6207 return 0;
6208 }
6209
Jeff Johnson295189b2012-06-20 16:38:30 -07006210 for (i = 0; i < ORLeng; i++)
6211 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006212 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006213 {
6214 /* Validate Rate Set */
6215 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
6216 {
6217 currentRate = supported_data_rate[j].supported_rate[rssidx];
6218 break;
6219 }
6220 }
6221 /* Update MAX rate */
6222 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6223 }
6224
6225 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306226 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
6227 ExtendedRates, &ERLeng))
6228 {
6229 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6230 /*To keep GUI happy*/
6231 return 0;
6232 }
6233
Jeff Johnson295189b2012-06-20 16:38:30 -07006234 for (i = 0; i < ERLeng; i++)
6235 {
Jeff Johnsone7245742012-09-05 17:12:55 -07006236 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006237 {
6238 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
6239 {
6240 currentRate = supported_data_rate[j].supported_rate[rssidx];
6241 break;
6242 }
6243 }
6244 /* Update MAX rate */
6245 maxRate = (currentRate > maxRate)?currentRate:maxRate;
6246 }
6247
6248 /* Get MCS Rate Set -- but only if we are connected at MCS
6249 rates or if we are always reporting max speed or if we have
6250 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006251 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07006252 {
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05306253 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
6254 MCSRates, &MCSLeng))
6255 {
6256 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
6257 /*To keep GUI happy*/
6258 return 0;
6259 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006260 rateFlag = 0;
6261 if (rate_flags & eHAL_TX_RATE_HT40)
6262 {
6263 rateFlag |= 1;
6264 }
6265 if (rate_flags & eHAL_TX_RATE_SGI)
6266 {
6267 rateFlag |= 2;
6268 }
6269
6270 for (i = 0; i < MCSLeng; i++)
6271 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006272 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6273 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006274 {
6275 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6276 {
6277 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6278 break;
6279 }
6280 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006281 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006282 {
6283 maxRate = currentRate;
6284 maxSpeedMCS = 1;
6285 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6286 }
6287 }
6288 }
6289
6290 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006291 if (((maxRate < myRate) && (0 == rssidx)) ||
6292 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006293 {
6294 maxRate = myRate;
6295 if (rate_flags & eHAL_TX_RATE_LEGACY)
6296 {
6297 maxSpeedMCS = 0;
6298 }
6299 else
6300 {
6301 maxSpeedMCS = 1;
6302 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6303 }
6304 }
6305
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006306 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006307 {
6308 sinfo->txrate.legacy = maxRate;
6309#ifdef LINKSPEED_DEBUG_ENABLED
6310 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6311#endif //LINKSPEED_DEBUG_ENABLED
6312 }
6313 else
6314 {
6315 sinfo->txrate.mcs = maxMCSIdx;
6316 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6317 if (rate_flags & eHAL_TX_RATE_SGI)
6318 {
6319 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6320 }
6321 if (rate_flags & eHAL_TX_RATE_HT40)
6322 {
6323 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6324 }
6325#ifdef LINKSPEED_DEBUG_ENABLED
6326 pr_info("Reporting MCS rate %d flags %x\n",
6327 sinfo->txrate.mcs,
6328 sinfo->txrate.flags );
6329#endif //LINKSPEED_DEBUG_ENABLED
6330 }
6331 }
6332 else
6333 {
6334 // report current rate instead of max rate
6335
6336 if (rate_flags & eHAL_TX_RATE_LEGACY)
6337 {
6338 //provide to the UI in units of 100kbps
6339 sinfo->txrate.legacy = myRate;
6340#ifdef LINKSPEED_DEBUG_ENABLED
6341 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6342#endif //LINKSPEED_DEBUG_ENABLED
6343 }
6344 else
6345 {
6346 //must be MCS
6347 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6348 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6349 if (rate_flags & eHAL_TX_RATE_SGI)
6350 {
6351 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6352 }
6353 if (rate_flags & eHAL_TX_RATE_HT40)
6354 {
6355 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6356 }
6357#ifdef LINKSPEED_DEBUG_ENABLED
6358 pr_info("Reporting actual MCS rate %d flags %x\n",
6359 sinfo->txrate.mcs,
6360 sinfo->txrate.flags );
6361#endif //LINKSPEED_DEBUG_ENABLED
6362 }
6363 }
6364 sinfo->filled |= STATION_INFO_TX_BITRATE;
6365
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006366 sinfo->tx_packets =
6367 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6368 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6369 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6370 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6371
6372 sinfo->tx_retries =
6373 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6374 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6375 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6376 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6377
6378 sinfo->tx_failed =
6379 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6380 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6381 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6382 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6383
6384 sinfo->filled |=
6385 STATION_INFO_TX_PACKETS |
6386 STATION_INFO_TX_RETRIES |
6387 STATION_INFO_TX_FAILED;
6388
6389 EXIT();
6390 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006391}
6392
6393static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6394 struct net_device *dev, bool mode, v_SINT_t timeout)
6395{
6396 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6397 VOS_STATUS vos_status;
6398
Jeff Johnsone7245742012-09-05 17:12:55 -07006399 ENTER();
6400
Jeff Johnson295189b2012-06-20 16:38:30 -07006401 if (NULL == pAdapter)
6402 {
6403 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6404 return -ENODEV;
6405 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006406 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6407 {
6408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6409 "%s:LOGP in Progress. Ignore!!!", __func__);
6410 return -EAGAIN;
6411 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006412
6413 /**The get power cmd from the supplicant gets updated by the nl only
6414 *on successful execution of the function call
6415 *we are oppositely mapped w.r.t mode in the driver
6416 **/
6417 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6418
Jeff Johnsone7245742012-09-05 17:12:55 -07006419 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006420 if (VOS_STATUS_E_FAILURE == vos_status)
6421 {
6422 return -EINVAL;
6423 }
6424 return 0;
6425}
6426
6427
6428#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6429static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6430 struct net_device *netdev,
6431 u8 key_index)
6432{
Jeff Johnsone7245742012-09-05 17:12:55 -07006433 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006434 return 0;
6435}
6436#endif //LINUX_VERSION_CODE
6437
6438#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6439static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6440 struct net_device *dev,
6441 struct ieee80211_txq_params *params)
6442{
Jeff Johnsone7245742012-09-05 17:12:55 -07006443 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006444 return 0;
6445}
6446#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6447static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6448 struct ieee80211_txq_params *params)
6449{
Jeff Johnsone7245742012-09-05 17:12:55 -07006450 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006451 return 0;
6452}
6453#endif //LINUX_VERSION_CODE
6454
6455static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6456 struct net_device *dev, u8 *mac)
6457{
6458 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006459 VOS_STATUS vos_status;
6460 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006461
Jeff Johnsone7245742012-09-05 17:12:55 -07006462 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006463 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6464 {
6465 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6466 return -EINVAL;
6467 }
6468
6469 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6470 {
6471 hddLog( LOGE,
6472 "%s: Wlan Load/Unload is in progress", __func__);
6473 return -EBUSY;
6474 }
6475
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006476 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6477 {
6478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6479 "%s:LOGP in Progress. Ignore!!!", __func__);
6480 return -EAGAIN;
6481 }
6482
Jeff Johnson295189b2012-06-20 16:38:30 -07006483 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006484 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 )
6486 {
6487 if( NULL == mac )
6488 {
6489 v_U16_t i;
6490 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6491 {
6492 if(pAdapter->aStaInfo[i].isUsed)
6493 {
6494 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6495 hddLog(VOS_TRACE_LEVEL_INFO,
6496 "%s: Delete STA with MAC::"
6497 "%02x:%02x:%02x:%02x:%02x:%02x",
6498 __func__,
6499 macAddr[0], macAddr[1], macAddr[2],
6500 macAddr[3], macAddr[4], macAddr[5]);
6501 hdd_softap_sta_deauth(pAdapter, macAddr);
6502 }
6503 }
6504 }
6505 else
6506 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006507
6508 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6509 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6510 {
6511 hddLog(VOS_TRACE_LEVEL_INFO,
6512 "%s: Skip this DEL STA as this is not used::"
6513 "%02x:%02x:%02x:%02x:%02x:%02x",
6514 __func__,
6515 mac[0], mac[1], mac[2],
6516 mac[3], mac[4], mac[5]);
6517 return -ENOENT;
6518 }
6519
6520 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6521 {
6522 hddLog(VOS_TRACE_LEVEL_INFO,
6523 "%s: Skip this DEL STA as deauth is in progress::"
6524 "%02x:%02x:%02x:%02x:%02x:%02x",
6525 __func__,
6526 mac[0], mac[1], mac[2],
6527 mac[3], mac[4], mac[5]);
6528 return -ENOENT;
6529 }
6530
6531 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6532
Jeff Johnson295189b2012-06-20 16:38:30 -07006533 hddLog(VOS_TRACE_LEVEL_INFO,
6534 "%s: Delete STA with MAC::"
6535 "%02x:%02x:%02x:%02x:%02x:%02x",
6536 __func__,
6537 mac[0], mac[1], mac[2],
6538 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006539
6540 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6541 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6542 {
6543 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6544 hddLog(VOS_TRACE_LEVEL_INFO,
6545 "%s: STA removal failed for ::"
6546 "%02x:%02x:%02x:%02x:%02x:%02x",
6547 __func__,
6548 mac[0], mac[1], mac[2],
6549 mac[3], mac[4], mac[5]);
6550 return -ENOENT;
6551 }
6552
Jeff Johnson295189b2012-06-20 16:38:30 -07006553 }
6554 }
6555
6556 EXIT();
6557
6558 return 0;
6559}
6560
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006561static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6562 struct net_device *dev, u8 *mac, struct station_parameters *params)
6563{
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006564 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006565#ifdef FEATURE_WLAN_TDLS
6566 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006567 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006568 mask = params->sta_flags_mask;
6569
6570 set = params->sta_flags_set;
6571
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006572#ifdef WLAN_FEATURE_TDLS_DEBUG
6573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6574 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
6575 __func__, mask, set, MAC_ADDR_ARRAY(mac));
6576#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006577
6578 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6579 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006580 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006581 }
6582 }
6583#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006584 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006585}
6586
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006587
6588#ifdef FEATURE_WLAN_LFR
6589static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006590 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006591{
6592#define MAX_PMKSAIDS_IN_CACHE 8
6593 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006594 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006595 tANI_U32 j=0;
6596 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6597 tHalHandle halHandle;
6598 eHalStatus result;
6599 tANI_U8 BSSIDMatched = 0;
6600
Jeff Johnsone7245742012-09-05 17:12:55 -07006601 ENTER();
6602
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006603 // Validate pAdapter
6604 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6605 {
6606 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6607 return -EINVAL;
6608 }
6609
6610 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6611 {
6612 hddLog( LOGE,
6613 "%s: Wlan Load/Unload is in progress", __func__);
6614 return -EBUSY;
6615 }
6616
6617 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6618 {
6619 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6620 "%s:LOGP in Progress. Ignore!!!", __func__);
6621 return -EAGAIN;
6622 }
6623
6624 // Retrieve halHandle
6625 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6626
6627 for (j = 0; j < i; j++)
6628 {
6629 if(vos_mem_compare(PMKIDCache[j].BSSID,
6630 pmksa->bssid, WNI_CFG_BSSID_LEN))
6631 {
6632 /* BSSID matched previous entry. Overwrite it. */
6633 BSSIDMatched = 1;
6634 vos_mem_copy(PMKIDCache[j].BSSID,
6635 pmksa->bssid, WNI_CFG_BSSID_LEN);
6636 vos_mem_copy(PMKIDCache[j].PMKID,
6637 pmksa->pmkid,
6638 CSR_RSN_PMKID_SIZE);
6639 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006640 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006641 dump_bssid(pmksa->bssid);
6642 dump_pmkid(halHandle, pmksa->pmkid);
6643 break;
6644 }
6645 }
6646
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006647 /* Check we compared all entries,if then take the first slot now */
6648 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6649
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006650 if (!BSSIDMatched)
6651 {
6652 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6653 vos_mem_copy(PMKIDCache[i].BSSID,
6654 pmksa->bssid, ETHER_ADDR_LEN);
6655 vos_mem_copy(PMKIDCache[i].PMKID,
6656 pmksa->pmkid,
6657 CSR_RSN_PMKID_SIZE);
6658 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006659 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006660 dump_bssid(pmksa->bssid);
6661 dump_pmkid(halHandle, pmksa->pmkid);
6662 // Increment the HDD Local Cache index
6663 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6664 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6665 }
6666
6667
6668 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6669 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006670 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006671 hddLog(VOS_TRACE_LEVEL_FATAL, "%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 // Finally set the PMKSA ID Cache in CSR
6674 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6675 PMKIDCache,
6676 i );
6677 return 0;
6678}
6679
6680
6681static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006682 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006683{
Jeff Johnsone7245742012-09-05 17:12:55 -07006684 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006685 // TODO: Implement this later.
6686 return 0;
6687}
6688
6689static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6690{
Jeff Johnsone7245742012-09-05 17:12:55 -07006691 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006692 // TODO: Implement this later.
6693 return 0;
6694}
6695#endif
6696
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006697#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6698static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6699 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6700{
6701 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6702 hdd_station_ctx_t *pHddStaCtx;
6703
6704 if (NULL == pAdapter)
6705 {
6706 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6707 return -ENODEV;
6708 }
6709
6710 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6711
6712 // Added for debug on reception of Re-assoc Req.
6713 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6714 {
6715 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6716 ftie->ie_len);
6717 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6718 }
6719
6720#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6721 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6722 ftie->ie_len);
6723#endif
6724
6725 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +05306726 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6727 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006728 ftie->ie_len);
6729 return 0;
6730}
6731#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006732
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006733#ifdef FEATURE_WLAN_TDLS
6734static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6735 u8 *peer, u8 action_code, u8 dialog_token,
6736 u16 status_code, const u8 *buf, size_t len)
6737{
6738
6739 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6740 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006741 u8 peerMac[6];
6742 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006743 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -08006744 int responder;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006745
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006746 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006747 {
6748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6749 "Invalid arguments");
6750 return -EINVAL;
6751 }
6752
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006753 if (pHddCtx->isLogpInProgress)
6754 {
6755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6756 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006757 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006758 return -EBUSY;
6759 }
6760
Hoonki Lee27511902013-03-14 18:19:06 -07006761 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006762 {
Hoonki Lee27511902013-03-14 18:19:06 -07006763 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6764 "%s: TDLS mode is disabled OR not enabled in FW."
6765 MAC_ADDRESS_STR " action %d declined.",
6766 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006767 return -ENOTSUPP;
6768 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006769
Hoonki Lee27511902013-03-14 18:19:06 -07006770 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
6771 (SIR_MAC_TDLS_DIS_RSP == action_code))
6772 {
6773 wlan_hdd_tdls_set_cap (pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
6774 }
6775
6776 /* other than teardown frame, other mgmt frames are not sent if disabled */
6777 if (SIR_MAC_TDLS_TEARDOWN != action_code)
6778 {
6779 /* if tdls_mode is disabled to respond to peer's request */
6780 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
6781 {
6782 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6783 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006784 " TDLS mode is disabled. action %d declined.",
6785 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -07006786
6787 return -ENOTSUPP;
6788 }
6789 }
6790
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006791 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
6792 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006793 if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006794 {
6795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006796 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006797 " TDLS setup is ongoing. action %d declined.",
6798 __func__, MAC_ADDR_ARRAY(peer), action_code);
6799 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006800 }
6801 }
6802
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006803 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
6804 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -08006805 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006806 if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers(pAdapter))
Lee Hoonkic1262f22013-01-24 21:59:00 -08006807 {
6808 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6809 we return error code at 'add_station()'. Hence we have this
6810 check again in addtion to add_station().
6811 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006812 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -08006813 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6815 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006816 " TDLS Max peer already connected. action %d declined.",
6817 __func__, MAC_ADDR_ARRAY(peer), action_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006818 goto error;
Lee Hoonkic1262f22013-01-24 21:59:00 -08006819 }
6820 else
6821 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006822 /* maximum reached. tweak to send error code to peer and return
6823 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006824 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6826 "%s: " MAC_ADDRESS_STR
6827 " TDLS Max peer already connected send response status %d",
6828 __func__, MAC_ADDR_ARRAY(peer), status_code);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006829 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006830 /* fall through to send setup resp with failure status
6831 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -08006832 }
6833 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006834 else
6835 {
6836 hddTdlsPeer_t *pTdlsPeer;
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006837 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006838 if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
6839 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006841 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
6842 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006843 return -EPERM;
6844 }
6845 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006846 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006847 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006848
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006849#ifdef WLAN_FEATURE_TDLS_DEBUG
6850 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006851 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %d",
6852 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
6853 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006854#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006855
Hoonki Leea34dd892013-02-05 22:56:02 -08006856 /*Except teardown responder will not be used so just make 0*/
6857 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006858 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -08006859 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006860 responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac);
6861 if(-1 == responder)
Hoonki Leea34dd892013-02-05 22:56:02 -08006862 {
6863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006864 "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d",
6865 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
Hoonki Leea34dd892013-02-05 22:56:02 -08006866 dialog_token, status_code, len);
6867 return -EPERM;
6868 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006869 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006870
Gopichand Nakkala05922802013-03-14 12:23:19 -07006871 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6872 because we already know that this transaction will be failed,
6873 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6874 to be safe, do not change the state mahine.
6875 */
6876 if (max_sta_failed == 0 &&
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006877 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08006878 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_CONNECTING);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006879
6880 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
6881
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006882 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Hoonki Leea34dd892013-02-05 22:56:02 -08006883 peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006884
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006885 if (VOS_STATUS_SUCCESS != status)
6886 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006887 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6888 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006889 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006890 }
6891
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006892 /* not block discovery request, as it is called from timer callback */
6893 if (SIR_MAC_TDLS_DIS_REQ != action_code)
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006894 {
Pervinder Singhb4638422013-03-04 22:51:36 -08006895 long rc;
6896
6897 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006898 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006899
Pervinder Singhb4638422013-03-04 22:51:36 -08006900 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006901 {
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006902 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pervinder Singhb4638422013-03-04 22:51:36 -08006903 "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu",
6904 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006905 return -EPERM;
Gopichand Nakkalab88f6772013-02-27 18:12:56 -08006906 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006907 }
6908
Gopichand Nakkala05922802013-03-14 12:23:19 -07006909 if (max_sta_failed)
6910 return max_sta_failed;
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006911
Hoonki Leea34dd892013-02-05 22:56:02 -08006912 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
6913 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006914 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006915 }
6916 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
6917 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006918 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -08006919 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006920
6921 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006922error:
6923 /* max_sta_failed ; we didn't set to CONNECTING for this case,
6924 because we already know that this transaction will be failed,
6925 but we weren't sure if supplicant call DISABLE_LINK or not. So,
6926 to be safe, do not change the state mahine.
6927 */
6928 if(max_sta_failed == 0 &&
6929 (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
6930 wlan_hdd_tdls_set_link_status(pAdapter, peerMac, eTDLS_LINK_IDLE);
6931 return -EPERM;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006932}
6933
6934static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6935 u8 *peer, enum nl80211_tdls_operation oper)
6936{
6937 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6938 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006939#ifdef WLAN_FEATURE_TDLS_DEBUG
6940 const char *tdls_oper_str[]= {
6941 "NL80211_TDLS_DISCOVERY_REQ",
6942 "NL80211_TDLS_SETUP",
6943 "NL80211_TDLS_TEARDOWN",
6944 "NL80211_TDLS_ENABLE_LINK",
6945 "NL80211_TDLS_DISABLE_LINK",
6946 "NL80211_TDLS_UNKONW_OPER"};
6947#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006948
6949 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6950 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006952 "Invalid arguments");
6953 return -EINVAL;
6954 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006955
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08006956 if (pHddCtx->isLogpInProgress)
6957 {
6958 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6959 "%s:LOGP in Progress. Ignore!!!", __func__);
6960 return -EBUSY;
6961 }
6962
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006963#ifdef WLAN_FEATURE_TDLS_DEBUG
6964 if((int)oper > 4)
6965 oper = 5;
6966
6967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006968 "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper",
6969 MAC_ADDR_ARRAY(peer), (int)oper,
6970 tdls_oper_str[(int)oper]);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006971#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006972
6973 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006974 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006975 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006976 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006977 "TDLS Disabled in INI OR not enabled in FW.\
6978 Cannot process TDLS commands \n");
6979 return -ENOTSUPP;
6980 }
6981
6982 switch (oper) {
6983 case NL80211_TDLS_ENABLE_LINK:
6984 {
Hoonki Lee387663d2013-02-05 18:08:43 -08006985 hddTdlsPeer_t *pTdlsPeer;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006986 VOS_STATUS status;
6987
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006988 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006989
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006990 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6991 "%s: TDLS_LINK_ENABLE " MAC_ADDRESS_STR,
6992 __func__, MAC_ADDR_ARRAY(peer));
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006993
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006994 if ( NULL == pTdlsPeer ) {
6995 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_hdd_tdls_find_peer "
6996 MAC_ADDRESS_STR " failed",
6997 __func__, MAC_ADDR_ARRAY(peer));
6998 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006999 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007000
7001 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
7002 {
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007003 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007004 /* start TDLS client registration with TL */
7005 status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -07007006 if (VOS_STATUS_SUCCESS == status)
7007 {
7008 wlan_hdd_tdls_increment_peer_count(pAdapter);
7009 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007010 wlan_hdd_tdls_check_bmps(pAdapter);
7011 }
7012
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007013 }
7014 break;
7015 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08007016 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -08007017 hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08007018
7019 if(NULL != curr_peer)
Lee Hoonkic1262f22013-01-24 21:59:00 -08007020 {
7021 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
7022 pAdapter->sessionId, peer );
Gopichand Nakkala8b00c632013-03-08 19:47:52 -08007023 wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007024 }
7025 else
7026 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007027 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7028 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -08007029 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08007030 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07007031 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007032 case NL80211_TDLS_TEARDOWN:
7033 case NL80211_TDLS_SETUP:
7034 case NL80211_TDLS_DISCOVERY_REQ:
7035 /* We don't support in-driver setup/teardown/discovery */
7036 return -ENOTSUPP;
7037 default:
7038 return -ENOTSUPP;
7039 }
7040 return 0;
7041}
Chilam NG571c65a2013-01-19 12:27:36 +05307042
7043int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
7044 struct net_device *dev, u8 *peer)
7045{
7046 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
7047 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
7048
7049 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
7050 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
7051}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007052#endif
7053
Jeff Johnson295189b2012-06-20 16:38:30 -07007054/* cfg80211_ops */
7055static struct cfg80211_ops wlan_hdd_cfg80211_ops =
7056{
7057 .add_virtual_intf = wlan_hdd_add_virtual_intf,
7058 .del_virtual_intf = wlan_hdd_del_virtual_intf,
7059 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
7060 .change_station = wlan_hdd_change_station,
7061#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7062 .add_beacon = wlan_hdd_cfg80211_add_beacon,
7063 .del_beacon = wlan_hdd_cfg80211_del_beacon,
7064 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007065#else
7066 .start_ap = wlan_hdd_cfg80211_start_ap,
7067 .change_beacon = wlan_hdd_cfg80211_change_beacon,
7068 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07007069#endif
7070 .change_bss = wlan_hdd_cfg80211_change_bss,
7071 .add_key = wlan_hdd_cfg80211_add_key,
7072 .get_key = wlan_hdd_cfg80211_get_key,
7073 .del_key = wlan_hdd_cfg80211_del_key,
7074 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007075#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07007076 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08007077#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007078 .scan = wlan_hdd_cfg80211_scan,
7079 .connect = wlan_hdd_cfg80211_connect,
7080 .disconnect = wlan_hdd_cfg80211_disconnect,
7081 .join_ibss = wlan_hdd_cfg80211_join_ibss,
7082 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
7083 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
7084 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
7085 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -07007086 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
7087 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
7088 .mgmt_tx = wlan_hdd_action,
7089#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7090 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
7091 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
7092 .set_txq_params = wlan_hdd_set_txq_params,
7093#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007094 .get_station = wlan_hdd_cfg80211_get_station,
7095 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
7096 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007097 .add_station = wlan_hdd_cfg80211_add_station,
7098#ifdef FEATURE_WLAN_LFR
7099 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
7100 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
7101 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
7102#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007103#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
7104 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
7105#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08007106#ifdef FEATURE_WLAN_TDLS
7107 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
7108 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
7109#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007110};
7111