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