blob: ca85655d5950c43853af2985f39996a7f610723c [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
74#ifdef CONFIG_CFG80211
75
76#include <linux/version.h>
77#include <linux/module.h>
78#include <linux/kernel.h>
79#include <linux/init.h>
80#include <linux/wireless.h>
81#include <wlan_hdd_includes.h>
82#include <net/arp.h>
83#include <net/cfg80211.h>
84#include <linux/wireless.h>
85#include <wlan_hdd_wowl.h>
86#include <aniGlobal.h>
87#include "ccmApi.h"
88#include "sirParams.h"
89#include "dot11f.h"
90#include "wlan_hdd_assoc.h"
91#include "wlan_hdd_wext.h"
92#include "sme_Api.h"
93#include "wlan_hdd_p2p.h"
94#include "wlan_hdd_cfg80211.h"
95#include "wlan_hdd_hostapd.h"
96#include "sapInternal.h"
97#include "wlan_hdd_softap_tx_rx.h"
98#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053099#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#ifdef WLAN_BTAMP_FEATURE
101#include "bap_hdd_misc.h"
102#endif
103#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800104#ifdef FEATURE_WLAN_TDLS
105#include "wlan_hdd_tdls.h"
106#endif
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
141static const u32 hdd_cipher_suites[] =
142{
143 WLAN_CIPHER_SUITE_WEP40,
144 WLAN_CIPHER_SUITE_WEP104,
145 WLAN_CIPHER_SUITE_TKIP,
146#ifdef FEATURE_WLAN_CCX
147#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
148 WLAN_CIPHER_SUITE_KRK,
149 WLAN_CIPHER_SUITE_CCMP,
150#else
151 WLAN_CIPHER_SUITE_CCMP,
152#endif
153#ifdef FEATURE_WLAN_WAPI
154 WLAN_CIPHER_SUITE_SMS4,
155#endif
156};
157
158static inline int is_broadcast_ether_addr(const u8 *addr)
159{
160 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
161 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
162}
163
164static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
165{
166 HDD2GHZCHAN(2412, 1, 0) ,
167 HDD2GHZCHAN(2417, 2, 0) ,
168 HDD2GHZCHAN(2422, 3, 0) ,
169 HDD2GHZCHAN(2427, 4, 0) ,
170 HDD2GHZCHAN(2432, 5, 0) ,
171 HDD2GHZCHAN(2437, 6, 0) ,
172 HDD2GHZCHAN(2442, 7, 0) ,
173 HDD2GHZCHAN(2447, 8, 0) ,
174 HDD2GHZCHAN(2452, 9, 0) ,
175 HDD2GHZCHAN(2457, 10, 0) ,
176 HDD2GHZCHAN(2462, 11, 0) ,
177 HDD2GHZCHAN(2467, 12, 0) ,
178 HDD2GHZCHAN(2472, 13, 0) ,
179 HDD2GHZCHAN(2484, 14, 0) ,
180};
181
182#ifdef WLAN_FEATURE_P2P
183static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
184{
185 HDD2GHZCHAN(2412, 1, 0) ,
186 HDD2GHZCHAN(2437, 6, 0) ,
187 HDD2GHZCHAN(2462, 11, 0) ,
188};
189#endif
190
191static struct ieee80211_channel hdd_channels_5_GHZ[] =
192{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700193 HDD5GHZCHAN(4920, 240, 0) ,
194 HDD5GHZCHAN(4940, 244, 0) ,
195 HDD5GHZCHAN(4960, 248, 0) ,
196 HDD5GHZCHAN(4980, 252, 0) ,
197 HDD5GHZCHAN(5040, 208, 0) ,
198 HDD5GHZCHAN(5060, 212, 0) ,
199 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700200 HDD5GHZCHAN(5180, 36, 0) ,
201 HDD5GHZCHAN(5200, 40, 0) ,
202 HDD5GHZCHAN(5220, 44, 0) ,
203 HDD5GHZCHAN(5240, 48, 0) ,
204 HDD5GHZCHAN(5260, 52, 0) ,
205 HDD5GHZCHAN(5280, 56, 0) ,
206 HDD5GHZCHAN(5300, 60, 0) ,
207 HDD5GHZCHAN(5320, 64, 0) ,
208 HDD5GHZCHAN(5500,100, 0) ,
209 HDD5GHZCHAN(5520,104, 0) ,
210 HDD5GHZCHAN(5540,108, 0) ,
211 HDD5GHZCHAN(5560,112, 0) ,
212 HDD5GHZCHAN(5580,116, 0) ,
213 HDD5GHZCHAN(5600,120, 0) ,
214 HDD5GHZCHAN(5620,124, 0) ,
215 HDD5GHZCHAN(5640,128, 0) ,
216 HDD5GHZCHAN(5660,132, 0) ,
217 HDD5GHZCHAN(5680,136, 0) ,
218 HDD5GHZCHAN(5700,140, 0) ,
219 HDD5GHZCHAN(5745,149, 0) ,
220 HDD5GHZCHAN(5765,153, 0) ,
221 HDD5GHZCHAN(5785,157, 0) ,
222 HDD5GHZCHAN(5805,161, 0) ,
223 HDD5GHZCHAN(5825,165, 0) ,
224};
225
226static struct ieee80211_rate g_mode_rates[] =
227{
228 HDD_G_MODE_RATETAB(10, 0x1, 0),
229 HDD_G_MODE_RATETAB(20, 0x2, 0),
230 HDD_G_MODE_RATETAB(55, 0x4, 0),
231 HDD_G_MODE_RATETAB(110, 0x8, 0),
232 HDD_G_MODE_RATETAB(60, 0x10, 0),
233 HDD_G_MODE_RATETAB(90, 0x20, 0),
234 HDD_G_MODE_RATETAB(120, 0x40, 0),
235 HDD_G_MODE_RATETAB(180, 0x80, 0),
236 HDD_G_MODE_RATETAB(240, 0x100, 0),
237 HDD_G_MODE_RATETAB(360, 0x200, 0),
238 HDD_G_MODE_RATETAB(480, 0x400, 0),
239 HDD_G_MODE_RATETAB(540, 0x800, 0),
240};
241
242static struct ieee80211_rate a_mode_rates[] =
243{
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
255{
256 .channels = hdd_channels_2_4_GHZ,
257 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
258 .band = IEEE80211_BAND_2GHZ,
259 .bitrates = g_mode_rates,
260 .n_bitrates = g_mode_rates_size,
261 .ht_cap.ht_supported = 1,
262 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
263 | IEEE80211_HT_CAP_GRN_FLD
264 | IEEE80211_HT_CAP_DSSSCCK40
265 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
266 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
267 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
268 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
269 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
270 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
271};
272
273#ifdef WLAN_FEATURE_P2P
274static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
275{
276 .channels = hdd_social_channels_2_4_GHZ,
277 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
278 .band = IEEE80211_BAND_2GHZ,
279 .bitrates = g_mode_rates,
280 .n_bitrates = g_mode_rates_size,
281 .ht_cap.ht_supported = 1,
282 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
283 | IEEE80211_HT_CAP_GRN_FLD
284 | IEEE80211_HT_CAP_DSSSCCK40
285 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
286 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
287 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
288 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
289 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
290 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
291};
292#endif
293
294static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
295{
296 .channels = hdd_channels_5_GHZ,
297 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
298 .band = IEEE80211_BAND_5GHZ,
299 .bitrates = a_mode_rates,
300 .n_bitrates = a_mode_rates_size,
301 .ht_cap.ht_supported = 1,
302 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
303 | IEEE80211_HT_CAP_GRN_FLD
304 | IEEE80211_HT_CAP_DSSSCCK40
305 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
306 | IEEE80211_HT_CAP_SGI_40
307 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
308 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
309 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
310 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
311 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
312 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
313};
314
315/* This structure contain information what kind of frame are expected in
316 TX/RX direction for each kind of interface */
317static const struct ieee80211_txrx_stypes
318wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
319 [NL80211_IFTYPE_STATION] = {
320 .tx = 0xffff,
321 .rx = BIT(SIR_MAC_MGMT_ACTION) |
322 BIT(SIR_MAC_MGMT_PROBE_REQ),
323 },
324 [NL80211_IFTYPE_AP] = {
325 .tx = 0xffff,
326 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
328 BIT(SIR_MAC_MGMT_PROBE_REQ) |
329 BIT(SIR_MAC_MGMT_DISASSOC) |
330 BIT(SIR_MAC_MGMT_AUTH) |
331 BIT(SIR_MAC_MGMT_DEAUTH) |
332 BIT(SIR_MAC_MGMT_ACTION),
333 },
334#ifdef WLAN_FEATURE_P2P
335 [NL80211_IFTYPE_P2P_CLIENT] = {
336 .tx = 0xffff,
337 .rx = BIT(SIR_MAC_MGMT_ACTION) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ),
339 },
340 [NL80211_IFTYPE_P2P_GO] = {
341 /* This is also same as for SoftAP */
342 .tx = 0xffff,
343 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
344 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
345 BIT(SIR_MAC_MGMT_PROBE_REQ) |
346 BIT(SIR_MAC_MGMT_DISASSOC) |
347 BIT(SIR_MAC_MGMT_AUTH) |
348 BIT(SIR_MAC_MGMT_DEAUTH) |
349 BIT(SIR_MAC_MGMT_ACTION),
350 },
351#endif
352};
353
354static struct cfg80211_ops wlan_hdd_cfg80211_ops;
355
356/* Data rate 100KBPS based on IE Index */
357struct index_data_rate_type
358{
359 v_U8_t beacon_rate_index;
360 v_U16_t supported_rate[4];
361};
362
363/* 11B, 11G Rate table include Basic rate and Extended rate
364 The IDX field is the rate index
365 The HI field is the rate when RSSI is strong or being ignored
366 (in this case we report actual rate)
367 The MID field is the rate when RSSI is moderate
368 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
369 The LO field is the rate when RSSI is low
370 (in this case we don't report rates, actual current rate used)
371 */
372static const struct
373{
374 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700375 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700376} supported_data_rate[] =
377{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700378/* IDX HI HM LM LO (RSSI-based index */
379 {2, { 10, 10, 10, 0}},
380 {4, { 20, 20, 10, 0}},
381 {11, { 55, 20, 10, 0}},
382 {12, { 60, 55, 20, 0}},
383 {18, { 90, 55, 20, 0}},
384 {22, {110, 55, 20, 0}},
385 {24, {120, 90, 60, 0}},
386 {36, {180, 120, 60, 0}},
387 {44, {220, 180, 60, 0}},
388 {48, {240, 180, 90, 0}},
389 {66, {330, 180, 90, 0}},
390 {72, {360, 240, 90, 0}},
391 {96, {480, 240, 120, 0}},
392 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700393};
394
395/* MCS Based rate table */
396static struct index_data_rate_type supported_mcs_rate[] =
397{
398/* MCS L20 L40 S20 S40 */
399 {0, {65, 135, 72, 150}},
400 {1, {130, 270, 144, 300}},
401 {2, {195, 405, 217, 450}},
402 {3, {260, 540, 289, 600}},
403 {4, {390, 810, 433, 900}},
404 {5, {520, 1080, 578, 1200}},
405 {6, {585, 1215, 650, 1350}},
406 {7, {650, 1350, 722, 1500}}
407};
408
409extern struct net_device_ops net_ops_struct;
410
411/*
412 * FUNCTION: wlan_hdd_cfg80211_init
413 * This function is called by hdd_wlan_startup()
414 * during initialization.
415 * This function is used to initialize and register wiphy structure.
416 */
417struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
418{
419 struct wiphy *wiphy;
420 ENTER();
421
422 /*
423 * Create wiphy device
424 */
425 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
426
427 if (!wiphy)
428 {
429 /* Print error and jump into err label and free the memory */
430 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
431 return NULL;
432 }
433
434 return wiphy;
435}
436
437/*
438 * FUNCTION: wlan_hdd_cfg80211_update_band
439 * This function is called from the supplicant through a
440 * private ioctl to change the band value
441 */
442int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
443{
Jeff Johnsone7245742012-09-05 17:12:55 -0700444 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700445 switch(eBand)
446 {
447 case eCSR_BAND_24:
448 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
449 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
450 break;
451 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700452#ifdef WLAN_FEATURE_P2P
453 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
454#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700456#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700457 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
458 break;
459 case eCSR_BAND_ALL:
460 default:
461 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
462 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
463 }
464 return 0;
465}
466/*
467 * FUNCTION: wlan_hdd_cfg80211_init
468 * This function is called by hdd_wlan_startup()
469 * during initialization.
470 * This function is used to initialize and register wiphy structure.
471 */
472int wlan_hdd_cfg80211_register(struct device *dev,
473 struct wiphy *wiphy,
474 hdd_config_t *pCfg
475 )
476{
Jeff Johnsone7245742012-09-05 17:12:55 -0700477 ENTER();
478
Jeff Johnson295189b2012-06-20 16:38:30 -0700479 /* Now bind the underlying wlan device with wiphy */
480 set_wiphy_dev(wiphy, dev);
481
482 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
483
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700484 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700485
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700486#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700487 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
488 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
489 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700490 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700491#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800492#ifdef FEATURE_WLAN_TDLS
493 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
494 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
495#endif
496
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700497 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
498 driver can still register regulatory callback and
499 it will get CRDA setting in wiphy->band[], but
500 driver need to determine what to do with both
501 regulatory settings */
502 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700503
Jeff Johnson295189b2012-06-20 16:38:30 -0700504 wiphy->max_scan_ssids = MAX_SCAN_SSID;
505
506 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
507
508 /* Supports STATION & AD-HOC modes right now */
509 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
510 | BIT(NL80211_IFTYPE_ADHOC)
511#ifdef WLAN_FEATURE_P2P
512 | BIT(NL80211_IFTYPE_P2P_CLIENT)
513 | BIT(NL80211_IFTYPE_P2P_GO)
514#endif
515 | BIT(NL80211_IFTYPE_AP);
516
517 /* Before registering we need to update the ht capabilitied based
518 * on ini values*/
519 if( !pCfg->ShortGI20MhzEnable )
520 {
521 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
522 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
523 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
524 }
525
526 if( !pCfg->ShortGI40MhzEnable )
527 {
528 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
529 }
530
531 if( !pCfg->nChannelBondingMode5GHz )
532 {
533 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
534 }
535
536 /*Initialize band capability*/
537 switch(pCfg->nBandCapability)
538 {
539 case eCSR_BAND_24:
540 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
541 break;
542 case eCSR_BAND_5G:
543#ifdef WLAN_FEATURE_P2P
544 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
545#endif
546 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
547 break;
548 case eCSR_BAND_ALL:
549 default:
550 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
551 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
552 }
553 /*Initialise the supported cipher suite details*/
554 wiphy->cipher_suites = hdd_cipher_suites;
555 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
556
557 /*signal strength in mBm (100*dBm) */
558 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
559
560#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
561#ifdef WLAN_FEATURE_P2P
562 wiphy->max_remain_on_channel_duration = 1000;
563#endif
564#endif
565
566 /* Register our wiphy dev with cfg80211 */
567 if (0 > wiphy_register(wiphy))
568 {
569 /* print eror */
570 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
571 return -EIO;
572 }
573
574 EXIT();
575 return 0;
576}
577
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700578/* In this function we will try to get default country code from crda.
579 If the gCrdaDefaultCountryCode is configured in ini file,
580 we will try to call user space crda to get the regulatory settings for
581 that country. We will timeout if we can't get it from crda.
582 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
583*/
584int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
585{
586 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
587 if (memcmp(pCfg->crdaDefaultCountryCode,
588 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
589 {
590 init_completion(&pHddCtx->driver_crda_req);
591 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
592 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
593 CRDA_WAIT_TIME);
594 }
595 return 0;
596}
597
Jeff Johnson295189b2012-06-20 16:38:30 -0700598/* In this function we will do all post VOS start initialization.
599 In this function we will register for all frame in which supplicant
600 is interested.
601*/
602void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
603{
604#ifdef WLAN_FEATURE_P2P
605 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
606 /* Register for all P2P action, public action etc frames */
607 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
608
Jeff Johnsone7245742012-09-05 17:12:55 -0700609 ENTER();
610
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 /* Right now we are registering these frame when driver is getting
612 initialized. Once we will move to 2.6.37 kernel, in which we have
613 frame register ops, we will move this code as a part of that */
614 /* GAS Initial Request */
615 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
616 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
617
618 /* GAS Initial Response */
619 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
620 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
621
622 /* GAS Comeback Request */
623 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
624 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
625
626 /* GAS Comeback Response */
627 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
628 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
629
630 /* P2P Public Action */
631 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
632 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
633 P2P_PUBLIC_ACTION_FRAME_SIZE );
634
635 /* P2P Action */
636 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
637 (v_U8_t*)P2P_ACTION_FRAME,
638 P2P_ACTION_FRAME_SIZE );
639#endif /* WLAN_FEATURE_P2P */
640}
641
642void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
643{
644#ifdef WLAN_FEATURE_P2P
645 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
646 /* Register for all P2P action, public action etc frames */
647 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
648
Jeff Johnsone7245742012-09-05 17:12:55 -0700649 ENTER();
650
Jeff Johnson295189b2012-06-20 16:38:30 -0700651 /* Right now we are registering these frame when driver is getting
652 initialized. Once we will move to 2.6.37 kernel, in which we have
653 frame register ops, we will move this code as a part of that */
654 /* GAS Initial Request */
655
656 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
657 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
658
659 /* GAS Initial Response */
660 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
661 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
662
663 /* GAS Comeback Request */
664 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
665 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
666
667 /* GAS Comeback Response */
668 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
669 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
670
671 /* P2P Public Action */
672 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
673 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
674 P2P_PUBLIC_ACTION_FRAME_SIZE );
675
676 /* P2P Action */
677 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
678 (v_U8_t*)P2P_ACTION_FRAME,
679 P2P_ACTION_FRAME_SIZE );
680#endif /* WLAN_FEATURE_P2P */
681}
682
683#ifdef FEATURE_WLAN_WAPI
684void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
685 const u8 *mac_addr, u8 *key , int key_Len)
686{
687 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
688 tCsrRoamSetKey setKey;
689 v_BOOL_t isConnected = TRUE;
690 int status = 0;
691 v_U32_t roamId= 0xFF;
692 tANI_U8 *pKeyPtr = NULL;
693 int n = 0;
694
695 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
696 __func__,pAdapter->device_mode);
697
698 setKey.keyId = key_index; // Store Key ID
699 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
700 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
701 setKey.paeRole = 0 ; // the PAE role
702 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
703 {
704 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
705 }
706 else
707 {
708 isConnected = hdd_connIsConnected(pHddStaCtx);
709 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
710 }
711 setKey.keyLength = key_Len;
712 pKeyPtr = setKey.Key;
713 memcpy( pKeyPtr, key, key_Len);
714
715 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
716 __func__, key_Len);
717 for (n = 0 ; n < key_Len; n++)
718 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
719 __func__,n,setKey.Key[n]);
720
721 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
722 if ( isConnected )
723 {
724 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
725 pAdapter->sessionId, &setKey, &roamId );
726 }
727 if ( status != 0 )
728 {
729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
730 "[%4d] sme_RoamSetKey returned ERROR status= %d",
731 __LINE__, status );
732 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
733 }
734}
735#endif /* FEATURE_WLAN_WAPI*/
736
737#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
738int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
739 beacon_data_t **ppBeacon,
740 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700741#else
742int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
743 beacon_data_t **ppBeacon,
744 struct cfg80211_beacon_data *params,
745 int dtim_period)
746#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700747{
748 int size;
749 beacon_data_t *beacon = NULL;
750 beacon_data_t *old = NULL;
751 int head_len,tail_len;
752
Jeff Johnsone7245742012-09-05 17:12:55 -0700753 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700754 if (params->head && !params->head_len)
755 return -EINVAL;
756
757 old = pAdapter->sessionCtx.ap.beacon;
758
759 if (!params->head && !old)
760 return -EINVAL;
761
762 if (params->tail && !params->tail_len)
763 return -EINVAL;
764
765#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
766 /* Kernel 3.0 is not updating dtim_period for set beacon */
767 if (!params->dtim_period)
768 return -EINVAL;
769#endif
770
771 if(params->head)
772 head_len = params->head_len;
773 else
774 head_len = old->head_len;
775
776 if(params->tail || !old)
777 tail_len = params->tail_len;
778 else
779 tail_len = old->tail_len;
780
781 size = sizeof(beacon_data_t) + head_len + tail_len;
782
783 beacon = kzalloc(size, GFP_KERNEL);
784
785 if( beacon == NULL )
786 return -ENOMEM;
787
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700788#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700789 if(params->dtim_period || !old )
790 beacon->dtim_period = params->dtim_period;
791 else
792 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700793#else
794 if(dtim_period || !old )
795 beacon->dtim_period = dtim_period;
796 else
797 beacon->dtim_period = old->dtim_period;
798#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700799
800 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
801 beacon->tail = beacon->head + head_len;
802 beacon->head_len = head_len;
803 beacon->tail_len = tail_len;
804
805 if(params->head) {
806 memcpy (beacon->head,params->head,beacon->head_len);
807 }
808 else {
809 if(old)
810 memcpy (beacon->head,old->head,beacon->head_len);
811 }
812
813 if(params->tail) {
814 memcpy (beacon->tail,params->tail,beacon->tail_len);
815 }
816 else {
817 if(old)
818 memcpy (beacon->tail,old->tail,beacon->tail_len);
819 }
820
821 *ppBeacon = beacon;
822
823 kfree(old);
824
825 return 0;
826
827}
Jeff Johnson295189b2012-06-20 16:38:30 -0700828
829v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
830{
831 int left = length;
832 v_U8_t *ptr = pIes;
833 v_U8_t elem_id,elem_len;
834
835 while(left >= 2)
836 {
837 elem_id = ptr[0];
838 elem_len = ptr[1];
839 left -= 2;
840 if(elem_len > left)
841 {
842 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700843 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700844 eid,elem_len,left);
845 return NULL;
846 }
847 if (elem_id == eid)
848 {
849 return ptr;
850 }
851
852 left -= elem_len;
853 ptr += (elem_len + 2);
854 }
855 return NULL;
856}
857
Jeff Johnson295189b2012-06-20 16:38:30 -0700858/* Check if rate is 11g rate or not */
859static int wlan_hdd_rate_is_11g(u8 rate)
860{
861 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
862 u8 i;
863 for (i = 0; i < 8; i++)
864 {
865 if(rate == gRateArray[i])
866 return TRUE;
867 }
868 return FALSE;
869}
870
871/* Check for 11g rate and set proper 11g only mode */
872static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
873 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
874{
875 u8 i, num_rates = pIe[0];
876
877 pIe += 1;
878 for ( i = 0; i < num_rates; i++)
879 {
880 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
881 {
882 /* If rate set have 11g rate than change the mode to 11G */
883 *pSapHw_mode = eSAP_DOT11_MODE_11g;
884 if (pIe[i] & BASIC_RATE_MASK)
885 {
886 /* If we have 11g rate as basic rate, it means mode
887 is 11g only mode.
888 */
889 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
890 *pCheckRatesfor11g = FALSE;
891 }
892 }
893 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
894 {
895 *require_ht = TRUE;
896 }
897 }
898 return;
899}
900
901static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
902{
903 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
904 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
905 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
906 u8 checkRatesfor11g = TRUE;
907 u8 require_ht = FALSE;
908 u8 *pIe=NULL;
909
910 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
911
912 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
913 pBeacon->head_len, WLAN_EID_SUPP_RATES);
914 if (pIe != NULL)
915 {
916 pIe += 1;
917 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
918 &pConfig->SapHw_mode);
919 }
920
921 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
922 WLAN_EID_EXT_SUPP_RATES);
923 if (pIe != NULL)
924 {
925
926 pIe += 1;
927 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
928 &pConfig->SapHw_mode);
929 }
930
931 if( pConfig->channel > 14 )
932 {
933 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
934 }
935
936 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
937 WLAN_EID_HT_CAPABILITY);
938
939 if(pIe)
940 {
941 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
942 if(require_ht)
943 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
944 }
945}
946
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700947#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700948static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
949 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700950#else
951static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
952 struct cfg80211_beacon_data *params)
953#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700954{
955 v_U8_t *genie;
956 v_U8_t total_ielen = 0, ielen = 0;
957 v_U8_t *pIe = NULL;
958 v_U8_t addIE[1] = {0};
959 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -0700960 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700961
962 genie = vos_mem_malloc(MAX_GENIE_LEN);
963
964 if(genie == NULL) {
965
966 return -ENOMEM;
967 }
968
969 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
970
971 if(pIe)
972 {
973 /*Copy the wps IE*/
974 ielen = pIe[1] + 2;
975 if( ielen <=MAX_GENIE_LEN)
976 {
977 vos_mem_copy(genie, pIe, ielen);
978 }
979 else
980 {
981 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700982 ret = -EINVAL;
983 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700984 }
985 total_ielen = ielen;
986 }
987
988#ifdef WLAN_FEATURE_WFD
989 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
990
991 if(pIe)
992 {
993 ielen = pIe[1] + 2;
994 if(total_ielen + ielen <= MAX_GENIE_LEN) {
995 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
996 }
997 else {
998 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700999 ret = -EINVAL;
1000 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001001 }
1002 total_ielen += ielen;
1003 }
1004#endif
1005
1006#ifdef WLAN_FEATURE_P2P
1007 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1008
1009 if(pIe)
1010 {
1011 ielen = pIe[1] + 2;
1012 if(total_ielen + ielen <= MAX_GENIE_LEN)
1013 {
1014 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1015 }
1016 else
1017 {
1018 hddLog( VOS_TRACE_LEVEL_ERROR,
1019 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001020 ret = -EINVAL;
1021 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001022 }
1023 total_ielen += ielen;
1024 }
1025#endif
1026
1027 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1028 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1029 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1030 {
1031 hddLog(LOGE,
1032 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001033 ret = -EINVAL;
1034 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001035 }
1036
1037 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1038 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1039 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1040 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1041 ==eHAL_STATUS_FAILURE)
1042 {
1043 hddLog(LOGE,
1044 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001045 ret = -EINVAL;
1046 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001047 }
1048
1049 // Added for ProResp IE
1050 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1051 {
1052 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1053 u8 probe_rsp_ie_len[3] = {0};
1054 u8 counter = 0;
1055 /* Check Probe Resp Length if it is greater then 255 then Store
1056 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1057 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1058 Store More then 255 bytes into One Variable.
1059 */
1060 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1061 {
1062 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1063 {
1064 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1065 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1066 }
1067 else
1068 {
1069 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1070 rem_probe_resp_ie_len = 0;
1071 }
1072 }
1073
1074 rem_probe_resp_ie_len = 0;
1075
1076 if (probe_rsp_ie_len[0] > 0)
1077 {
1078 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1079 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1080 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1081 probe_rsp_ie_len[0], NULL,
1082 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1083 {
1084 hddLog(LOGE,
1085 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001086 ret = -EINVAL;
1087 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001088 }
1089 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1090 }
1091
1092 if (probe_rsp_ie_len[1] > 0)
1093 {
1094 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1095 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1096 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1097 probe_rsp_ie_len[1], NULL,
1098 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1099 {
1100 hddLog(LOGE,
1101 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001102 ret = -EINVAL;
1103 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 }
1105 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1106 }
1107
1108 if (probe_rsp_ie_len[2] > 0)
1109 {
1110 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1111 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1112 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1113 probe_rsp_ie_len[2], NULL,
1114 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1115 {
1116 hddLog(LOGE,
1117 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001118 ret = -EINVAL;
1119 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001120 }
1121 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1122 }
1123
1124 if (probe_rsp_ie_len[1] == 0 )
1125 {
1126 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1127 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1128 eANI_BOOLEAN_FALSE) )
1129 {
1130 hddLog(LOGE,
1131 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1132 }
1133 }
1134
1135 if (probe_rsp_ie_len[2] == 0 )
1136 {
1137 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1138 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1139 eANI_BOOLEAN_FALSE) )
1140 {
1141 hddLog(LOGE,
1142 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1143 }
1144 }
1145
1146 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1147 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1148 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1149 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1150 == eHAL_STATUS_FAILURE)
1151 {
1152 hddLog(LOGE,
1153 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001154 ret = -EINVAL;
1155 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001156 }
1157 }
1158 else
1159 {
1160 // Reset WNI_CFG_PROBE_RSP Flags
1161 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1162
1163 hddLog(VOS_TRACE_LEVEL_INFO,
1164 "%s: No Probe Response IE received in set beacon",
1165 __func__);
1166 }
1167
1168 // Added for AssocResp IE
1169 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1170 {
1171 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1172 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1173 params->assocresp_ies_len, NULL,
1174 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1175 {
1176 hddLog(LOGE,
1177 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001178 ret = -EINVAL;
1179 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001180 }
1181
1182 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1183 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1184 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1185 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1186 == eHAL_STATUS_FAILURE)
1187 {
1188 hddLog(LOGE,
1189 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001190 ret = -EINVAL;
1191 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001192 }
1193 }
1194 else
1195 {
1196 hddLog(VOS_TRACE_LEVEL_INFO,
1197 "%s: No Assoc Response IE received in set beacon",
1198 __func__);
1199
1200 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1201 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1202 eANI_BOOLEAN_FALSE) )
1203 {
1204 hddLog(LOGE,
1205 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1206 }
1207 }
1208
Jeff Johnsone7245742012-09-05 17:12:55 -07001209done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001210 vos_mem_free(genie);
1211 return 0;
1212}
Jeff Johnson295189b2012-06-20 16:38:30 -07001213
1214/*
1215 * FUNCTION: wlan_hdd_validate_operation_channel
1216 * called by wlan_hdd_cfg80211_start_bss() and
1217 * wlan_hdd_cfg80211_set_channel()
1218 * This function validates whether given channel is part of valid
1219 * channel list.
1220 */
1221static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1222{
1223
1224 v_U32_t num_ch = 0;
1225 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1226 u32 indx = 0;
1227 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1228
1229 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1230
1231 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1232 valid_ch, &num_ch))
1233 {
1234 hddLog(VOS_TRACE_LEVEL_ERROR,
1235 "%s: failed to get valid channel list\n", __func__);
1236 return VOS_STATUS_E_FAILURE;
1237 }
1238
1239 for (indx = 0; indx < num_ch; indx++)
1240 {
1241 if (channel == valid_ch[indx])
1242 {
1243 break;
1244 }
1245 }
1246
1247 if (indx >= num_ch)
1248 {
1249 hddLog(VOS_TRACE_LEVEL_ERROR,
1250 "%s: Invalid Channel [%d] \n", __func__, channel);
1251 return VOS_STATUS_E_FAILURE;
1252 }
1253 return VOS_STATUS_SUCCESS;
1254
1255}
1256
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301257/*
1258 * FUNCTION: wlan_hdd_select_cbmode
1259 * called by wlan_hdd_cfg80211_start_bss() and
1260 * This function selects the cbmode based on primary channel
1261 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001262VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301263{
1264 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001265 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1266 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1267
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301268 if(
1269#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001270 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1271 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301272#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001273 SapHw_mode != eSAP_DOT11_MODE_11n &&
1274 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301275 )
1276 {
1277 return VOS_STATUS_SUCCESS;
1278 }
1279
1280 if (!pConfigIni->nChannelBondingMode5GHz) {
1281 return VOS_STATUS_SUCCESS;
1282 }
1283
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001284 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301285 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1286
1287 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1288
1289#ifdef WLAN_FEATURE_11AC
1290
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001291 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1292 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301293 {
1294 if ( channel== 36 || channel == 52 || channel == 100 ||
1295 channel == 116 || channel == 149 )
1296 {
1297 smeConfig.csrConfig.channelBondingMode5GHz =
1298 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1299 }
1300 else if ( channel == 40 || channel == 56 || channel == 104 ||
1301 channel == 120 || channel == 153 )
1302 {
1303 smeConfig.csrConfig.channelBondingMode5GHz =
1304 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1305 }
1306 else if ( channel == 44 || channel == 60 || channel == 108 ||
1307 channel == 124 || channel == 157 )
1308 {
1309 smeConfig.csrConfig.channelBondingMode5GHz =
1310 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1311 }
1312 else if ( channel == 48 || channel == 64 || channel == 112 ||
1313 channel == 128 || channel == 161 )
1314 {
1315 smeConfig.csrConfig.channelBondingMode5GHz =
1316 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1317 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301318 }
1319#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001320 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1321 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301322 {
1323 if ( channel== 40 || channel == 48 || channel == 56 ||
1324 channel == 64 || channel == 104 || channel == 112 ||
1325 channel == 120 || channel == 128 || channel == 136 ||
1326 channel == 144 || channel == 153 || channel == 161 )
1327 {
1328 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1329 }
1330 else if ( channel== 36 || channel == 44 || channel == 52 ||
1331 channel == 60 || channel == 100 || channel == 108 ||
1332 channel == 116 || channel == 124 || channel == 132 ||
1333 channel == 140 || channel == 149 || channel == 157 )
1334 {
1335 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1336 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301337 }
1338 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1339
1340 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1341 return VOS_STATUS_SUCCESS;
1342}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001343
Jeff Johnson295189b2012-06-20 16:38:30 -07001344#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1345static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1346 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001347#else
1348static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1349 struct cfg80211_beacon_data *params,
1350 const u8 *ssid, size_t ssid_len,
1351 enum nl80211_hidden_ssid hidden_ssid)
1352#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001353{
1354 tsap_Config_t *pConfig;
1355 beacon_data_t *pBeacon = NULL;
1356 struct ieee80211_mgmt *pMgmt_frame;
1357 v_U8_t *pIe=NULL;
1358 v_U16_t capab_info;
1359 eCsrAuthType RSNAuthType;
1360 eCsrEncryptionType RSNEncryptType;
1361 eCsrEncryptionType mcRSNEncryptType;
1362 int status = VOS_STATUS_SUCCESS;
1363 tpWLAN_SAPEventCB pSapEventCallback;
1364 hdd_hostapd_state_t *pHostapdState;
1365 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1366 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1367 struct qc_mac_acl_entry *acl_entry = NULL;
1368 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001369 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001370
1371 ENTER();
1372
1373 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1374
1375 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1376
1377 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1378
1379 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1380
1381 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1382
1383 //channel is already set in the set_channel Call back
1384 //pConfig->channel = pCommitConfig->channel;
1385
1386 /*Protection parameter to enable or disable*/
1387 pConfig->protEnabled =
1388 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1389
1390 pConfig->dtim_period = pBeacon->dtim_period;
1391
1392 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1393 pConfig->dtim_period);
1394
1395
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001396 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001397 {
1398 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001399 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001400 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001401 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001402 tANI_BOOLEAN restartNeeded;
1403 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1404 pConfig->ieee80211d = 1;
1405 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1406 sme_setRegInfo(hHal, pConfig->countryCode);
1407 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1408 /*
1409 * If auto channel is configured i.e. channel is 0,
1410 * so skip channel validation.
1411 */
1412 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001413 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001414 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1415 {
1416 hddLog(VOS_TRACE_LEVEL_ERROR,
1417 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1418 return -EINVAL;
1419 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001420 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001421 /*
1422 * Validate the given channel range for the given country code
1423 */
1424 else
1425 {
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001426 if(1 != pHddCtx->is_dynamic_channel_range_set)
Ng Chilamfc416462012-12-27 17:26:52 -08001427 {
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001428 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001429 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
Ng Chilamfc416462012-12-27 17:26:52 -08001430 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001431 }
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001432
Ng Chilamfc416462012-12-27 17:26:52 -08001433 pHddCtx->is_dynamic_channel_range_set = 0;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001434 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001435 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001436 else
1437 {
1438 pConfig->ieee80211d = 0;
1439 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001440 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001441 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001442 {
1443 pConfig->ieee80211d = 0;
1444 }
1445 pConfig->authType = eSAP_AUTO_SWITCH;
1446
1447 capab_info = pMgmt_frame->u.beacon.capab_info;
1448
1449 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1450 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1451
1452 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1453
1454 /*Set wps station to configured*/
1455 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1456
1457 if(pIe)
1458 {
1459 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1460 {
1461 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1462 return -EINVAL;
1463 }
1464 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1465 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001466 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001467 /* Check 15 bit of WPS IE as it contain information for wps state
1468 * WPS state
1469 */
1470 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1471 {
1472 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1473 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1474 {
1475 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1476 }
1477 }
1478 }
1479 else
1480 {
1481 pConfig->wps_state = SAP_WPS_DISABLED;
1482 }
1483 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1484
1485 pConfig->RSNWPAReqIELength = 0;
1486 pConfig->pRSNWPAReqIE = NULL;
1487 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1488 WLAN_EID_RSN);
1489 if(pIe && pIe[1])
1490 {
1491 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1492 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1493 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1494 /* The actual processing may eventually be more extensive than
1495 * this. Right now, just consume any PMKIDs that are sent in
1496 * by the app.
1497 * */
1498 status = hdd_softap_unpackIE(
1499 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1500 &RSNEncryptType,
1501 &mcRSNEncryptType,
1502 &RSNAuthType,
1503 pConfig->pRSNWPAReqIE[1]+2,
1504 pConfig->pRSNWPAReqIE );
1505
1506 if( VOS_STATUS_SUCCESS == status )
1507 {
1508 /* Now copy over all the security attributes you have
1509 * parsed out
1510 * */
1511 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1512 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1513 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1514 = RSNEncryptType;
1515 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1516 "EncryptionType = %d mcEncryptionType = %d\n"),
1517 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1518 }
1519 }
1520
1521 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1522 pBeacon->tail, pBeacon->tail_len);
1523
1524 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1525 {
1526 if (pConfig->pRSNWPAReqIE)
1527 {
1528 /*Mixed mode WPA/WPA2*/
1529 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1530 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1531 }
1532 else
1533 {
1534 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1535 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1536 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1537 status = hdd_softap_unpackIE(
1538 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1539 &RSNEncryptType,
1540 &mcRSNEncryptType,
1541 &RSNAuthType,
1542 pConfig->pRSNWPAReqIE[1]+2,
1543 pConfig->pRSNWPAReqIE );
1544
1545 if( VOS_STATUS_SUCCESS == status )
1546 {
1547 /* Now copy over all the security attributes you have
1548 * parsed out
1549 * */
1550 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1551 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1552 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1553 = RSNEncryptType;
1554 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1555 "EncryptionType = %d mcEncryptionType = %d\n"),
1556 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1557 }
1558 }
1559 }
1560
1561 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1562
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001563#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001564 if (params->ssid != NULL)
1565 {
1566 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1567 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1568 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1569 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1570 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001571#else
1572 if (ssid != NULL)
1573 {
1574 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1575 pConfig->SSIDinfo.ssid.length = ssid_len;
1576 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1577 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1578 }
1579#endif
1580
Jeff Johnson295189b2012-06-20 16:38:30 -07001581 vos_mem_copy(pConfig->self_macaddr.bytes,
1582 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1583
1584 /* default value */
1585 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1586 pConfig->num_accept_mac = 0;
1587 pConfig->num_deny_mac = 0;
1588
1589 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1590 pBeacon->tail, pBeacon->tail_len);
1591
1592 /* pIe for black list is following form:
1593 type : 1 byte
1594 length : 1 byte
1595 OUI : 4 bytes
1596 acl type : 1 byte
1597 no of mac addr in black list: 1 byte
1598 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1599 */
1600 if ((pIe != NULL) && (pIe[1] != 0))
1601 {
1602 pConfig->SapMacaddr_acl = pIe[6];
1603 pConfig->num_deny_mac = pIe[7];
1604 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1605 pIe[6], pIe[7]);
1606 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1607 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1608 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1609 for (i = 0; i < pConfig->num_deny_mac; i++)
1610 {
1611 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1612 acl_entry++;
1613 }
1614 }
1615 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1616 pBeacon->tail, pBeacon->tail_len);
1617
1618 /* pIe for white list is following form:
1619 type : 1 byte
1620 length : 1 byte
1621 OUI : 4 bytes
1622 acl type : 1 byte
1623 no of mac addr in white list: 1 byte
1624 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1625 */
1626 if ((pIe != NULL) && (pIe[1] != 0))
1627 {
1628 pConfig->SapMacaddr_acl = pIe[6];
1629 pConfig->num_accept_mac = pIe[7];
1630 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1631 pIe[6], pIe[7]);
1632 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1633 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1634 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1635 for (i = 0; i < pConfig->num_accept_mac; i++)
1636 {
1637 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1638 acl_entry++;
1639 }
1640 }
1641 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1642
Jeff Johnsone7245742012-09-05 17:12:55 -07001643#ifdef WLAN_FEATURE_11AC
1644 if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1645 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1646 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) )
1647 {
1648 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1649 }
1650#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301651
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001652 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1653 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001654 // ht_capab is not what the name conveys,this is used for protection bitmap
1655 pConfig->ht_capab =
1656 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1657
1658 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1659 {
1660 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1661 return -EINVAL;
1662 }
1663
1664 //Uapsd Enabled Bit
1665 pConfig->UapsdEnable =
1666 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1667 //Enable OBSS protection
1668 pConfig->obssProtEnabled =
1669 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1670
1671 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1672 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1673 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1674 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1675 (int)pConfig->channel);
1676 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1677 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1678 pConfig->authType);
1679 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1680 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1681 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1682 pConfig->protEnabled, pConfig->obssProtEnabled);
1683
1684 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1685 {
1686 //Bss already started. just return.
1687 //TODO Probably it should update some beacon params.
1688 hddLog( LOGE, "Bss Already started...Ignore the request");
1689 EXIT();
1690 return 0;
1691 }
1692
1693 pConfig->persona = pHostapdAdapter->device_mode;
1694
1695 pSapEventCallback = hdd_hostapd_SAPEventCB;
1696 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1697 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1698 {
1699 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1700 return -EINVAL;
1701 }
1702
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001703 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1705
1706 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1707
1708 if (!VOS_IS_STATUS_SUCCESS(status))
1709 {
1710 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1711 ("ERROR: HDD vos wait for single_event failed!!\n"));
1712 VOS_ASSERT(0);
1713 }
1714
1715 //Succesfully started Bss update the state bit.
1716 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1717
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001718#ifdef WLAN_FEATURE_P2P_DEBUG
1719 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1720 {
1721 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1722 {
1723 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1724 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001725 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001726 }
1727 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1728 {
1729 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1730 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001731 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001732 }
1733 }
1734#endif
1735
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 pHostapdState->bCommit = TRUE;
1737 EXIT();
1738
1739 return 0;
1740}
1741
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001742#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001743static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1744 struct net_device *dev,
1745 struct beacon_parameters *params)
1746{
1747 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1748 int status=VOS_STATUS_SUCCESS;
1749
1750 ENTER();
1751
1752 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1753
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001754 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1755 {
1756 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1757 "%s:LOGP in Progress. Ignore!!!", __func__);
1758 return -EAGAIN;
1759 }
1760
Jeff Johnson295189b2012-06-20 16:38:30 -07001761 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1762#ifdef WLAN_FEATURE_P2P
1763 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1764#endif
1765 )
1766 {
1767 beacon_data_t *old,*new;
1768
1769 old = pAdapter->sessionCtx.ap.beacon;
1770
1771 if (old)
1772 return -EALREADY;
1773
1774 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1775
1776 if(status != VOS_STATUS_SUCCESS)
1777 {
1778 hddLog(VOS_TRACE_LEVEL_FATAL,
1779 "%s:Error!!! Allocating the new beacon\n",__func__);
1780 return -EINVAL;
1781 }
1782
1783 pAdapter->sessionCtx.ap.beacon = new;
1784
1785 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1786 }
1787
1788 EXIT();
1789 return status;
1790}
1791
1792static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1793 struct net_device *dev,
1794 struct beacon_parameters *params)
1795{
1796 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1797 int status=VOS_STATUS_SUCCESS;
1798
1799 ENTER();
1800
1801 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1802 __func__,pAdapter->device_mode);
1803
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001804 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1805 {
1806 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1807 "%s:LOGP in Progress. Ignore!!!", __func__);
1808 return -EAGAIN;
1809 }
1810
Jeff Johnson295189b2012-06-20 16:38:30 -07001811 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1812#ifdef WLAN_FEATURE_P2P
1813 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1814#endif
1815 )
1816 {
1817 beacon_data_t *old,*new;
1818
1819 old = pAdapter->sessionCtx.ap.beacon;
1820
1821 if (!old)
1822 return -ENOENT;
1823
1824 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1825
1826 if(status != VOS_STATUS_SUCCESS) {
1827 hddLog(VOS_TRACE_LEVEL_FATAL,
1828 "%s: Error!!! Allocating the new beacon\n",__func__);
1829 return -EINVAL;
1830 }
1831
1832 pAdapter->sessionCtx.ap.beacon = new;
1833
1834 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1835 }
1836
1837 EXIT();
1838 return status;
1839}
1840
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001841#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1842
1843#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001844static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1845 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001846#else
1847static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1848 struct net_device *dev)
1849#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001850{
1851 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001852 hdd_context_t *pHddCtx = NULL;
1853 hdd_scaninfo_t *pScanInfo = NULL;
1854 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001855 VOS_STATUS status = 0;
1856
1857 ENTER();
1858
1859 if (NULL == pAdapter)
1860 {
1861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001862 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001863 return -ENODEV;
1864 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001865 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1866 {
1867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1868 "%s:LOGP in Progress. Ignore!!!", __func__);
1869 return -EAGAIN;
1870 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001871
1872 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1873 if (NULL == pHddCtx)
1874 {
1875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001876 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001877 return -ENODEV;
1878 }
1879
1880 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1881 if (NULL == staAdapter)
1882 {
1883 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1884 if (NULL == staAdapter)
1885 {
1886 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001887 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001888 return -ENODEV;
1889 }
1890 }
1891
1892 pScanInfo = &pHddCtx->scan_info;
1893
Jeff Johnson295189b2012-06-20 16:38:30 -07001894 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1895 {
1896 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1897 return -EAGAIN;
1898 }
1899
1900 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1901
1902 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1903 __func__,pAdapter->device_mode);
1904
Jeff Johnsone7245742012-09-05 17:12:55 -07001905 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1906 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001907 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001908 hdd_abort_mac_scan(staAdapter->pHddCtx);
1909 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001910 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07001911 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1912 if (!status)
1913 {
1914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08001915 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001916 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001917 VOS_ASSERT(pScanInfo->mScanPending);
1918 return 0;
1919 }
1920 }
1921
Jeff Johnson295189b2012-06-20 16:38:30 -07001922 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1923#ifdef WLAN_FEATURE_P2P
1924 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1925#endif
1926 )
1927 {
1928 beacon_data_t *old;
1929
1930 old = pAdapter->sessionCtx.ap.beacon;
1931
1932 if (!old)
1933 return -ENOENT;
1934
1935#ifdef CONFIG_CFG80211
1936 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1937#endif
1938
1939 mutex_lock(&pHddCtx->sap_lock);
1940 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1941 {
1942 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
1943 {
1944 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
1945
1946 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1947
1948 if (!VOS_IS_STATUS_SUCCESS(status))
1949 {
1950 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1951 ("ERROR: HDD vos wait for single_event failed!!\n"));
1952 VOS_ASSERT(0);
1953 }
1954 }
1955 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
1956 }
1957 mutex_unlock(&pHddCtx->sap_lock);
1958
1959 if(status != VOS_STATUS_SUCCESS)
1960 {
1961 hddLog(VOS_TRACE_LEVEL_FATAL,
1962 "%s:Error!!! Stopping the BSS\n",__func__);
1963 return -EINVAL;
1964 }
1965
1966 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1967 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
1968 ==eHAL_STATUS_FAILURE)
1969 {
1970 hddLog(LOGE,
1971 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
1972 }
1973
1974 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1975 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1976 eANI_BOOLEAN_FALSE) )
1977 {
1978 hddLog(LOGE,
1979 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1980 }
1981
1982 // Reset WNI_CFG_PROBE_RSP Flags
1983 wlan_hdd_reset_prob_rspies(pAdapter);
1984
1985 pAdapter->sessionCtx.ap.beacon = NULL;
1986 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001987#ifdef WLAN_FEATURE_P2P_DEBUG
1988 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
1989 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
1990 {
1991 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
1992 "GO got removed");
1993 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
1994 }
1995#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001996 }
1997 EXIT();
1998 return status;
1999}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002000
2001#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2002
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302003static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2004 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002005 struct cfg80211_ap_settings *params)
2006{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302007 hdd_adapter_t *pAdapter;
2008 hdd_context_t *pHddCtx;
2009 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002010
2011 ENTER();
2012
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302013 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002014 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2016 "%s: Device is Null", __func__);
2017 return -ENODEV;
2018 }
2019
2020 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2021 if (NULL == pAdapter)
2022 {
2023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2024 "%s: HDD adapter is Null", __func__);
2025 return -ENODEV;
2026 }
2027
2028 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2029 {
2030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2031 "%s: HDD adapter magic is invalid", __func__);
2032 return -ENODEV;
2033 }
2034
2035 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2036 if (NULL == pHddCtx)
2037 {
2038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2039 "%s: HDD context is Null", __func__);
2040 return -ENODEV;
2041 }
2042
2043 if (pHddCtx->isLogpInProgress)
2044 {
2045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2046 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002047 return -EAGAIN;
2048 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302049
2050 if (pHddCtx->isLoadUnloadInProgress)
2051 {
2052 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2053 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2054 return -EAGAIN;
2055 }
2056
2057 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2058 __func__, pAdapter->device_mode);
2059
2060 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002061#ifdef WLAN_FEATURE_P2P
2062 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2063#endif
2064 )
2065 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302066 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002067
2068 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302069
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002070 if (old)
2071 return -EALREADY;
2072
2073 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2074
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302075 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002076 {
2077 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302078 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002079 return -EINVAL;
2080 }
2081 pAdapter->sessionCtx.ap.beacon = new;
2082 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2083 params->ssid_len, params->hidden_ssid);
2084 }
2085
2086 EXIT();
2087 return status;
2088}
2089
2090
2091static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2092 struct net_device *dev,
2093 struct cfg80211_beacon_data *params)
2094{
2095 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2096 int status=VOS_STATUS_SUCCESS;
2097
2098 ENTER();
2099
2100 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2101 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002102 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2103 {
2104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2105 return -EAGAIN;
2106 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002107
2108 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2109#ifdef WLAN_FEATURE_P2P
2110 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2111#endif
2112 )
2113 {
2114 beacon_data_t *old,*new;
2115
2116 old = pAdapter->sessionCtx.ap.beacon;
2117
2118 if (!old)
2119 return -ENOENT;
2120
2121 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2122
2123 if(status != VOS_STATUS_SUCCESS) {
2124 hddLog(VOS_TRACE_LEVEL_FATAL,
2125 "%s: Error!!! Allocating the new beacon\n",__func__);
2126 return -EINVAL;
2127 }
2128
2129 pAdapter->sessionCtx.ap.beacon = new;
2130
2131 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2132 }
2133
2134 EXIT();
2135 return status;
2136}
2137
2138#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2139
Jeff Johnson295189b2012-06-20 16:38:30 -07002140
2141static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2142 struct net_device *dev,
2143 struct bss_parameters *params)
2144{
2145 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2146
2147 ENTER();
2148
2149 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2150 __func__,pAdapter->device_mode);
2151
2152 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2153#ifdef WLAN_FEATURE_P2P
2154 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2155#endif
2156 )
2157 {
2158 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2159 * want to update this parameter */
2160 if (-1 != params->ap_isolate)
2161 {
2162 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2163 }
2164 }
2165
2166 EXIT();
2167 return 0;
2168}
2169
2170/*
2171 * FUNCTION: wlan_hdd_cfg80211_change_iface
2172 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2173 */
2174int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2175 struct net_device *ndev,
2176 enum nl80211_iftype type,
2177 u32 *flags,
2178 struct vif_params *params
2179 )
2180{
2181 struct wireless_dev *wdev;
2182 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2183 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002184 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002185 tCsrRoamProfile *pRoamProfile = NULL;
2186 eCsrRoamBssType LastBSSType;
2187 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2188 eMib_dot11DesiredBssType connectedBssType;
2189 VOS_STATUS status;
2190
2191 ENTER();
2192
2193 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2194 {
2195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2196 return -EAGAIN;
2197 }
2198
2199 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2200 __func__, pAdapter->device_mode);
2201
2202 wdev = ndev->ieee80211_ptr;
2203
2204#ifdef WLAN_BTAMP_FEATURE
2205 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2206 (NL80211_IFTYPE_ADHOC == type)||
2207 (NL80211_IFTYPE_AP == type)||
2208 (NL80211_IFTYPE_P2P_GO == type))
2209 {
2210 pHddCtx->isAmpAllowed = VOS_FALSE;
2211 // stop AMP traffic
2212 status = WLANBAP_StopAmp();
2213 if(VOS_STATUS_SUCCESS != status )
2214 {
2215 pHddCtx->isAmpAllowed = VOS_TRUE;
2216 hddLog(VOS_TRACE_LEVEL_FATAL,
2217 "%s: Failed to stop AMP", __func__);
2218 return -EINVAL;
2219 }
2220 }
2221#endif //WLAN_BTAMP_FEATURE
2222 /* Reset the current device mode bit mask*/
2223 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2224
2225 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2226#ifdef WLAN_FEATURE_P2P
2227 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002228 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002229#endif
2230 )
2231 {
2232 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2233 pRoamProfile = &pWextState->roamProfile;
2234 LastBSSType = pRoamProfile->BSSType;
2235
2236 switch (type)
2237 {
2238 case NL80211_IFTYPE_STATION:
2239#ifdef WLAN_FEATURE_P2P
2240 case NL80211_IFTYPE_P2P_CLIENT:
2241#endif
2242 hddLog(VOS_TRACE_LEVEL_INFO,
2243 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2244 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002245#ifdef WLAN_FEATURE_11AC
2246 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2247 {
2248 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2249 }
2250#endif
2251 pRoamProfile->phyMode =
2252 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002253 wdev->iftype = type;
2254#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002255 //Check for sub-string p2p to confirm its a p2p interface
2256 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002257 {
2258 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2259 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2260 }
2261 else
2262 {
2263 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002264 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002265 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002266#endif
2267 break;
2268 case NL80211_IFTYPE_ADHOC:
2269 hddLog(VOS_TRACE_LEVEL_INFO,
2270 "%s: setting interface Type to ADHOC", __func__);
2271 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2272 pRoamProfile->phyMode =
2273 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2274 wdev->iftype = type;
2275 break;
2276
2277 case NL80211_IFTYPE_AP:
2278#ifdef WLAN_FEATURE_P2P
2279 case NL80211_IFTYPE_P2P_GO:
2280#endif
2281 {
2282 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2283 "%s: setting interface Type to %s", __func__,
2284 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2285
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002286 //Cancel any remain on channel for GO mode
2287 if (NL80211_IFTYPE_P2P_GO == type)
2288 {
2289 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2290 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002291 if (NL80211_IFTYPE_AP == type)
2292 {
2293 /* As Loading WLAN Driver one interface being created for p2p device
2294 * address. This will take one HW STA and the max number of clients
2295 * that can connect to softAP will be reduced by one. so while changing
2296 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2297 * interface as it is not required in SoftAP mode.
2298 */
2299
2300 // Get P2P Adapter
2301 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2302
2303 if (pP2pAdapter)
2304 {
2305 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2306 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2307 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2308 }
2309 }
2310
Jeff Johnson295189b2012-06-20 16:38:30 -07002311 //De-init the adapter.
2312 hdd_stop_adapter( pHddCtx, pAdapter );
2313 hdd_deinit_adapter( pHddCtx, pAdapter );
2314 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2315#ifdef WLAN_SOFTAP_FEATURE
2316#ifdef WLAN_FEATURE_P2P
2317 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2318 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2319#else
2320 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2321#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002322
2323 //Disable BMPS and IMPS if enabled
2324 //before starting Go
2325 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2326 {
2327 if(VOS_STATUS_E_FAILURE ==
2328 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2329 {
2330 //Fail to Exit BMPS
2331 VOS_ASSERT(0);
2332 }
2333 }
2334
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002335 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2336 (pConfig->apRandomBssidEnabled))
2337 {
2338 /* To meet Android requirements create a randomized
2339 MAC address of the form 02:1A:11:Fx:xx:xx */
2340 get_random_bytes(&ndev->dev_addr[3], 3);
2341 ndev->dev_addr[0] = 0x02;
2342 ndev->dev_addr[1] = 0x1A;
2343 ndev->dev_addr[2] = 0x11;
2344 ndev->dev_addr[3] |= 0xF0;
2345 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2346 VOS_MAC_ADDR_SIZE);
2347 pr_info("wlan: Generated HotSpot BSSID "
2348 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2349 ndev->dev_addr[0],
2350 ndev->dev_addr[1],
2351 ndev->dev_addr[2],
2352 ndev->dev_addr[3],
2353 ndev->dev_addr[4],
2354 ndev->dev_addr[5]);
2355 }
2356
Jeff Johnson295189b2012-06-20 16:38:30 -07002357 hdd_set_ap_ops( pAdapter->dev );
2358
2359 status = hdd_init_ap_mode(pAdapter);
2360 if(status != VOS_STATUS_SUCCESS)
2361 {
2362 hddLog(VOS_TRACE_LEVEL_FATAL,
2363 "%s: Error initializing the ap mode", __func__);
2364 return -EINVAL;
2365 }
2366 hdd_set_conparam(1);
2367
2368#endif
2369 /*interface type changed update in wiphy structure*/
2370 if(wdev)
2371 {
2372 wdev->iftype = type;
2373 pHddCtx->change_iface = type;
2374 }
2375 else
2376 {
2377 hddLog(VOS_TRACE_LEVEL_ERROR,
2378 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2379 return -EINVAL;
2380 }
2381 goto done;
2382 }
2383
2384 default:
2385 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2386 __func__);
2387 return -EOPNOTSUPP;
2388 }
2389 }
2390 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2391#ifdef WLAN_FEATURE_P2P
2392 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2393#endif
2394 )
2395 {
2396 switch(type)
2397 {
2398 case NL80211_IFTYPE_STATION:
2399#ifdef WLAN_FEATURE_P2P
2400 case NL80211_IFTYPE_P2P_CLIENT:
2401#endif
2402 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002403 hdd_stop_adapter( pHddCtx, pAdapter );
2404 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002405 wdev->iftype = type;
2406#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002407 //Check for sub-string p2p to confirm its a p2p interface
2408 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002409 {
2410 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2411 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2412 }
2413 else
2414 {
2415 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002416 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002417 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002418#endif
2419 hdd_set_conparam(0);
2420 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002421 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2422 hdd_set_station_ops( pAdapter->dev );
2423 status = hdd_init_station_mode( pAdapter );
2424 if( VOS_STATUS_SUCCESS != status )
2425 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002426 /* In case of JB, for P2P-GO, only change interface will be called,
2427 * This is the right place to enable back bmps_imps()
2428 */
2429 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002430 goto done;
2431 case NL80211_IFTYPE_AP:
2432#ifdef WLAN_FEATURE_P2P
2433 case NL80211_IFTYPE_P2P_GO:
2434#endif
2435 wdev->iftype = type;
2436#ifdef WLAN_FEATURE_P2P
2437 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2438 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2439#endif
2440 goto done;
2441 default:
2442 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2443 __func__);
2444 return -EOPNOTSUPP;
2445
2446 }
2447
2448 }
2449 else
2450 {
2451 return -EOPNOTSUPP;
2452 }
2453
2454
2455 if(pRoamProfile)
2456 {
2457 if ( LastBSSType != pRoamProfile->BSSType )
2458 {
2459 /*interface type changed update in wiphy structure*/
2460 wdev->iftype = type;
2461
2462 /*the BSS mode changed, We need to issue disconnect
2463 if connected or in IBSS disconnect state*/
2464 if ( hdd_connGetConnectedBssType(
2465 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2466 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2467 {
2468 /*need to issue a disconnect to CSR.*/
2469 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2470 if( eHAL_STATUS_SUCCESS ==
2471 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2472 pAdapter->sessionId,
2473 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2474 {
2475 wait_for_completion_interruptible_timeout(
2476 &pAdapter->disconnect_comp_var,
2477 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2478 }
2479 }
2480 }
2481 }
2482
2483done:
2484 /*set bitmask based on updated value*/
2485 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2486#ifdef WLAN_BTAMP_FEATURE
2487 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2488 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2489 {
2490 //we are ok to do AMP
2491 pHddCtx->isAmpAllowed = VOS_TRUE;
2492 }
2493#endif //WLAN_BTAMP_FEATURE
2494 EXIT();
2495 return 0;
2496}
2497
2498static int wlan_hdd_change_station(struct wiphy *wiphy,
2499 struct net_device *dev,
2500 u8 *mac,
2501 struct station_parameters *params)
2502{
2503 VOS_STATUS status = VOS_STATUS_SUCCESS;
2504 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2505 v_MACADDR_t STAMacAddress;
2506
Jeff Johnsone7245742012-09-05 17:12:55 -07002507 ENTER();
2508
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002509 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2510 {
2511 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2512 "%s:LOGP in Progress. Ignore!!!", __func__);
2513 return -EAGAIN;
2514 }
2515
Jeff Johnson295189b2012-06-20 16:38:30 -07002516 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2517
2518 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2519#ifdef WLAN_FEATURE_P2P
2520 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2521#endif
2522 )
2523 {
2524 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2525 {
2526 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2527 WLANTL_STA_AUTHENTICATED);
2528
2529 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002530 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 return -EINVAL;
2532 }
2533 }
2534
Jeff Johnsone7245742012-09-05 17:12:55 -07002535 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002536 return status;
2537}
2538
2539/*
2540 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2541 * This function is used to get peer station index in IBSS mode
2542 */
2543static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2544{
2545 u8 idx = 0;
2546 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2547 ENTER();
2548 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2549 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2550 {
2551 if ( (0 !=
2552 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2553 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2554 temp, VOS_MAC_ADDR_SIZE)
2555 )
2556 {
2557 return idx;
2558 }
2559 }
2560 return idx;
2561}
2562
2563
2564/*
2565 * FUNCTION: wlan_hdd_cfg80211_add_key
2566 * This function is used to initialize the key information
2567 */
2568#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2569static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2570 struct net_device *ndev,
2571 u8 key_index, bool pairwise,
2572 const u8 *mac_addr,
2573 struct key_params *params
2574 )
2575#else
2576static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2577 struct net_device *ndev,
2578 u8 key_index, const u8 *mac_addr,
2579 struct key_params *params
2580 )
2581#endif
2582{
2583 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2584 tCsrRoamSetKey setKey;
2585 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2586 int status = 0;
2587 v_U32_t roamId= 0xFF;
2588 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2589 hdd_hostapd_state_t *pHostapdState;
2590 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002591 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002592
2593 ENTER();
2594
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002595 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2596 {
2597 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2598 "%s:LOGP in Progress. Ignore!!!", __func__);
2599 return -EAGAIN;
2600 }
2601
Jeff Johnson295189b2012-06-20 16:38:30 -07002602 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2603 __func__,pAdapter->device_mode);
2604
2605 if (CSR_MAX_NUM_KEY <= key_index)
2606 {
2607 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2608 key_index);
2609
2610 return -EINVAL;
2611 }
2612
2613 hddLog(VOS_TRACE_LEVEL_INFO,
2614 "%s: called with key index = %d & key length %d",
2615 __func__, key_index, params->key_len);
2616
2617 /*extract key idx, key len and key*/
2618 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2619 setKey.keyId = key_index;
2620 setKey.keyLength = params->key_len;
2621 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2622
2623 switch (params->cipher)
2624 {
2625 case WLAN_CIPHER_SUITE_WEP40:
2626 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2627 break;
2628
2629 case WLAN_CIPHER_SUITE_WEP104:
2630 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2631 break;
2632
2633 case WLAN_CIPHER_SUITE_TKIP:
2634 {
2635 u8 *pKey = &setKey.Key[0];
2636 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2637
2638 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2639
2640 /*Supplicant sends the 32bytes key in this order
2641
2642 |--------------|----------|----------|
2643 | Tk1 |TX-MIC | RX Mic |
2644 |--------------|----------|----------|
2645 <---16bytes---><--8bytes--><--8bytes-->
2646
2647 */
2648 /*Sme expects the 32 bytes key to be in the below order
2649
2650 |--------------|----------|----------|
2651 | Tk1 |RX-MIC | TX Mic |
2652 |--------------|----------|----------|
2653 <---16bytes---><--8bytes--><--8bytes-->
2654 */
2655 /* Copy the Temporal Key 1 (TK1) */
2656 vos_mem_copy(pKey, params->key,16);
2657
2658 /*Copy the rx mic first*/
2659 vos_mem_copy(&pKey[16],&params->key[24],8);
2660
2661 /*Copy the tx mic */
2662 vos_mem_copy(&pKey[24],&params->key[16],8);
2663
2664
2665 break;
2666 }
2667
2668 case WLAN_CIPHER_SUITE_CCMP:
2669 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2670 break;
2671
2672#ifdef FEATURE_WLAN_WAPI
2673 case WLAN_CIPHER_SUITE_SMS4:
2674 {
2675 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2676 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2677 params->key, params->key_len);
2678 return 0;
2679 }
2680#endif
2681#ifdef FEATURE_WLAN_CCX
2682 case WLAN_CIPHER_SUITE_KRK:
2683 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2684 break;
2685#endif
2686 default:
2687 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2688 __func__, params->cipher);
2689 return -EOPNOTSUPP;
2690 }
2691
2692 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2693 __func__, setKey.encType);
2694
2695
2696
2697 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2698#ifdef WLAN_FEATURE_P2P
2699 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2700#endif
2701 )
2702 {
2703
2704
2705 if (
2706#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2707 (!pairwise)
2708#else
2709 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2710#endif
2711 )
2712 {
2713 /* set group key*/
2714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002715 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002716 __func__, __LINE__);
2717 setKey.keyDirection = eSIR_RX_ONLY;
2718 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2719 }
2720 else
2721 {
2722 /* set pairwise key*/
2723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2724 "%s- %d: setting pairwise key",
2725 __func__, __LINE__);
2726 setKey.keyDirection = eSIR_TX_RX;
2727 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2728 }
2729
2730 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2731 if( pHostapdState->bssState == BSS_START )
2732 {
2733 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2734
2735 if ( status != eHAL_STATUS_SUCCESS )
2736 {
2737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2738 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2739 __LINE__, status );
2740 }
2741 }
2742
2743 /* Saving WEP keys */
2744 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2745 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2746 {
2747 //Save the wep key in ap context. Issue setkey after the BSS is started.
2748 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2749 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2750 }
2751 else
2752 {
2753 //Save the key in ap context. Issue setkey after the BSS is started.
2754 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2755 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2756 }
2757 }
2758 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2759#ifdef WLAN_FEATURE_P2P
2760 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2761#endif
2762 )
2763 {
2764 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2765 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2766
2767 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2768
2769 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2770 params->key, params->key_len);
2771
2772 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2773
2774 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2775 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2776 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2777 )
2778 &&
2779 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2780 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2781 )
2782 )
2783 {
2784 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2785 * interface, copy bssid for pairwise key and group macaddr for
2786 * group key initialization*/
2787
2788 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2789
2790 pWextState->roamProfile.negotiatedUCEncryptionType =
2791 pHddStaCtx->conn_info.ucEncryptionType =
2792 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2793 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2794 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2795
2796
2797 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2798 "%s: Negotiated encryption type %d", __func__,
2799 pWextState->roamProfile.negotiatedUCEncryptionType);
2800
2801 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2802 &pWextState->roamProfile, true);
2803 setKey.keyLength = 0;
2804 setKey.keyDirection = eSIR_TX_RX;
2805
2806#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2807 if (pairwise)
2808 {
2809#endif
2810 if (mac_addr)
2811 {
2812 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2813 }
2814 else
2815 {
2816 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2817 * and peerMacAddress in case of IBSS*/
2818 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2819 {
2820 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2821 if (HDD_MAX_NUM_IBSS_STA != staidx)
2822 {
2823 vos_mem_copy(setKey.peerMac,
2824 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2825 WNI_CFG_BSSID_LEN);
2826
2827 }
2828 else
2829 {
2830 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2831 __func__);
2832 return -EOPNOTSUPP;
2833 }
2834 }
2835 else
2836 {
2837 vos_mem_copy(setKey.peerMac,
2838 &pHddStaCtx->conn_info.bssId[0],
2839 WNI_CFG_BSSID_LEN);
2840 }
2841 }
2842#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2843 }
2844 else
2845 {
2846 /* set group key*/
2847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2848 "%s- %d: setting Group key",
2849 __func__, __LINE__);
2850 setKey.keyDirection = eSIR_RX_ONLY;
2851 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2852 }
2853#endif
2854 }
2855 else if (
2856#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2857 (!pairwise)
2858#else
2859 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2860#endif
2861 )
2862 {
2863 /* set group key*/
2864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2865 "%s- %d: setting Group key",
2866 __func__, __LINE__);
2867 setKey.keyDirection = eSIR_RX_ONLY;
2868 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2869 }
2870 else
2871 {
2872 /* set pairwise key*/
2873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2874 "%s- %d: setting pairwise key",
2875 __func__, __LINE__);
2876 setKey.keyDirection = eSIR_TX_RX;
2877 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2878 }
2879
2880 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2881 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2882 __func__, setKey.peerMac[0], setKey.peerMac[1],
2883 setKey.peerMac[2], setKey.peerMac[3],
2884 setKey.peerMac[4], setKey.peerMac[5],
2885 setKey.keyDirection);
2886
2887 vos_status = wlan_hdd_check_ula_done(pAdapter);
2888
2889 if ( vos_status != VOS_STATUS_SUCCESS )
2890 {
2891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2892 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2893 __LINE__, vos_status );
2894
2895 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2896
2897 return -EINVAL;
2898
2899 }
2900
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002901#ifdef WLAN_FEATURE_VOWIFI_11R
2902 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2903 Save the key in the UMAC and include it in the ADD BSS request */
2904 /*TODO 11r - is this used?? */
2905 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2906 if( halStatus == eHAL_STATUS_SUCCESS )
2907 {
2908 return halStatus;
2909 }
2910#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002911
2912 /* issue set key request to SME*/
2913 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2914 pAdapter->sessionId, &setKey, &roamId );
2915
2916 if ( 0 != status )
2917 {
2918 hddLog(VOS_TRACE_LEVEL_ERROR,
2919 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2920 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2921 return -EINVAL;
2922 }
2923
2924
2925 /* in case of IBSS as there was no information available about WEP keys during
2926 * IBSS join, group key intialized with NULL key, so re-initialize group key
2927 * with correct value*/
2928 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2929 !( ( IW_AUTH_KEY_MGMT_802_1X
2930 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2931 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2932 )
2933 &&
2934 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2935 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2936 )
2937 )
2938 {
2939 setKey.keyDirection = eSIR_RX_ONLY;
2940 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2941
2942 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2943 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2944 __func__, setKey.peerMac[0], setKey.peerMac[1],
2945 setKey.peerMac[2], setKey.peerMac[3],
2946 setKey.peerMac[4], setKey.peerMac[5],
2947 setKey.keyDirection);
2948
2949 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2950 pAdapter->sessionId, &setKey, &roamId );
2951
2952 if ( 0 != status )
2953 {
2954 hddLog(VOS_TRACE_LEVEL_ERROR,
2955 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
2956 __func__, status);
2957 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2958 return -EINVAL;
2959 }
2960 }
2961 }
2962
2963 return 0;
2964}
2965
2966/*
2967 * FUNCTION: wlan_hdd_cfg80211_get_key
2968 * This function is used to get the key information
2969 */
2970#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2971static int wlan_hdd_cfg80211_get_key(
2972 struct wiphy *wiphy,
2973 struct net_device *ndev,
2974 u8 key_index, bool pairwise,
2975 const u8 *mac_addr, void *cookie,
2976 void (*callback)(void *cookie, struct key_params*)
2977 )
2978#else
2979static int wlan_hdd_cfg80211_get_key(
2980 struct wiphy *wiphy,
2981 struct net_device *ndev,
2982 u8 key_index, const u8 *mac_addr, void *cookie,
2983 void (*callback)(void *cookie, struct key_params*)
2984 )
2985#endif
2986{
2987 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2988 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2989 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
2990 struct key_params params;
2991
2992 ENTER();
2993
2994 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2995 __func__,pAdapter->device_mode);
2996
2997 memset(&params, 0, sizeof(params));
2998
2999 if (CSR_MAX_NUM_KEY <= key_index)
3000 {
3001 return -EINVAL;
3002 }
3003
3004 switch(pRoamProfile->EncryptionType.encryptionType[0])
3005 {
3006 case eCSR_ENCRYPT_TYPE_NONE:
3007 params.cipher = IW_AUTH_CIPHER_NONE;
3008 break;
3009
3010 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3011 case eCSR_ENCRYPT_TYPE_WEP40:
3012 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3013 break;
3014
3015 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3016 case eCSR_ENCRYPT_TYPE_WEP104:
3017 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3018 break;
3019
3020 case eCSR_ENCRYPT_TYPE_TKIP:
3021 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3022 break;
3023
3024 case eCSR_ENCRYPT_TYPE_AES:
3025 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3026 break;
3027
3028 default:
3029 params.cipher = IW_AUTH_CIPHER_NONE;
3030 break;
3031 }
3032
3033 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3034 params.seq_len = 0;
3035 params.seq = NULL;
3036 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3037 callback(cookie, &params);
3038 return 0;
3039}
3040
3041/*
3042 * FUNCTION: wlan_hdd_cfg80211_del_key
3043 * This function is used to delete the key information
3044 */
3045#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3046static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3047 struct net_device *ndev,
3048 u8 key_index,
3049 bool pairwise,
3050 const u8 *mac_addr
3051 )
3052#else
3053static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3054 struct net_device *ndev,
3055 u8 key_index,
3056 const u8 *mac_addr
3057 )
3058#endif
3059{
3060 int status = 0;
3061
3062 //This code needs to be revisited. There is sme_removeKey API, we should
3063 //plan to use that. After the change to use correct index in setkey,
3064 //it is observed that this is invalidating peer
3065 //key index whenever re-key is done. This is affecting data link.
3066 //It should be ok to ignore del_key.
3067#if 0
3068 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3069 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3070 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3071 tCsrRoamSetKey setKey;
3072 v_U32_t roamId= 0xFF;
3073
3074 ENTER();
3075
3076 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3077 __func__,pAdapter->device_mode);
3078
3079 if (CSR_MAX_NUM_KEY <= key_index)
3080 {
3081 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3082 key_index);
3083
3084 return -EINVAL;
3085 }
3086
3087 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3088 setKey.keyId = key_index;
3089
3090 if (mac_addr)
3091 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3092 else
3093 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3094
3095 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3096
3097 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3098#ifdef WLAN_FEATURE_P2P
3099 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3100#endif
3101 )
3102 {
3103
3104 hdd_hostapd_state_t *pHostapdState =
3105 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3106 if( pHostapdState->bssState == BSS_START)
3107 {
3108 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3109
3110 if ( status != eHAL_STATUS_SUCCESS )
3111 {
3112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3113 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3114 __LINE__, status );
3115 }
3116 }
3117 }
3118 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3119#ifdef WLAN_FEATURE_P2P
3120 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3121#endif
3122 )
3123 {
3124 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3125
3126 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3127
3128 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3129 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3130 __func__, setKey.peerMac[0], setKey.peerMac[1],
3131 setKey.peerMac[2], setKey.peerMac[3],
3132 setKey.peerMac[4], setKey.peerMac[5]);
3133 if(pAdapter->sessionCtx.station.conn_info.connState ==
3134 eConnectionState_Associated)
3135 {
3136 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3137 pAdapter->sessionId, &setKey, &roamId );
3138
3139 if ( 0 != status )
3140 {
3141 hddLog(VOS_TRACE_LEVEL_ERROR,
3142 "%s: sme_RoamSetKey failure, returned %d",
3143 __func__, status);
3144 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3145 return -EINVAL;
3146 }
3147 }
3148 }
3149#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003150 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003151 return status;
3152}
3153
3154/*
3155 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3156 * This function is used to set the default tx key index
3157 */
3158#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3159static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3160 struct net_device *ndev,
3161 u8 key_index,
3162 bool unicast, bool multicast)
3163#else
3164static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3165 struct net_device *ndev,
3166 u8 key_index)
3167#endif
3168{
3169 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3170 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3171 int status = 0;
3172 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3173
3174 ENTER();
3175
3176 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3177 __func__,pAdapter->device_mode, key_index);
3178
3179 if (CSR_MAX_NUM_KEY <= key_index)
3180 {
3181 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3182 key_index);
3183
3184 return -EINVAL;
3185 }
3186
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003187 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3188 {
3189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3190 "%s:LOGP in Progress. Ignore!!!", __func__);
3191 return -EAGAIN;
3192 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003193
3194 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3195#ifdef WLAN_FEATURE_P2P
3196 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3197#endif
3198 )
3199 {
3200 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3201 (eCSR_ENCRYPT_TYPE_TKIP !=
3202 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3203 (eCSR_ENCRYPT_TYPE_AES !=
3204 pWextState->roamProfile.EncryptionType.encryptionType[0])
3205 )
3206 {
3207 /* if default key index is not same as previous one,
3208 * then update the default key index */
3209
3210 tCsrRoamSetKey setKey;
3211 v_U32_t roamId= 0xFF;
3212 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3213
3214 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3215 __func__, key_index);
3216
3217 Keys->defaultIndex = (u8)key_index;
3218 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3219 setKey.keyId = key_index;
3220 setKey.keyLength = Keys->KeyLength[key_index];
3221
3222 vos_mem_copy(&setKey.Key[0],
3223 &Keys->KeyMaterial[key_index][0],
3224 Keys->KeyLength[key_index]);
3225
3226 setKey.keyDirection = eSIR_TX_ONLY;
3227
3228 vos_mem_copy(setKey.peerMac,
3229 &pHddStaCtx->conn_info.bssId[0],
3230 WNI_CFG_BSSID_LEN);
3231
3232 setKey.encType =
3233 pWextState->roamProfile.EncryptionType.encryptionType[0];
3234
3235 /* issue set key request */
3236 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3237 pAdapter->sessionId, &setKey, &roamId );
3238
3239 if ( 0 != status )
3240 {
3241 hddLog(VOS_TRACE_LEVEL_ERROR,
3242 "%s: sme_RoamSetKey failed, returned %d", __func__,
3243 status);
3244 return -EINVAL;
3245 }
3246 }
3247 }
3248
3249 /* In SoftAp mode setting key direction for default mode */
3250 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3251 {
3252 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3253 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3254 (eCSR_ENCRYPT_TYPE_AES !=
3255 pWextState->roamProfile.EncryptionType.encryptionType[0])
3256 )
3257 {
3258 /* Saving key direction for default key index to TX default */
3259 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3260 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3261 }
3262 }
3263
3264 return status;
3265}
3266
3267/**
3268 * FUNCTION: wlan_hdd_cfg80211_set_channel
3269 * This function is used to set the channel number
3270 */
3271int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3272 struct ieee80211_channel *chan,
3273 enum nl80211_channel_type channel_type
3274 )
3275{
3276 v_U32_t num_ch = 0;
3277 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003278 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003279 int freq = chan->center_freq; /* freq is in MHZ */
3280
3281 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003282
3283 if( NULL == dev )
3284 {
3285 hddLog(VOS_TRACE_LEVEL_ERROR,
3286 "%s: Called with dev = NULL.\n", __func__);
3287 return -ENODEV;
3288 }
3289 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003290
3291 hddLog(VOS_TRACE_LEVEL_INFO,
3292 "%s: device_mode = %d freq = %d \n",__func__,
3293 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003294 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3295 {
3296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3297 return -EAGAIN;
3298 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003299
3300 /*
3301 * Do freq to chan conversion
3302 * TODO: for 11a
3303 */
3304
3305 channel = ieee80211_frequency_to_channel(freq);
3306
3307 /* Check freq range */
3308 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3309 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3310 {
3311 hddLog(VOS_TRACE_LEVEL_ERROR,
3312 "%s: Channel [%d] is outside valid range from %d to %d\n",
3313 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3314 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3315 return -EINVAL;
3316 }
3317
3318 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3319
3320 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3321#ifdef WLAN_FEATURE_P2P
3322 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3323#endif
3324 )
3325 {
3326 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3327 {
3328 hddLog(VOS_TRACE_LEVEL_ERROR,
3329 "%s: Invalid Channel [%d] \n", __func__, channel);
3330 return -EINVAL;
3331 }
3332 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3333 "%s: set channel to [%d] for device mode =%d",
3334 __func__, channel,pAdapter->device_mode);
3335 }
3336 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3337#ifdef WLAN_FEATURE_P2P
3338 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3339#endif
3340 )
3341 {
3342 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3343 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3344 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3345
3346 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3347 {
3348 /* Link is up then return cant set channel*/
3349 hddLog( VOS_TRACE_LEVEL_ERROR,
3350 "%s: IBSS Associated, can't set the channel\n", __func__);
3351 return -EINVAL;
3352 }
3353
3354 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3355 pHddStaCtx->conn_info.operationChannel = channel;
3356 pRoamProfile->ChannelInfo.ChannelList =
3357 &pHddStaCtx->conn_info.operationChannel;
3358 }
3359 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3360#ifdef WLAN_FEATURE_P2P
3361 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3362#endif
3363 )
3364 {
3365 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3366
3367 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3368 {
3369 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3370
3371 /* If auto channel selection is configured as enable/ 1 then ignore
3372 channel set by supplicant
3373 */
3374 if ( cfg_param->apAutoChannelSelection )
3375 {
3376 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3377
3378 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3379 "%s: set channel to auto channel (0) for device mode =%d",
3380 __func__, pAdapter->device_mode);
3381 }
3382 }
3383 }
3384 else
3385 {
3386 hddLog(VOS_TRACE_LEVEL_FATAL,
3387 "%s: Invalid device mode failed to set valid channel", __func__);
3388 return -EINVAL;
3389 }
3390 EXIT();
3391 return 0;
3392}
3393
3394
3395
3396/*
3397 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3398 * This function is used to inform the BSS details to nl80211 interface.
3399 */
3400static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3401 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3402{
3403 struct net_device *dev = pAdapter->dev;
3404 struct wireless_dev *wdev = dev->ieee80211_ptr;
3405 struct wiphy *wiphy = wdev->wiphy;
3406 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3407 int chan_no;
3408 int ie_length;
3409 const char *ie;
3410 unsigned int freq;
3411 struct ieee80211_channel *chan;
3412 int rssi = 0;
3413 struct cfg80211_bss *bss = NULL;
3414
3415 ENTER();
3416
3417 if( NULL == pBssDesc )
3418 {
3419 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3420 return bss;
3421 }
3422
3423 chan_no = pBssDesc->channelId;
3424 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3425 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3426
3427 if( NULL == ie )
3428 {
3429 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3430 return bss;
3431 }
3432
3433#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3434 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3435 {
3436 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3437 }
3438 else
3439 {
3440 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3441 }
3442#else
3443 freq = ieee80211_channel_to_frequency(chan_no);
3444#endif
3445
3446 chan = __ieee80211_get_channel(wiphy, freq);
3447
3448 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3449 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3450 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3451 if (bss == NULL)
3452 {
3453 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3454
3455 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3456 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3457 pBssDesc->capabilityInfo,
3458 pBssDesc->beaconInterval, ie, ie_length,
3459 rssi, GFP_KERNEL ));
3460}
3461 else
3462 {
3463 return bss;
3464 }
3465}
3466
3467
3468
3469/*
3470 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3471 * This function is used to inform the BSS details to nl80211 interface.
3472 */
3473struct cfg80211_bss*
3474wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3475 tSirBssDescription *bss_desc
3476 )
3477{
3478 /*
3479 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3480 already exists in bss data base of cfg80211 for that particular BSS ID.
3481 Using cfg80211_inform_bss_frame to update the bss entry instead of
3482 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3483 now there is no possibility to get the mgmt(probe response) frame from PE,
3484 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3485 cfg80211_inform_bss_frame.
3486 */
3487 struct net_device *dev = pAdapter->dev;
3488 struct wireless_dev *wdev = dev->ieee80211_ptr;
3489 struct wiphy *wiphy = wdev->wiphy;
3490 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003491#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3492 qcom_ie_age *qie_age = NULL;
3493 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3494#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003495 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003496#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003497 const char *ie =
3498 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3499 unsigned int freq;
3500 struct ieee80211_channel *chan;
3501 struct ieee80211_mgmt *mgmt =
3502 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3503 struct cfg80211_bss *bss_status = NULL;
3504 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3505 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003506#ifdef WLAN_OPEN_SOURCE
3507 struct timespec ts;
3508#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003509
3510 ENTER();
3511
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003512 if (!mgmt)
3513 return NULL;
3514
Jeff Johnson295189b2012-06-20 16:38:30 -07003515 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003516
3517#ifdef WLAN_OPEN_SOURCE
3518 /* Android does not want the timestamp from the frame.
3519 Instead it wants a monotonic increasing value */
3520 get_monotonic_boottime(&ts);
3521 mgmt->u.probe_resp.timestamp =
3522 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3523#else
3524 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003525 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3526 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003527
3528#endif
3529
Jeff Johnson295189b2012-06-20 16:38:30 -07003530 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3531 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003532
3533#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3534 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3535 /* Assuming this is the last IE, copy at the end */
3536 ie_length -=sizeof(qcom_ie_age);
3537 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3538 qie_age->element_id = QCOM_VENDOR_IE_ID;
3539 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3540 qie_age->oui_1 = QCOM_OUI1;
3541 qie_age->oui_2 = QCOM_OUI2;
3542 qie_age->oui_3 = QCOM_OUI3;
3543 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3544 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3545#endif
3546
Jeff Johnson295189b2012-06-20 16:38:30 -07003547 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3548
3549 mgmt->frame_control |=
3550 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3551
3552#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3553 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3554 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3555 {
3556 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3557 }
3558 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3559 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3560
3561 {
3562 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3563 }
3564 else
3565 {
3566 kfree(mgmt);
3567 return NULL;
3568 }
3569#else
3570 freq = ieee80211_channel_to_frequency(chan_no);
3571#endif
3572 chan = __ieee80211_get_channel(wiphy, freq);
3573
3574 /*To keep the rssi icon of the connected AP in the scan window
3575 *and the rssi icon of the wireless networks in sync
3576 * */
3577 if (( eConnectionState_Associated ==
3578 pAdapter->sessionCtx.station.conn_info.connState ) &&
3579 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3580 pAdapter->sessionCtx.station.conn_info.bssId,
3581 WNI_CFG_BSSID_LEN)))
3582 {
3583 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3584 rssi = (pAdapter->rssi * 100);
3585 }
3586 else
3587 {
3588 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3589 }
3590
3591 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3592 frame_len, rssi, GFP_KERNEL);
3593 kfree(mgmt);
3594 return bss_status;
3595}
3596
3597/*
3598 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3599 * This function is used to update the BSS data base of CFG8011
3600 */
3601struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3602 tCsrRoamInfo *pRoamInfo
3603 )
3604{
3605 tCsrRoamConnectedProfile roamProfile;
3606 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3607 struct cfg80211_bss *bss = NULL;
3608
3609 ENTER();
3610
3611 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3612 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3613
3614 if (NULL != roamProfile.pBssDesc)
3615 {
3616 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3617 &roamProfile);
3618
3619 if (NULL == bss)
3620 {
3621 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3622 __func__);
3623 }
3624
3625 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3626 }
3627 else
3628 {
3629 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3630 __func__);
3631 }
3632 return bss;
3633}
3634
3635/*
3636 * FUNCTION: wlan_hdd_cfg80211_update_bss
3637 */
3638static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3639 hdd_adapter_t *pAdapter
3640 )
3641{
3642 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3643 tCsrScanResultInfo *pScanResult;
3644 eHalStatus status = 0;
3645 tScanResultHandle pResult;
3646 struct cfg80211_bss *bss_status = NULL;
3647
3648 ENTER();
3649
3650 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3651 {
3652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3653 return -EAGAIN;
3654 }
3655
3656 /*
3657 * start getting scan results and populate cgf80211 BSS database
3658 */
3659 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3660
3661 /* no scan results */
3662 if (NULL == pResult)
3663 {
3664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3665 return status;
3666 }
3667
3668 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3669
3670 while (pScanResult)
3671 {
3672 /*
3673 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3674 * entry already exists in bss data base of cfg80211 for that
3675 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3676 * bss entry instead of cfg80211_inform_bss, But this call expects
3677 * mgmt packet as input. As of now there is no possibility to get
3678 * the mgmt(probe response) frame from PE, converting bss_desc to
3679 * ieee80211_mgmt(probe response) and passing to c
3680 * fg80211_inform_bss_frame.
3681 * */
3682
3683 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3684 &pScanResult->BssDescriptor);
3685
3686
3687 if (NULL == bss_status)
3688 {
3689 hddLog(VOS_TRACE_LEVEL_INFO,
3690 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3691 }
3692 else
3693 {
3694 cfg80211_put_bss(bss_status);
3695 }
3696
3697 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3698 }
3699
3700 sme_ScanResultPurge(hHal, pResult);
3701
3702 return 0;
3703}
3704
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003705void
3706hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3707{
3708 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003709 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3710 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3711 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003712} /****** end hddPrintMacAddr() ******/
3713
3714void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003715hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003716{
3717 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003718 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3719 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3720 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3721 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003722} /****** end hddPrintPmkId() ******/
3723
3724//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3725//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3726
3727//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3728//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3729
3730#define dump_bssid(bssid) \
3731 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003732 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3733 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3734 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003735 }
3736
3737#define dump_pmkid(pMac, pmkid) \
3738 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003739 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3740 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3741 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003742 }
3743
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003744#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003745/*
3746 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3747 * This function is used to notify the supplicant of a new PMKSA candidate.
3748 */
3749int wlan_hdd_cfg80211_pmksa_candidate_notify(
3750 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3751 int index, bool preauth )
3752{
Jeff Johnsone7245742012-09-05 17:12:55 -07003753#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003754 struct net_device *dev = pAdapter->dev;
3755
3756 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003757 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003758
3759 if( NULL == pRoamInfo )
3760 {
3761 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3762 return -EINVAL;
3763 }
3764
3765 dump_bssid(pRoamInfo->bssid);
3766 cfg80211_pmksa_candidate_notify(dev, index,
3767 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003768#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003769 return 0;
3770}
3771#endif //FEATURE_WLAN_LFR
3772
Jeff Johnson295189b2012-06-20 16:38:30 -07003773/*
3774 * FUNCTION: hdd_cfg80211_scan_done_callback
3775 * scanning callback function, called after finishing scan
3776 *
3777 */
3778static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3779 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3780{
3781 struct net_device *dev = (struct net_device *) pContext;
3782 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3783 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003784 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3785 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003786 struct cfg80211_scan_request *req = NULL;
3787 int ret = 0;
3788
3789 ENTER();
3790
3791 hddLog(VOS_TRACE_LEVEL_INFO,
3792 "%s called with halHandle = %p, pContext = %p,"
3793 "scanID = %d, returned status = %d\n",
3794 __func__, halHandle, pContext, (int) scanId, (int) status);
3795
3796 //Block on scan req completion variable. Can't wait forever though.
3797 ret = wait_for_completion_interruptible_timeout(
3798 &pScanInfo->scan_req_completion_event,
3799 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3800 if (!ret)
3801 {
3802 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003803 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 }
3805
3806 if(pScanInfo->mScanPending != VOS_TRUE)
3807 {
3808 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003809 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 }
3811
3812 /* Check the scanId */
3813 if (pScanInfo->scanId != scanId)
3814 {
3815 hddLog(VOS_TRACE_LEVEL_INFO,
3816 "%s called with mismatched scanId pScanInfo->scanId = %d "
3817 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3818 (int) scanId);
3819 }
3820
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3822 pAdapter);
3823
3824 if (0 > ret)
3825 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3826
3827
3828 /* If any client wait scan result through WEXT
3829 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003830 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003831 {
3832 /* The other scan request waiting for current scan finish
3833 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003834 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003835 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003836 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 }
3838 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003839 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003840 {
3841 struct net_device *dev = pAdapter->dev;
3842 union iwreq_data wrqu;
3843 int we_event;
3844 char *msg;
3845
3846 memset(&wrqu, '\0', sizeof(wrqu));
3847 we_event = SIOCGIWSCAN;
3848 msg = NULL;
3849 wireless_send_event(dev, we_event, &wrqu, msg);
3850 }
3851 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003852 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003853
3854 /* Get the Scan Req */
3855 req = pAdapter->request;
3856
3857 if (!req)
3858 {
3859 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003860 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003861 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 }
3863
3864 /*
3865 * setting up 0, just in case.
3866 */
3867 req->n_ssids = 0;
3868 req->n_channels = 0;
3869 req->ie = 0;
3870
Jeff Johnson295189b2012-06-20 16:38:30 -07003871 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003872 /* Scan is no longer pending */
3873 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003874
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003875 /*
3876 * cfg80211_scan_done informing NL80211 about completion
3877 * of scanning
3878 */
3879 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003880 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003881
Jeff Johnsone7245742012-09-05 17:12:55 -07003882allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003883 /* release the wake lock at the end of the scan*/
3884 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003885
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003886 /* Acquire wakelock to handle the case where APP's tries to suspend
3887 * immediatly after the driver gets connect request(i.e after scan)
3888 * from supplicant, this result in app's is suspending and not able
3889 * to process the connect request to AP */
3890 hdd_allow_suspend_timeout(100);
3891
Jeff Johnson295189b2012-06-20 16:38:30 -07003892 EXIT();
3893 return 0;
3894}
3895
3896/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08003897 * FUNCTION: hdd_isScanAllowed
3898 * Go through each adapter and check if scan allowed
3899 *
3900 */
3901v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
3902{
3903 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3904 hdd_station_ctx_t *pHddStaCtx = NULL;
3905 hdd_adapter_t *pAdapter = NULL;
3906 VOS_STATUS status = 0;
3907 v_U8_t staId = 0;
3908 v_U8_t *staMac = NULL;
3909
3910 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3911
3912 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3913 {
3914 pAdapter = pAdapterNode->pAdapter;
3915
3916 if( pAdapter )
3917 {
3918 hddLog(VOS_TRACE_LEVEL_INFO,
3919 "%s: Adapter with device mode %d exists",
3920 __func__, pAdapter->device_mode);
3921 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3922 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3923 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
3924 {
3925 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3926 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
3927 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
3928 {
3929 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
3930 hddLog(VOS_TRACE_LEVEL_ERROR,
3931 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
3932 "middle of WPS/EAPOL exchange.", __func__,
3933 staMac[0], staMac[1], staMac[2],
3934 staMac[3], staMac[4], staMac[5]);
3935 return VOS_FALSE;
3936 }
3937 }
3938 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
3939 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
3940 {
3941 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
3942 {
3943 if ((pAdapter->aStaInfo[staId].isUsed) &&
3944 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
3945 {
3946 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
3947
3948 hddLog(VOS_TRACE_LEVEL_ERROR,
3949 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
3950 "middle of WPS/EAPOL exchange.", __func__,
3951 staMac[0], staMac[1], staMac[2],
3952 staMac[3], staMac[4], staMac[5]);
3953 return VOS_FALSE;
3954 }
3955 }
3956 }
3957 }
3958 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3959 pAdapterNode = pNext;
3960 }
3961 hddLog(VOS_TRACE_LEVEL_INFO,
3962 "%s: Scan allowed", __func__);
3963 return VOS_TRUE;
3964}
3965
3966/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003967 * FUNCTION: wlan_hdd_cfg80211_scan
3968 * this scan respond to scan trigger and update cfg80211 scan database
3969 * later, scan dump command can be used to recieve scan results
3970 */
3971int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3972 struct cfg80211_scan_request *request)
3973{
3974 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3975 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3976 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3977 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3978 tCsrScanRequest scanRequest;
3979 tANI_U8 *channelList = NULL, i;
3980 v_U32_t scanId = 0;
3981 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003982 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003983#ifdef WLAN_FEATURE_P2P
3984 v_U8_t* pP2pIe = NULL;
3985#endif
3986
3987 ENTER();
3988
3989 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3990 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003991
3992 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
3993 (eConnectionState_Connecting ==
3994 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
3995 {
3996 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08003997 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
3998 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003999 return -EBUSY;
4000 }
4001
Jeff Johnson295189b2012-06-20 16:38:30 -07004002#ifdef WLAN_BTAMP_FEATURE
4003 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004004 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004005 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004006 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004007 "%s: No scanning when AMP is on", __func__);
4008 return -EOPNOTSUPP;
4009 }
4010#endif
4011 //Scan on any other interface is not supported.
4012 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4013 {
4014 hddLog(VOS_TRACE_LEVEL_ERROR,
4015 "%s: Not scanning on device_mode = %d",
4016 __func__, pAdapter->device_mode);
4017 return -EOPNOTSUPP;
4018 }
4019
4020 if (TRUE == pScanInfo->mScanPending)
4021 {
4022 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4023 return -EBUSY;
4024 }
4025
4026 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4027 {
4028 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4029 "%s:LOGP in Progress. Ignore!!!", __func__);
4030 return -EAGAIN;
4031 }
4032
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004033 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4034 {
4035 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4036 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4037 return -EAGAIN;
4038 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004039 //Don't Allow Scan and return busy if Remain On
4040 //Channel and action frame is pending
4041 //Otherwise Cancel Remain On Channel and allow Scan
4042 //If no action frame pending
4043 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4044 {
4045 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4046 return -EBUSY;
4047 }
4048
Jeff Johnson295189b2012-06-20 16:38:30 -07004049 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4050 {
4051 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004052 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004053 return -EAGAIN;
4054 }
4055 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4056 {
4057 hddLog(VOS_TRACE_LEVEL_WARN,
4058 "%s: MAX TM Level Scan not allowed", __func__);
4059 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4060 return -EBUSY;
4061 }
4062 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4063
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004064 /* Check if scan is allowed at this point of time.
4065 */
4066 if (!hdd_isScanAllowed(pHddCtx))
4067 {
4068 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4069 return -EBUSY;
4070 }
4071
Jeff Johnson295189b2012-06-20 16:38:30 -07004072 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4073
4074 if (NULL != request)
4075 {
4076 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4077 (int)request->n_ssids);
4078
4079 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4080 * Becasue of this, driver is assuming that this is not wildcard scan and so
4081 * is not aging out the scan results.
4082 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004083 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004084 {
4085 request->n_ssids = 0;
4086 }
4087
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004088 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004089 {
4090 tCsrSSIDInfo *SsidInfo;
4091 int j;
4092 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4093 /* Allocate num_ssid tCsrSSIDInfo structure */
4094 SsidInfo = scanRequest.SSIDs.SSIDList =
4095 ( tCsrSSIDInfo *)vos_mem_malloc(
4096 request->n_ssids*sizeof(tCsrSSIDInfo));
4097
4098 if(NULL == scanRequest.SSIDs.SSIDList)
4099 {
4100 hddLog(VOS_TRACE_LEVEL_ERROR,
4101 "memory alloc failed SSIDInfo buffer");
4102 return -ENOMEM;
4103 }
4104
4105 /* copy all the ssid's and their length */
4106 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4107 {
4108 /* get the ssid length */
4109 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4110 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4111 SsidInfo->SSID.length);
4112 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4113 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4114 j, SsidInfo->SSID.ssId);
4115 }
4116 /* set the scan type to active */
4117 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4118 }
4119 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4120 {
4121 /* set the scan type to active */
4122 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4123 }
4124 else
4125 {
4126 /*Set the scan type to default type, in this case it is ACTIVE*/
4127 scanRequest.scanType = pScanInfo->scan_mode;
4128 }
4129 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4130 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4131 }
4132 else
4133 {
4134 /* set the scan type to active */
4135 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4136 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4137
4138 /* set min and max channel time to zero */
4139 scanRequest.minChnTime = 0;
4140 scanRequest.maxChnTime = 0;
4141 }
4142
4143 /* set BSSType to default type */
4144 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4145
4146 /*TODO: scan the requested channels only*/
4147
4148 /*Right now scanning all the channels */
4149 if( request )
4150 {
4151 if( request->n_channels )
4152 {
4153 channelList = vos_mem_malloc( request->n_channels );
4154 if( NULL == channelList )
4155 {
4156 status = -ENOMEM;
4157 goto free_mem;
4158 }
4159
4160 for( i = 0 ; i < request->n_channels ; i++ )
4161 channelList[i] = request->channels[i]->hw_value;
4162 }
4163
4164 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4165 scanRequest.ChannelInfo.ChannelList = channelList;
4166
4167 /* set requestType to full scan */
4168 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004169
4170 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4171 * search (Flush on both full scan and social scan but not on single
4172 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4173 */
4174
4175 /* Supplicant does single channel scan after 8-way handshake
4176 * and in that case driver shoudnt flush scan results. If
4177 * driver flushes the scan results here and unfortunately if
4178 * the AP doesnt respond to our probe req then association
4179 * fails which is not desired
4180 */
4181
4182 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4183 {
4184 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4185 pAdapter->sessionId );
4186 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004187
4188 if( request->ie_len )
4189 {
4190 /* save this for future association (join requires this) */
4191 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4192 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4193 pScanInfo->scanAddIE.length = request->ie_len;
4194
4195 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004196 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4197 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004198 )
4199 {
4200 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4201 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4202 }
4203
4204 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4205 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4206
4207#ifdef WLAN_FEATURE_P2P
4208 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4209 request->ie_len);
4210 if (pP2pIe != NULL)
4211 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004212#ifdef WLAN_FEATURE_P2P_DEBUG
4213 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4214 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4215 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4216 {
4217 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4218 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4219 "Go nego completed to Connection is started");
4220 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4221 "for 8way Handshake");
4222 }
4223 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4224 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4225 {
4226 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4227 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4228 "Disconnected state to Connection is started");
4229 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4230 "for 4way Handshake");
4231 }
4232#endif
4233
Jeff Johnsone7245742012-09-05 17:12:55 -07004234 /* no_cck will be set during p2p find to disable 11b rates */
4235 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004236 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004237 hddLog(VOS_TRACE_LEVEL_INFO,
4238 "%s: This is a P2P Search", __func__);
4239 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004240
Jeff Johnsone7245742012-09-05 17:12:55 -07004241 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4242 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004243 /* set requestType to P2P Discovery */
4244 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004245 }
4246
4247 /*
4248 Skip Dfs Channel in case of P2P Search
4249 if it is set in ini file
4250 */
4251 if(cfg_param->skipDfsChnlInP2pSearch)
4252 {
4253 scanRequest.skipDfsChnlInP2pSearch = 1;
4254 }
4255 else
4256 {
4257 scanRequest.skipDfsChnlInP2pSearch = 0;
4258 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004259
Jeff Johnson295189b2012-06-20 16:38:30 -07004260 }
4261 }
4262#endif
4263 }
4264 }
4265
4266 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4267
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004268 /* acquire the wakelock to avoid the apps suspend during the scan. To
4269 * address the following issues.
4270 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4271 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4272 * for long time, this result in apps running at full power for long time.
4273 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4274 * be stuck in full power because of resume BMPS
4275 */
4276 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004277
4278 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004279 pAdapter->sessionId, &scanRequest, &scanId,
4280 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004281
Jeff Johnson295189b2012-06-20 16:38:30 -07004282 if (eHAL_STATUS_SUCCESS != status)
4283 {
4284 hddLog(VOS_TRACE_LEVEL_ERROR,
4285 "%s: sme_ScanRequest returned error %d", __func__, status);
4286 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004287 if(eHAL_STATUS_RESOURCES == status)
4288 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004289 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 -07004290 status = -EBUSY;
4291 } else {
4292 status = -EIO;
4293 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004294 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004295 goto free_mem;
4296 }
4297
4298 pScanInfo->mScanPending = TRUE;
4299 pAdapter->request = request;
4300 pScanInfo->scanId = scanId;
4301
4302 complete(&pScanInfo->scan_req_completion_event);
4303
4304free_mem:
4305 if( scanRequest.SSIDs.SSIDList )
4306 {
4307 vos_mem_free(scanRequest.SSIDs.SSIDList);
4308 }
4309
4310 if( channelList )
4311 vos_mem_free( channelList );
4312
4313 EXIT();
4314
4315 return status;
4316}
4317
4318/*
4319 * FUNCTION: wlan_hdd_cfg80211_connect_start
4320 * This function is used to start the association process
4321 */
4322int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004323 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004324{
4325 int status = 0;
4326 hdd_wext_state_t *pWextState;
4327 v_U32_t roamId;
4328 tCsrRoamProfile *pRoamProfile;
4329 eMib_dot11DesiredBssType connectedBssType;
4330 eCsrAuthType RSNAuthType;
4331
4332 ENTER();
4333
4334 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4335
4336 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4337 {
4338 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4339 return -EINVAL;
4340 }
4341
4342 pRoamProfile = &pWextState->roamProfile;
4343
4344 if (pRoamProfile)
4345 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004346 int ret = 0;
4347 hdd_station_ctx_t *pHddStaCtx;
4348 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4349 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4350
4351 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4352 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4353 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004354 {
4355 /* Issue disconnect to CSR */
4356 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4357 if( eHAL_STATUS_SUCCESS ==
4358 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4359 pAdapter->sessionId,
4360 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4361 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004362 ret = wait_for_completion_interruptible_timeout(
4363 &pAdapter->disconnect_comp_var,
4364 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4365 if (0 == ret)
4366 {
4367 VOS_ASSERT(0);
4368 }
4369 }
4370 }
4371 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4372 {
4373 ret = wait_for_completion_interruptible_timeout(
4374 &pAdapter->disconnect_comp_var,
4375 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4376 if (0 == ret)
4377 {
4378 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004379 }
4380 }
4381
4382 if (HDD_WMM_USER_MODE_NO_QOS ==
4383 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4384 {
4385 /*QoS not enabled in cfg file*/
4386 pRoamProfile->uapsd_mask = 0;
4387 }
4388 else
4389 {
4390 /*QoS enabled, update uapsd mask from cfg file*/
4391 pRoamProfile->uapsd_mask =
4392 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4393 }
4394
4395 pRoamProfile->SSIDs.numOfSSIDs = 1;
4396 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4397 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4398 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4399 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4400 ssid, ssid_len);
4401
4402 if (bssid)
4403 {
4404 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4405 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4406 WNI_CFG_BSSID_LEN);
4407 /* Save BSSID in seperate variable as well, as RoamProfile
4408 BSSID is getting zeroed out in the association process. And in
4409 case of join failure we should send valid BSSID to supplicant
4410 */
4411 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4412 WNI_CFG_BSSID_LEN);
4413 }
4414
4415 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4416 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4417 {
4418 /*set gen ie*/
4419 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4420 /*set auth*/
4421 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4422 }
4423 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4424 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4425 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4426 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4427 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4428 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4429 )
4430 {
4431 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4432 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4433 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4434 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4435 eCSR_AUTH_TYPE_AUTOSWITCH;
4436 pWextState->roamProfile.AuthType.authType[0] =
4437 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4438 }
4439#ifdef FEATURE_WLAN_WAPI
4440 if (pAdapter->wapi_info.nWapiMode)
4441 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004442 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004443 switch (pAdapter->wapi_info.wapiAuthMode)
4444 {
4445 case WAPI_AUTH_MODE_PSK:
4446 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004447 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004448 pAdapter->wapi_info.wapiAuthMode);
4449 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4450 break;
4451 }
4452 case WAPI_AUTH_MODE_CERT:
4453 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004454 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004455 pAdapter->wapi_info.wapiAuthMode);
4456 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4457 break;
4458 }
4459 } // End of switch
4460 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4461 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4462 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004463 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004464 pRoamProfile->AuthType.numEntries = 1;
4465 pRoamProfile->EncryptionType.numEntries = 1;
4466 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4467 pRoamProfile->mcEncryptionType.numEntries = 1;
4468 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4469 }
4470 }
4471#endif /* FEATURE_WLAN_WAPI */
4472 pRoamProfile->csrPersona = pAdapter->device_mode;
4473
Jeff Johnson32d95a32012-09-10 13:15:23 -07004474 if( operatingChannel )
4475 {
4476 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4477 pRoamProfile->ChannelInfo.numOfChannels = 1;
4478 }
4479
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004480 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4481 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4482 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4483 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004484 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4485 */
4486 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4487 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4488 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004489
Jeff Johnson295189b2012-06-20 16:38:30 -07004490 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4491 pAdapter->sessionId, pRoamProfile, &roamId);
4492
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004493 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304494 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4495
4496 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004497 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4498 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4499 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304500 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004501 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304502 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004503
4504 pRoamProfile->ChannelInfo.ChannelList = NULL;
4505 pRoamProfile->ChannelInfo.numOfChannels = 0;
4506
Jeff Johnson295189b2012-06-20 16:38:30 -07004507 }
4508 else
4509 {
4510 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4511 return -EINVAL;
4512 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004513 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004514 return status;
4515}
4516
4517/*
4518 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4519 * This function is used to set the authentication type (OPEN/SHARED).
4520 *
4521 */
4522static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4523 enum nl80211_auth_type auth_type)
4524{
4525 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4526 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4527
4528 ENTER();
4529
4530 /*set authentication type*/
4531 switch (auth_type)
4532 {
4533 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4534 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004535#ifdef WLAN_FEATURE_VOWIFI_11R
4536 case NL80211_AUTHTYPE_FT:
4537#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004538 hddLog(VOS_TRACE_LEVEL_INFO,
4539 "%s: set authentication type to OPEN", __func__);
4540 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4541 break;
4542
4543 case NL80211_AUTHTYPE_SHARED_KEY:
4544 hddLog(VOS_TRACE_LEVEL_INFO,
4545 "%s: set authentication type to SHARED", __func__);
4546 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4547 break;
4548#ifdef FEATURE_WLAN_CCX
4549 case NL80211_AUTHTYPE_NETWORK_EAP:
4550 hddLog(VOS_TRACE_LEVEL_INFO,
4551 "%s: set authentication type to CCKM WPA", __func__);
4552 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4553 break;
4554#endif
4555
4556
4557 default:
4558 hddLog(VOS_TRACE_LEVEL_ERROR,
4559 "%s: Unsupported authentication type %d", __func__,
4560 auth_type);
4561 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4562 return -EINVAL;
4563 }
4564
4565 pWextState->roamProfile.AuthType.authType[0] =
4566 pHddStaCtx->conn_info.authType;
4567 return 0;
4568}
4569
4570/*
4571 * FUNCTION: wlan_hdd_set_akm_suite
4572 * This function is used to set the key mgmt type(PSK/8021x).
4573 *
4574 */
4575static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4576 u32 key_mgmt
4577 )
4578{
4579 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4580 ENTER();
4581
4582 /*set key mgmt type*/
4583 switch(key_mgmt)
4584 {
4585 case WLAN_AKM_SUITE_PSK:
4586 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4587 __func__);
4588 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4589 break;
4590
4591 case WLAN_AKM_SUITE_8021X:
4592 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4593 __func__);
4594 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4595 break;
4596#ifdef FEATURE_WLAN_CCX
4597#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4598#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4599 case WLAN_AKM_SUITE_CCKM:
4600 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4601 __func__);
4602 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4603 break;
4604#endif
4605
4606 default:
4607 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4608 __func__, key_mgmt);
4609 return -EINVAL;
4610
4611 }
4612 return 0;
4613}
4614
4615/*
4616 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4617 * This function is used to set the encryption type
4618 * (NONE/WEP40/WEP104/TKIP/CCMP).
4619 */
4620static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4621 u32 cipher,
4622 bool ucast
4623 )
4624{
4625 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4626 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4627 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4628
4629 ENTER();
4630
4631 if (!cipher)
4632 {
4633 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4634 __func__, cipher);
4635 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4636 }
4637 else
4638 {
4639
4640 /*set encryption method*/
4641 switch (cipher)
4642 {
4643 case IW_AUTH_CIPHER_NONE:
4644 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4645 break;
4646
4647 case WLAN_CIPHER_SUITE_WEP40:
4648 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4649 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4650 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4651 else
4652 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4653 break;
4654
4655 case WLAN_CIPHER_SUITE_WEP104:
4656 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4657 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4658 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4659 else
4660 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4661 break;
4662
4663 case WLAN_CIPHER_SUITE_TKIP:
4664 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4665 break;
4666
4667 case WLAN_CIPHER_SUITE_CCMP:
4668 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4669 break;
4670#ifdef FEATURE_WLAN_WAPI
4671 case WLAN_CIPHER_SUITE_SMS4:
4672 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4673 break;
4674#endif
4675
4676#ifdef FEATURE_WLAN_CCX
4677 case WLAN_CIPHER_SUITE_KRK:
4678 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4679 break;
4680#endif
4681 default:
4682 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4683 __func__, cipher);
4684 return -EOPNOTSUPP;
4685 }
4686 }
4687
4688 if (ucast)
4689 {
4690 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4691 __func__, encryptionType);
4692 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4693 pWextState->roamProfile.EncryptionType.numEntries = 1;
4694 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4695 encryptionType;
4696 }
4697 else
4698 {
4699 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4700 __func__, encryptionType);
4701 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4702 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4703 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4704 }
4705
4706 return 0;
4707}
4708
4709
4710/*
4711 * FUNCTION: wlan_hdd_cfg80211_set_ie
4712 * This function is used to parse WPA/RSN IE's.
4713 */
4714int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4715 u8 *ie,
4716 size_t ie_len
4717 )
4718{
4719 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4720 u8 *genie = ie;
4721 v_U16_t remLen = ie_len;
4722#ifdef FEATURE_WLAN_WAPI
4723 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4724 u16 *tmp;
4725 v_U16_t akmsuiteCount;
4726 int *akmlist;
4727#endif
4728 ENTER();
4729
4730 /* clear previous assocAddIE */
4731 pWextState->assocAddIE.length = 0;
4732 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4733
4734 while (remLen >= 2)
4735 {
4736 v_U16_t eLen = 0;
4737 v_U8_t elementId;
4738 elementId = *genie++;
4739 eLen = *genie++;
4740 remLen -= 2;
4741
4742 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4743 __func__, elementId, eLen);
4744
4745 switch ( elementId )
4746 {
4747 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004748 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 -07004749 {
4750 hddLog(VOS_TRACE_LEVEL_ERROR,
4751 "%s: Invalid WPA IE", __func__);
4752 return -EINVAL;
4753 }
4754 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4755 {
4756 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4757 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4758 __func__, eLen + 2);
4759
4760 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4761 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004762 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4763 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004764 VOS_ASSERT(0);
4765 return -ENOMEM;
4766 }
4767 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4768 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4769 pWextState->assocAddIE.length += eLen + 2;
4770
4771 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4772 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4773 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4774 }
4775 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4776 {
4777 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4778 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4779 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4780 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4781 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4782 }
4783#ifdef WLAN_FEATURE_P2P
4784 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4785 P2P_OUI_TYPE_SIZE))
4786 /*Consider P2P IE, only for P2P Client */
4787 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4788 {
4789 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4790 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4791 __func__, eLen + 2);
4792
4793 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4794 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004795 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4796 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004797 VOS_ASSERT(0);
4798 return -ENOMEM;
4799 }
4800 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4801 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4802 pWextState->assocAddIE.length += eLen + 2;
4803
4804 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4805 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4806 }
4807#endif
4808#ifdef WLAN_FEATURE_WFD
4809 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4810 WFD_OUI_TYPE_SIZE))
4811 /*Consider WFD IE, only for P2P Client */
4812 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4813 {
4814 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4815 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4816 __func__, eLen + 2);
4817
4818 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4819 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004820 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4821 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004822 VOS_ASSERT(0);
4823 return -ENOMEM;
4824 }
4825 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4826 // WPS IE + P2P IE + WFD IE
4827 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4828 pWextState->assocAddIE.length += eLen + 2;
4829
4830 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4831 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4832 }
4833#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004834 /* Appending HS 2.0 Indication Element in Assiciation Request */
4835 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004836 HS20_OUI_TYPE_SIZE)) )
4837 {
4838 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4839 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4840 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004841
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004842 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4843 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004844 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4845 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004846 VOS_ASSERT(0);
4847 return -ENOMEM;
4848 }
4849 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4850 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004851
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004852 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4853 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4854 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004855
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 break;
4857 case DOT11F_EID_RSN:
4858 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4859 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4860 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4861 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4862 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4863 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004864 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4865 case DOT11F_EID_EXTCAP:
4866 {
4867 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4868 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4869 __func__, eLen + 2);
4870
4871 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4872 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004873 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4874 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004875 VOS_ASSERT(0);
4876 return -ENOMEM;
4877 }
4878 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4879 pWextState->assocAddIE.length += eLen + 2;
4880
4881 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4882 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4883 break;
4884 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004885#ifdef FEATURE_WLAN_WAPI
4886 case WLAN_EID_WAPI:
4887 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4888 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4889 pAdapter->wapi_info.nWapiMode);
4890 tmp = (u16 *)ie;
4891 tmp = tmp + 2; // Skip element Id and Len, Version
4892 akmsuiteCount = WPA_GET_LE16(tmp);
4893 tmp = tmp + 1;
4894 akmlist = (int *)(tmp);
4895 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4896 {
4897 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4898 }
4899 else
4900 {
4901 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4902 VOS_ASSERT(0);
4903 return -EINVAL;
4904 }
4905
4906 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4907 {
4908 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004909 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4911 }
4912 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4913 {
4914 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004915 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004916 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4917 }
4918 break;
4919#endif
4920 default:
4921 hddLog (VOS_TRACE_LEVEL_ERROR,
4922 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004923 /* when Unknown IE is received we should break and continue
4924 * to the next IE in the buffer instead we were returning
4925 * so changing this to break */
4926 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004927 }
4928 genie += eLen;
4929 remLen -= eLen;
4930 }
4931 EXIT();
4932 return 0;
4933}
4934
4935/*
4936 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4937 * This function is used to initialize the security
4938 * parameters during connect operation.
4939 */
4940int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4941 struct cfg80211_connect_params *req
4942 )
4943{
4944 int status = 0;
4945 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4946 ENTER();
4947
4948 /*set wpa version*/
4949 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4950
4951 if (req->crypto.wpa_versions)
4952 {
4953 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4954 && ( (req->ie_len)
4955 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4956 // Make sure that it is including a WPA IE.
4957 /* Currently NL is putting WPA version 1 even for open,
4958 * since p2p ie is also put in same buffer.
4959 * */
4960 {
4961 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4962 }
4963 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4964 {
4965 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4966 }
4967 }
4968
4969 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4970 pWextState->wpaVersion);
4971
4972 /*set authentication type*/
4973 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4974
4975 if (0 > status)
4976 {
4977 hddLog(VOS_TRACE_LEVEL_ERROR,
4978 "%s: failed to set authentication type ", __func__);
4979 return status;
4980 }
4981
4982 /*set key mgmt type*/
4983 if (req->crypto.n_akm_suites)
4984 {
4985 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4986 if (0 > status)
4987 {
4988 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4989 __func__);
4990 return status;
4991 }
4992 }
4993
4994 /*set pairwise cipher type*/
4995 if (req->crypto.n_ciphers_pairwise)
4996 {
4997 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4998 req->crypto.ciphers_pairwise[0], true);
4999 if (0 > status)
5000 {
5001 hddLog(VOS_TRACE_LEVEL_ERROR,
5002 "%s: failed to set unicast cipher type", __func__);
5003 return status;
5004 }
5005 }
5006 else
5007 {
5008 /*Reset previous cipher suite to none*/
5009 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5010 if (0 > status)
5011 {
5012 hddLog(VOS_TRACE_LEVEL_ERROR,
5013 "%s: failed to set unicast cipher type", __func__);
5014 return status;
5015 }
5016 }
5017
5018 /*set group cipher type*/
5019 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5020 false);
5021
5022 if (0 > status)
5023 {
5024 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5025 __func__);
5026 return status;
5027 }
5028
5029 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5030 if (req->ie_len)
5031 {
5032 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5033 if ( 0 > status)
5034 {
5035 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5036 __func__);
5037 return status;
5038 }
5039 }
5040
5041 /*incase of WEP set default key information*/
5042 if (req->key && req->key_len)
5043 {
5044 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5045 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5046 )
5047 {
5048 if ( IW_AUTH_KEY_MGMT_802_1X
5049 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5050 {
5051 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5052 __func__);
5053 return -EOPNOTSUPP;
5054 }
5055 else
5056 {
5057 u8 key_len = req->key_len;
5058 u8 key_idx = req->key_idx;
5059
5060 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5061 && (CSR_MAX_NUM_KEY > key_idx)
5062 )
5063 {
5064 hddLog(VOS_TRACE_LEVEL_INFO,
5065 "%s: setting default wep key, key_idx = %hu key_len %hu",
5066 __func__, key_idx, key_len);
5067 vos_mem_copy(
5068 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5069 req->key, key_len);
5070 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5071 (u8)key_len;
5072 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5073 }
5074 }
5075 }
5076 }
5077
5078 return status;
5079}
5080
5081/*
5082 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5083 * This function is used to initialize the security
5084 * parameters during connect operation.
5085 */
5086static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5087 struct net_device *ndev,
5088 struct cfg80211_connect_params *req
5089 )
5090{
5091 int status = 0;
5092 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5093 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5094 hdd_context_t *pHddCtx = NULL;
5095
5096 ENTER();
5097
5098 hddLog(VOS_TRACE_LEVEL_INFO,
5099 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5100
5101 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5102 {
5103 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5104 "%s:LOGP in Progress. Ignore!!!", __func__);
5105 return -EAGAIN;
5106 }
5107
5108#ifdef WLAN_BTAMP_FEATURE
5109 //Infra connect not supported when AMP traffic is on.
5110 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5111 {
5112 hddLog(VOS_TRACE_LEVEL_ERROR,
5113 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005114 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005115 }
5116#endif
5117 /*initialise security parameters*/
5118 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5119
5120 if ( 0 > status)
5121 {
5122 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5123 __func__);
5124 return status;
5125 }
5126
5127 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005128 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005129 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5130 (vos_concurrent_sessions_running()))
5131 {
5132 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5133
5134 if (NULL != pVosContext)
5135 {
5136 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5137 if(NULL != pHddCtx)
5138 {
5139 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5140 }
5141 }
5142 }
5143
Mohit Khanna765234a2012-09-11 15:08:35 -07005144 if ( req->channel )
5145 {
5146 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5147 req->ssid_len, req->bssid,
5148 req->channel->hw_value);
5149 }
5150 else
5151 {
5152 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5153 req->ssid_len, req->bssid,
5154 0);
5155 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005156
5157 if (0 > status)
5158 {
5159 //ReEnable BMPS if disabled
5160 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5161 (NULL != pHddCtx))
5162 {
5163 //ReEnable Bmps and Imps back
5164 hdd_enable_bmps_imps(pHddCtx);
5165 }
5166
5167 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5168 return status;
5169 }
5170 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5171 EXIT();
5172 return status;
5173}
5174
5175
5176/*
5177 * FUNCTION: wlan_hdd_cfg80211_disconnect
5178 * This function is used to issue a disconnect request to SME
5179 */
5180static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5181 struct net_device *dev,
5182 u16 reason
5183 )
5184{
5185 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5186 tCsrRoamProfile *pRoamProfile =
5187 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5188 int status = 0;
5189 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5190
5191 ENTER();
5192
5193 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5194 __func__,pAdapter->device_mode);
5195
5196 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5197 __func__, reason);
5198
5199 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5200 {
5201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5202 "%s:LOGP in Progress. Ignore!!!",__func__);
5203 return -EAGAIN;
5204 }
5205 if (NULL != pRoamProfile)
5206 {
5207 /*issue disconnect request to SME, if station is in connected state*/
5208 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5209 {
5210 eCsrRoamDisconnectReason reasonCode =
5211 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5212 switch(reason)
5213 {
5214 case WLAN_REASON_MIC_FAILURE:
5215 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5216 break;
5217
5218 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5219 case WLAN_REASON_DISASSOC_AP_BUSY:
5220 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5221 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5222 break;
5223
5224 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5225 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5226 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5227 break;
5228
5229 case WLAN_REASON_DEAUTH_LEAVING:
5230 default:
5231 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5232 break;
5233 }
5234 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5235 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5236 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5237
5238 /*issue disconnect*/
5239 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5240 pAdapter->sessionId, reasonCode);
5241
5242 if ( 0 != status)
5243 {
5244 hddLog(VOS_TRACE_LEVEL_ERROR,
5245 "%s csrRoamDisconnect failure, returned %d \n",
5246 __func__, (int)status );
5247 return -EINVAL;
5248 }
5249
5250 wait_for_completion_interruptible_timeout(
5251 &pAdapter->disconnect_comp_var,
5252 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5253
5254
5255 /*stop tx queues*/
5256 netif_tx_disable(dev);
5257 netif_carrier_off(dev);
5258 }
5259 }
5260 else
5261 {
5262 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5263 }
5264
5265 return status;
5266}
5267
5268/*
5269 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5270 * This function is used to initialize the security
5271 * settings in IBSS mode.
5272 */
5273static int wlan_hdd_cfg80211_set_privacy_ibss(
5274 hdd_adapter_t *pAdapter,
5275 struct cfg80211_ibss_params *params
5276 )
5277{
5278 int status = 0;
5279 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5280 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5281 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5282
5283 ENTER();
5284
5285 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5286
5287 if (params->ie_len && ( NULL != params->ie) )
5288 {
5289 if (WLAN_EID_RSN == params->ie[0])
5290 {
5291 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5292 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5293 }
5294 else
5295 {
5296 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5297 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5298 }
5299 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5300
5301 if (0 > status)
5302 {
5303 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5304 __func__);
5305 return status;
5306 }
5307 }
5308
5309 pWextState->roamProfile.AuthType.authType[0] =
5310 pHddStaCtx->conn_info.authType =
5311 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5312
5313 if (params->privacy)
5314 {
5315 /* Security enabled IBSS, At this time there is no information available
5316 * about the security paramters, so initialise the encryption type to
5317 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5318 * The correct security parameters will be updated later in
5319 * wlan_hdd_cfg80211_add_key */
5320 /* Hal expects encryption type to be set inorder
5321 *enable privacy bit in beacons */
5322
5323 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5324 }
5325
5326 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5327 pWextState->roamProfile.EncryptionType.numEntries = 1;
5328 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5329
5330 return status;
5331}
5332
5333/*
5334 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5335 * This function is used to create/join an IBSS
5336 */
5337static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5338 struct net_device *dev,
5339 struct cfg80211_ibss_params *params
5340 )
5341{
5342 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5343 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5344 tCsrRoamProfile *pRoamProfile;
5345 int status;
5346 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5347
5348 ENTER();
5349
5350 hddLog(VOS_TRACE_LEVEL_INFO,
5351 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5352
5353 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5354 {
5355 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5356 "%s:LOGP in Progress. Ignore!!!", __func__);
5357 return -EAGAIN;
5358 }
5359
5360 if (NULL == pWextState)
5361 {
5362 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5363 __func__);
5364 return -EIO;
5365 }
5366
5367 pRoamProfile = &pWextState->roamProfile;
5368
5369 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5370 {
5371 hddLog (VOS_TRACE_LEVEL_ERROR,
5372 "%s Interface type is not set to IBSS \n", __func__);
5373 return -EINVAL;
5374 }
5375
5376 /* Set Channel */
5377 if (NULL != params->channel)
5378 {
5379 u8 channelNum;
5380 if (IEEE80211_BAND_5GHZ == params->channel->band)
5381 {
5382 hddLog(VOS_TRACE_LEVEL_ERROR,
5383 "%s: IBSS join is called with unsupported band %d",
5384 __func__, params->channel->band);
5385 return -EOPNOTSUPP;
5386 }
5387
5388 /* Get channel number */
5389 channelNum =
5390 ieee80211_frequency_to_channel(params->channel->center_freq);
5391
5392 /*TODO: use macro*/
5393 if (14 >= channelNum)
5394 {
5395 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5396 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5397 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5398 int indx;
5399
5400 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5401 validChan, &numChans))
5402 {
5403 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5404 __func__);
5405 return -EOPNOTSUPP;
5406 }
5407
5408 for (indx = 0; indx < numChans; indx++)
5409 {
5410 if (channelNum == validChan[indx])
5411 {
5412 break;
5413 }
5414 }
5415 if (indx >= numChans)
5416 {
5417 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5418 __func__, channelNum);
5419 return -EINVAL;
5420 }
5421 /* Set the Operational Channel */
5422 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5423 channelNum);
5424 pRoamProfile->ChannelInfo.numOfChannels = 1;
5425 pHddStaCtx->conn_info.operationChannel = channelNum;
5426 pRoamProfile->ChannelInfo.ChannelList =
5427 &pHddStaCtx->conn_info.operationChannel;
5428 }
5429 else
5430 {
5431 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5432 __func__, channelNum);
5433 return -EINVAL;
5434 }
5435 }
5436
5437 /* Initialize security parameters */
5438 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5439 if (status < 0)
5440 {
5441 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5442 __func__);
5443 return status;
5444 }
5445
5446 /* Issue connect start */
5447 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005448 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005449
5450 if (0 > status)
5451 {
5452 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5453 return status;
5454 }
5455
5456 return 0;
5457}
5458
5459/*
5460 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5461 * This function is used to leave an IBSS
5462 */
5463static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5464 struct net_device *dev
5465 )
5466{
5467 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5468 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5469 tCsrRoamProfile *pRoamProfile;
5470
5471 ENTER();
5472
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005473 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5474 {
5475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5476 "%s:LOGP in Progress. Ignore!!!", __func__);
5477 return -EAGAIN;
5478 }
5479
Jeff Johnson295189b2012-06-20 16:38:30 -07005480 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5481 if (NULL == pWextState)
5482 {
5483 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5484 __func__);
5485 return -EIO;
5486 }
5487
5488 pRoamProfile = &pWextState->roamProfile;
5489
5490 /* Issue disconnect only if interface type is set to IBSS */
5491 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5492 {
5493 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5494 __func__);
5495 return -EINVAL;
5496 }
5497
5498 /* Issue Disconnect request */
5499 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5500 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5501 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5502
5503 return 0;
5504}
5505
5506/*
5507 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5508 * This function is used to set the phy parameters
5509 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5510 */
5511static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5512 u32 changed)
5513{
5514 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5515 tHalHandle hHal = pHddCtx->hHal;
5516
5517 ENTER();
5518
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005519 if ( pHddCtx->isLogpInProgress )
5520 {
5521 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5522 "%s:LOGP in Progress. Ignore!!!", __func__);
5523 return -EAGAIN;
5524 }
5525
Jeff Johnson295189b2012-06-20 16:38:30 -07005526 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5527 {
5528 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5529 WNI_CFG_RTS_THRESHOLD_STAMAX :
5530 wiphy->rts_threshold;
5531
5532 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5533 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5534 {
5535 hddLog(VOS_TRACE_LEVEL_ERROR,
5536 "%s: Invalid RTS Threshold value %hu",
5537 __func__, rts_threshold);
5538 return -EINVAL;
5539 }
5540
5541 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5542 rts_threshold, ccmCfgSetCallback,
5543 eANI_BOOLEAN_TRUE))
5544 {
5545 hddLog(VOS_TRACE_LEVEL_ERROR,
5546 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5547 __func__, rts_threshold);
5548 return -EIO;
5549 }
5550
5551 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5552 rts_threshold);
5553 }
5554
5555 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5556 {
5557 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5558 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5559 wiphy->frag_threshold;
5560
5561 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5562 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5563 {
5564 hddLog(VOS_TRACE_LEVEL_ERROR,
5565 "%s: Invalid frag_threshold value %hu", __func__,
5566 frag_threshold);
5567 return -EINVAL;
5568 }
5569
5570 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5571 frag_threshold, ccmCfgSetCallback,
5572 eANI_BOOLEAN_TRUE))
5573 {
5574 hddLog(VOS_TRACE_LEVEL_ERROR,
5575 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5576 __func__, frag_threshold);
5577 return -EIO;
5578 }
5579
5580 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5581 frag_threshold);
5582 }
5583
5584 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5585 || (changed & WIPHY_PARAM_RETRY_LONG))
5586 {
5587 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5588 wiphy->retry_short :
5589 wiphy->retry_long;
5590
5591 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5592 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5593 {
5594 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5595 __func__, retry_value);
5596 return -EINVAL;
5597 }
5598
5599 if (changed & WIPHY_PARAM_RETRY_SHORT)
5600 {
5601 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5602 retry_value, ccmCfgSetCallback,
5603 eANI_BOOLEAN_TRUE))
5604 {
5605 hddLog(VOS_TRACE_LEVEL_ERROR,
5606 "%s: ccmCfgSetInt failed for long retry count %hu",
5607 __func__, retry_value);
5608 return -EIO;
5609 }
5610 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5611 __func__, retry_value);
5612 }
5613 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5614 {
5615 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5616 retry_value, ccmCfgSetCallback,
5617 eANI_BOOLEAN_TRUE))
5618 {
5619 hddLog(VOS_TRACE_LEVEL_ERROR,
5620 "%s: ccmCfgSetInt failed for short retry count %hu",
5621 __func__, retry_value);
5622 return -EIO;
5623 }
5624 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5625 __func__, retry_value);
5626 }
5627 }
5628
5629 return 0;
5630}
5631
5632/*
5633 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5634 * This function is used to set the txpower
5635 */
5636static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5637#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5638 enum tx_power_setting type,
5639#else
5640 enum nl80211_tx_power_setting type,
5641#endif
5642 int dbm)
5643{
5644 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5645 tHalHandle hHal = pHddCtx->hHal;
5646 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5647 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5648
5649 ENTER();
5650
5651 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5652 dbm, ccmCfgSetCallback,
5653 eANI_BOOLEAN_TRUE))
5654 {
5655 hddLog(VOS_TRACE_LEVEL_ERROR,
5656 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5657 return -EIO;
5658 }
5659
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005660 if ( pHddCtx->isLogpInProgress )
5661 {
5662 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5663 "%s:LOGP in Progress. Ignore!!!", __func__);
5664 return -EAGAIN;
5665 }
5666
Jeff Johnson295189b2012-06-20 16:38:30 -07005667 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5668 dbm);
5669
5670 switch(type)
5671 {
5672 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5673 /* Fall through */
5674 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5675 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5676 {
5677 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5678 __func__);
5679 return -EIO;
5680 }
5681 break;
5682 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5683 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5684 __func__);
5685 return -EOPNOTSUPP;
5686 break;
5687 default:
5688 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5689 __func__, type);
5690 return -EIO;
5691 }
5692
5693 return 0;
5694}
5695
5696/*
5697 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5698 * This function is used to read the txpower
5699 */
5700static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5701{
5702
5703 hdd_adapter_t *pAdapter;
5704 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5705
Jeff Johnsone7245742012-09-05 17:12:55 -07005706 ENTER();
5707
Jeff Johnson295189b2012-06-20 16:38:30 -07005708 if (NULL == pHddCtx)
5709 {
5710 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5711 *dbm = 0;
5712 return -ENOENT;
5713 }
5714
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005715 if ( pHddCtx->isLogpInProgress )
5716 {
5717 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5718 "%s:LOGP in Progress. Ignore!!!", __func__);
5719 return -EAGAIN;
5720 }
5721
Jeff Johnson295189b2012-06-20 16:38:30 -07005722 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5723 if (NULL == pAdapter)
5724 {
5725 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5726 return -ENOENT;
5727 }
5728
5729 wlan_hdd_get_classAstats(pAdapter);
5730 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5731
Jeff Johnsone7245742012-09-05 17:12:55 -07005732 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005733 return 0;
5734}
5735
5736static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5737 u8* mac, struct station_info *sinfo)
5738{
5739 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5740 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5741 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5742 tANI_U8 rate_flags;
5743
5744 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5745 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5746 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5747
5748 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5749 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5750 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5751 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5752 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5753 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5754 tANI_U16 maxRate = 0;
5755 tANI_U16 myRate;
5756 tANI_U16 currentRate = 0;
5757 tANI_U8 maxSpeedMCS = 0;
5758 tANI_U8 maxMCSIdx = 0;
5759 tANI_U8 rateFlag = 1;
5760 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005761 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005762
Jeff Johnsone7245742012-09-05 17:12:55 -07005763 ENTER();
5764
Jeff Johnson295189b2012-06-20 16:38:30 -07005765 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5766 (0 == ssidlen))
5767 {
5768 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5769 " Invalid ssidlen, %d", __func__, ssidlen);
5770 /*To keep GUI happy*/
5771 return 0;
5772 }
5773
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005774 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5775 {
5776 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5777 "%s:LOGP in Progress. Ignore!!!", __func__);
5778 return -EAGAIN;
5779 }
5780
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5782 sinfo->filled |= STATION_INFO_SIGNAL;
5783
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005784 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005785 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5786
5787 //convert to the UI units of 100kbps
5788 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5789
5790#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005791 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 -07005792 sinfo->signal,
5793 pCfg->reportMaxLinkSpeed,
5794 myRate,
5795 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005796 (int) pCfg->linkSpeedRssiMid,
5797 (int) pCfg->linkSpeedRssiLow,
5798 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005799#endif //LINKSPEED_DEBUG_ENABLED
5800
5801 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5802 {
5803 // we do not want to necessarily report the current speed
5804 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5805 {
5806 // report the max possible speed
5807 rssidx = 0;
5808 }
5809 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5810 {
5811 // report the max possible speed with RSSI scaling
5812 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5813 {
5814 // report the max possible speed
5815 rssidx = 0;
5816 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005817 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005818 {
5819 // report middle speed
5820 rssidx = 1;
5821 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005822 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5823 {
5824 // report middle speed
5825 rssidx = 2;
5826 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 else
5828 {
5829 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005830 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 }
5832 }
5833 else
5834 {
5835 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5836 hddLog(VOS_TRACE_LEVEL_ERROR,
5837 "%s: Invalid value for reportMaxLinkSpeed: %u",
5838 __func__, pCfg->reportMaxLinkSpeed);
5839 rssidx = 0;
5840 }
5841
5842 maxRate = 0;
5843
5844 /* Get Basic Rate Set */
5845 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5846 for (i = 0; i < ORLeng; i++)
5847 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005848 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005849 {
5850 /* Validate Rate Set */
5851 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5852 {
5853 currentRate = supported_data_rate[j].supported_rate[rssidx];
5854 break;
5855 }
5856 }
5857 /* Update MAX rate */
5858 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5859 }
5860
5861 /* Get Extended Rate Set */
5862 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5863 for (i = 0; i < ERLeng; i++)
5864 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005865 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005866 {
5867 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5868 {
5869 currentRate = supported_data_rate[j].supported_rate[rssidx];
5870 break;
5871 }
5872 }
5873 /* Update MAX rate */
5874 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5875 }
5876
5877 /* Get MCS Rate Set -- but only if we are connected at MCS
5878 rates or if we are always reporting max speed or if we have
5879 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005880 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 {
5882 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5883 rateFlag = 0;
5884 if (rate_flags & eHAL_TX_RATE_HT40)
5885 {
5886 rateFlag |= 1;
5887 }
5888 if (rate_flags & eHAL_TX_RATE_SGI)
5889 {
5890 rateFlag |= 2;
5891 }
5892
5893 for (i = 0; i < MCSLeng; i++)
5894 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005895 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5896 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 {
5898 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5899 {
5900 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5901 break;
5902 }
5903 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005904 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 {
5906 maxRate = currentRate;
5907 maxSpeedMCS = 1;
5908 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5909 }
5910 }
5911 }
5912
5913 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005914 if (((maxRate < myRate) && (0 == rssidx)) ||
5915 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005916 {
5917 maxRate = myRate;
5918 if (rate_flags & eHAL_TX_RATE_LEGACY)
5919 {
5920 maxSpeedMCS = 0;
5921 }
5922 else
5923 {
5924 maxSpeedMCS = 1;
5925 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5926 }
5927 }
5928
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005929 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005930 {
5931 sinfo->txrate.legacy = maxRate;
5932#ifdef LINKSPEED_DEBUG_ENABLED
5933 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5934#endif //LINKSPEED_DEBUG_ENABLED
5935 }
5936 else
5937 {
5938 sinfo->txrate.mcs = maxMCSIdx;
5939 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5940 if (rate_flags & eHAL_TX_RATE_SGI)
5941 {
5942 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5943 }
5944 if (rate_flags & eHAL_TX_RATE_HT40)
5945 {
5946 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5947 }
5948#ifdef LINKSPEED_DEBUG_ENABLED
5949 pr_info("Reporting MCS rate %d flags %x\n",
5950 sinfo->txrate.mcs,
5951 sinfo->txrate.flags );
5952#endif //LINKSPEED_DEBUG_ENABLED
5953 }
5954 }
5955 else
5956 {
5957 // report current rate instead of max rate
5958
5959 if (rate_flags & eHAL_TX_RATE_LEGACY)
5960 {
5961 //provide to the UI in units of 100kbps
5962 sinfo->txrate.legacy = myRate;
5963#ifdef LINKSPEED_DEBUG_ENABLED
5964 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5965#endif //LINKSPEED_DEBUG_ENABLED
5966 }
5967 else
5968 {
5969 //must be MCS
5970 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5971 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5972 if (rate_flags & eHAL_TX_RATE_SGI)
5973 {
5974 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5975 }
5976 if (rate_flags & eHAL_TX_RATE_HT40)
5977 {
5978 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5979 }
5980#ifdef LINKSPEED_DEBUG_ENABLED
5981 pr_info("Reporting actual MCS rate %d flags %x\n",
5982 sinfo->txrate.mcs,
5983 sinfo->txrate.flags );
5984#endif //LINKSPEED_DEBUG_ENABLED
5985 }
5986 }
5987 sinfo->filled |= STATION_INFO_TX_BITRATE;
5988
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005989 sinfo->tx_packets =
5990 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5991 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5992 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5993 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5994
5995 sinfo->tx_retries =
5996 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
5997 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
5998 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
5999 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6000
6001 sinfo->tx_failed =
6002 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6003 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6004 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6005 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6006
6007 sinfo->filled |=
6008 STATION_INFO_TX_PACKETS |
6009 STATION_INFO_TX_RETRIES |
6010 STATION_INFO_TX_FAILED;
6011
6012 EXIT();
6013 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006014}
6015
6016static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6017 struct net_device *dev, bool mode, v_SINT_t timeout)
6018{
6019 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6020 VOS_STATUS vos_status;
6021
Jeff Johnsone7245742012-09-05 17:12:55 -07006022 ENTER();
6023
Jeff Johnson295189b2012-06-20 16:38:30 -07006024 if (NULL == pAdapter)
6025 {
6026 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6027 return -ENODEV;
6028 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006029 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6030 {
6031 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6032 "%s:LOGP in Progress. Ignore!!!", __func__);
6033 return -EAGAIN;
6034 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006035
6036 /**The get power cmd from the supplicant gets updated by the nl only
6037 *on successful execution of the function call
6038 *we are oppositely mapped w.r.t mode in the driver
6039 **/
6040 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6041
Jeff Johnsone7245742012-09-05 17:12:55 -07006042 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 if (VOS_STATUS_E_FAILURE == vos_status)
6044 {
6045 return -EINVAL;
6046 }
6047 return 0;
6048}
6049
6050
6051#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6052static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6053 struct net_device *netdev,
6054 u8 key_index)
6055{
Jeff Johnsone7245742012-09-05 17:12:55 -07006056 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006057 return 0;
6058}
6059#endif //LINUX_VERSION_CODE
6060
6061#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6062static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6063 struct net_device *dev,
6064 struct ieee80211_txq_params *params)
6065{
Jeff Johnsone7245742012-09-05 17:12:55 -07006066 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006067 return 0;
6068}
6069#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6070static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6071 struct ieee80211_txq_params *params)
6072{
Jeff Johnsone7245742012-09-05 17:12:55 -07006073 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006074 return 0;
6075}
6076#endif //LINUX_VERSION_CODE
6077
6078static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6079 struct net_device *dev, u8 *mac)
6080{
6081 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6082
Jeff Johnsone7245742012-09-05 17:12:55 -07006083 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006084 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6085 {
6086 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6087 return -EINVAL;
6088 }
6089
6090 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6091 {
6092 hddLog( LOGE,
6093 "%s: Wlan Load/Unload is in progress", __func__);
6094 return -EBUSY;
6095 }
6096
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006097 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6098 {
6099 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6100 "%s:LOGP in Progress. Ignore!!!", __func__);
6101 return -EAGAIN;
6102 }
6103
Jeff Johnson295189b2012-06-20 16:38:30 -07006104 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6105#ifdef WLAN_FEATURE_P2P
6106 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6107#endif
6108 )
6109 {
6110 if( NULL == mac )
6111 {
6112 v_U16_t i;
6113 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6114 {
6115 if(pAdapter->aStaInfo[i].isUsed)
6116 {
6117 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6118 hddLog(VOS_TRACE_LEVEL_INFO,
6119 "%s: Delete STA with MAC::"
6120 "%02x:%02x:%02x:%02x:%02x:%02x",
6121 __func__,
6122 macAddr[0], macAddr[1], macAddr[2],
6123 macAddr[3], macAddr[4], macAddr[5]);
6124 hdd_softap_sta_deauth(pAdapter, macAddr);
6125 }
6126 }
6127 }
6128 else
6129 {
6130 hddLog(VOS_TRACE_LEVEL_INFO,
6131 "%s: Delete STA with MAC::"
6132 "%02x:%02x:%02x:%02x:%02x:%02x",
6133 __func__,
6134 mac[0], mac[1], mac[2],
6135 mac[3], mac[4], mac[5]);
6136 hdd_softap_sta_deauth(pAdapter, mac);
6137 }
6138 }
6139
6140 EXIT();
6141
6142 return 0;
6143}
6144
6145static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6146 struct net_device *dev, u8 *mac, struct station_parameters *params)
6147{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006148#ifdef FEATURE_WLAN_TDLS
6149 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6150 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6151 u32 mask, set;
6152 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006153 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006154
6155 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6156 {
6157 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6158 "Invalid arguments");
6159 return -EINVAL;
6160 }
6161
6162 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6163 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6164 {
6165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6166 "TDLS Disabled in INI OR not enabled in FW.\
6167 Cannot process TDLS commands \n");
6168 return -ENOTSUPP;
6169 }
6170
6171 mask = params->sta_flags_mask;
6172
6173 set = params->sta_flags_set;
6174
6175
6176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6177 "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
6178
6179 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6180 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6182 "Add TDLS peer");
6183
6184
6185 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6186 pAdapter->sessionId, mac);
6187
6188 if (VOS_STATUS_SUCCESS != status) {
6189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6190 "%s: sme_AddTdlsPeerSta failed!", __func__);
6191 }
6192 }
6193 }
6194#endif
6195
Jeff Johnson295189b2012-06-20 16:38:30 -07006196 return 0;
6197}
6198
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006199
6200#ifdef FEATURE_WLAN_LFR
6201static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006202 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006203{
6204#define MAX_PMKSAIDS_IN_CACHE 8
6205 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006206 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006207 tANI_U32 j=0;
6208 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6209 tHalHandle halHandle;
6210 eHalStatus result;
6211 tANI_U8 BSSIDMatched = 0;
6212
Jeff Johnsone7245742012-09-05 17:12:55 -07006213 ENTER();
6214
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006215 // Validate pAdapter
6216 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6217 {
6218 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6219 return -EINVAL;
6220 }
6221
6222 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6223 {
6224 hddLog( LOGE,
6225 "%s: Wlan Load/Unload is in progress", __func__);
6226 return -EBUSY;
6227 }
6228
6229 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6230 {
6231 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6232 "%s:LOGP in Progress. Ignore!!!", __func__);
6233 return -EAGAIN;
6234 }
6235
6236 // Retrieve halHandle
6237 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6238
6239 for (j = 0; j < i; j++)
6240 {
6241 if(vos_mem_compare(PMKIDCache[j].BSSID,
6242 pmksa->bssid, WNI_CFG_BSSID_LEN))
6243 {
6244 /* BSSID matched previous entry. Overwrite it. */
6245 BSSIDMatched = 1;
6246 vos_mem_copy(PMKIDCache[j].BSSID,
6247 pmksa->bssid, WNI_CFG_BSSID_LEN);
6248 vos_mem_copy(PMKIDCache[j].PMKID,
6249 pmksa->pmkid,
6250 CSR_RSN_PMKID_SIZE);
6251 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006252 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006253 dump_bssid(pmksa->bssid);
6254 dump_pmkid(halHandle, pmksa->pmkid);
6255 break;
6256 }
6257 }
6258
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006259 /* Check we compared all entries,if then take the first slot now */
6260 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6261
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006262 if (!BSSIDMatched)
6263 {
6264 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6265 vos_mem_copy(PMKIDCache[i].BSSID,
6266 pmksa->bssid, ETHER_ADDR_LEN);
6267 vos_mem_copy(PMKIDCache[i].PMKID,
6268 pmksa->pmkid,
6269 CSR_RSN_PMKID_SIZE);
6270 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006271 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006272 dump_bssid(pmksa->bssid);
6273 dump_pmkid(halHandle, pmksa->pmkid);
6274 // Increment the HDD Local Cache index
6275 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6276 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6277 }
6278
6279
6280 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6281 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006282 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006283 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006284 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006285 // Finally set the PMKSA ID Cache in CSR
6286 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6287 PMKIDCache,
6288 i );
6289 return 0;
6290}
6291
6292
6293static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006294 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006295{
Jeff Johnsone7245742012-09-05 17:12:55 -07006296 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006297 // TODO: Implement this later.
6298 return 0;
6299}
6300
6301static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6302{
Jeff Johnsone7245742012-09-05 17:12:55 -07006303 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006304 // TODO: Implement this later.
6305 return 0;
6306}
6307#endif
6308
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006309#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6310static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6311 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6312{
6313 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6314 hdd_station_ctx_t *pHddStaCtx;
6315
6316 if (NULL == pAdapter)
6317 {
6318 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6319 return -ENODEV;
6320 }
6321
6322 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6323
6324 // Added for debug on reception of Re-assoc Req.
6325 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6326 {
6327 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6328 ftie->ie_len);
6329 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6330 }
6331
6332#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6333 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6334 ftie->ie_len);
6335#endif
6336
6337 // Pass the received FT IEs to SME
6338 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6339 ftie->ie_len);
6340 return 0;
6341}
6342#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006343
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006344#ifdef FEATURE_WLAN_TDLS
6345static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6346 u8 *peer, u8 action_code, u8 dialog_token,
6347 u16 status_code, const u8 *buf, size_t len)
6348{
6349
6350 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6351 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6352 u8 *buf_1;
6353 size_t len_1 = len;
6354 u8 peerMac[6];
6355 VOS_STATUS status;
6356
6357 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6358 {
6359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6360 "Invalid arguments");
6361 return -EINVAL;
6362 }
6363
6364 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6365 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6366 {
6367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6368 "TDLS Disabled in INI OR not enabled in FW.\
6369 Cannot process TDLS commands \n");
6370 return -ENOTSUPP;
6371 }
6372 vos_mem_copy( peerMac, peer, 6);
6373
6374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6375 "Request to send TDLS management: action = %d, status = %d, \
Ng Chilamfc416462012-12-27 17:26:52 -08006376 len = %d", action_code, status_code, len);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006377
6378 buf_1 = vos_mem_malloc(len);
6379 if(buf_1 == NULL) {
6380 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6381 "%s: malloc failed!", __func__);
6382 return -ENOMEM;
6383 }
6384 vos_mem_copy(buf_1, buf, len);
6385
6386 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6387 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6388
6389 if (VOS_STATUS_SUCCESS != status) {
6390 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6391 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6392 }
6393
6394 vos_mem_free(buf_1);
6395
6396 return 0;
6397}
6398
6399static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6400 u8 *peer, enum nl80211_tdls_operation oper)
6401{
6402 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6403 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6404
6405 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6406 {
6407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6408 "Invalid arguments");
6409 return -EINVAL;
6410 }
6411
6412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6413 "Request for TDLS oper: %d", (int)oper);
6414
6415 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6416 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6417 {
6418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6419 "TDLS Disabled in INI OR not enabled in FW.\
6420 Cannot process TDLS commands \n");
6421 return -ENOTSUPP;
6422 }
6423
6424 switch (oper) {
6425 case NL80211_TDLS_ENABLE_LINK:
6426 {
6427 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6428 v_U8_t my_peer[6];
6429 v_U8_t ucSTAId;
6430 VOS_STATUS status;
6431
6432 if (peer) {
6433 vos_mem_copy(my_peer, peer, 6);
6434 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6435
6436 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6437 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6438 __func__, peer[0], peer[1],
6439 peer[2], peer[3],
6440 peer[4], peer[5] );
6441
6442 if (-1 == ucSTAId ) {
6443 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
6444 return 0;
6445 }
6446
6447 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6448 WLANTL_STA_AUTHENTICATED );
6449
6450 if (0 != status) {
6451 hddLog(VOS_TRACE_LEVEL_ERROR,
6452 "%s: WLANTL_ChangeSTAState failed, returned %d",
6453 __func__, status);
6454 return status;
6455 }
6456 } else {
6457 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6458 }
6459 }
6460 break;
6461 case NL80211_TDLS_DISABLE_LINK:
6462 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6463 pAdapter->sessionId, peer );
6464 return 0;
6465 case NL80211_TDLS_TEARDOWN:
6466 case NL80211_TDLS_SETUP:
6467 case NL80211_TDLS_DISCOVERY_REQ:
6468 /* We don't support in-driver setup/teardown/discovery */
6469 return -ENOTSUPP;
6470 default:
6471 return -ENOTSUPP;
6472 }
6473 return 0;
6474}
6475#endif
6476
Jeff Johnson295189b2012-06-20 16:38:30 -07006477/* cfg80211_ops */
6478static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6479{
6480 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6481 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6482 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6483 .change_station = wlan_hdd_change_station,
6484#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6485 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6486 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6487 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006488#else
6489 .start_ap = wlan_hdd_cfg80211_start_ap,
6490 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6491 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006492#endif
6493 .change_bss = wlan_hdd_cfg80211_change_bss,
6494 .add_key = wlan_hdd_cfg80211_add_key,
6495 .get_key = wlan_hdd_cfg80211_get_key,
6496 .del_key = wlan_hdd_cfg80211_del_key,
6497 .set_default_key = wlan_hdd_cfg80211_set_default_key,
6498 .set_channel = wlan_hdd_cfg80211_set_channel,
6499 .scan = wlan_hdd_cfg80211_scan,
6500 .connect = wlan_hdd_cfg80211_connect,
6501 .disconnect = wlan_hdd_cfg80211_disconnect,
6502 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6503 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6504 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6505 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6506 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6507#ifdef WLAN_FEATURE_P2P
6508 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6509 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6510 .mgmt_tx = wlan_hdd_action,
6511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6512 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6513 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6514 .set_txq_params = wlan_hdd_set_txq_params,
6515#endif
6516#endif
6517 .get_station = wlan_hdd_cfg80211_get_station,
6518 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6519 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006520 .add_station = wlan_hdd_cfg80211_add_station,
6521#ifdef FEATURE_WLAN_LFR
6522 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6523 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6524 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6525#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006526#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6527 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6528#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006529#ifdef FEATURE_WLAN_TDLS
6530 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6531 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6532#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006533};
6534
6535#endif // CONFIG_CFG80211