blob: 913242b82c158e1634b693c954ddbfd07fdc2e03 [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
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001644 /* Overwrite the hostapd setting for HW mode only for 11ac.
1645 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1646 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1647 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1648 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1649 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1650 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1651 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001652 {
1653 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1654 }
1655#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301656
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001657 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1658 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001659 // ht_capab is not what the name conveys,this is used for protection bitmap
1660 pConfig->ht_capab =
1661 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1662
1663 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1664 {
1665 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1666 return -EINVAL;
1667 }
1668
1669 //Uapsd Enabled Bit
1670 pConfig->UapsdEnable =
1671 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1672 //Enable OBSS protection
1673 pConfig->obssProtEnabled =
1674 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1675
1676 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1677 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1678 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1679 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1680 (int)pConfig->channel);
1681 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1682 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1683 pConfig->authType);
1684 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1685 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1686 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1687 pConfig->protEnabled, pConfig->obssProtEnabled);
1688
1689 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1690 {
1691 //Bss already started. just return.
1692 //TODO Probably it should update some beacon params.
1693 hddLog( LOGE, "Bss Already started...Ignore the request");
1694 EXIT();
1695 return 0;
1696 }
1697
1698 pConfig->persona = pHostapdAdapter->device_mode;
1699
1700 pSapEventCallback = hdd_hostapd_SAPEventCB;
1701 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1702 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1703 {
1704 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1705 return -EINVAL;
1706 }
1707
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001708 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001709 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1710
1711 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1712
1713 if (!VOS_IS_STATUS_SUCCESS(status))
1714 {
1715 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1716 ("ERROR: HDD vos wait for single_event failed!!\n"));
1717 VOS_ASSERT(0);
1718 }
1719
1720 //Succesfully started Bss update the state bit.
1721 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1722
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001723#ifdef WLAN_FEATURE_P2P_DEBUG
1724 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1725 {
1726 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1727 {
1728 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1729 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001730 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001731 }
1732 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1733 {
1734 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1735 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001736 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001737 }
1738 }
1739#endif
1740
Jeff Johnson295189b2012-06-20 16:38:30 -07001741 pHostapdState->bCommit = TRUE;
1742 EXIT();
1743
1744 return 0;
1745}
1746
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001747#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001748static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1749 struct net_device *dev,
1750 struct beacon_parameters *params)
1751{
1752 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1753 int status=VOS_STATUS_SUCCESS;
1754
1755 ENTER();
1756
1757 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1758
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001759 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1760 {
1761 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1762 "%s:LOGP in Progress. Ignore!!!", __func__);
1763 return -EAGAIN;
1764 }
1765
Jeff Johnson295189b2012-06-20 16:38:30 -07001766 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1767#ifdef WLAN_FEATURE_P2P
1768 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1769#endif
1770 )
1771 {
1772 beacon_data_t *old,*new;
1773
1774 old = pAdapter->sessionCtx.ap.beacon;
1775
1776 if (old)
1777 return -EALREADY;
1778
1779 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1780
1781 if(status != VOS_STATUS_SUCCESS)
1782 {
1783 hddLog(VOS_TRACE_LEVEL_FATAL,
1784 "%s:Error!!! Allocating the new beacon\n",__func__);
1785 return -EINVAL;
1786 }
1787
1788 pAdapter->sessionCtx.ap.beacon = new;
1789
1790 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1791 }
1792
1793 EXIT();
1794 return status;
1795}
1796
1797static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1798 struct net_device *dev,
1799 struct beacon_parameters *params)
1800{
1801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1802 int status=VOS_STATUS_SUCCESS;
1803
1804 ENTER();
1805
1806 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1807 __func__,pAdapter->device_mode);
1808
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001809 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1810 {
1811 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1812 "%s:LOGP in Progress. Ignore!!!", __func__);
1813 return -EAGAIN;
1814 }
1815
Jeff Johnson295189b2012-06-20 16:38:30 -07001816 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1817#ifdef WLAN_FEATURE_P2P
1818 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1819#endif
1820 )
1821 {
1822 beacon_data_t *old,*new;
1823
1824 old = pAdapter->sessionCtx.ap.beacon;
1825
1826 if (!old)
1827 return -ENOENT;
1828
1829 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1830
1831 if(status != VOS_STATUS_SUCCESS) {
1832 hddLog(VOS_TRACE_LEVEL_FATAL,
1833 "%s: Error!!! Allocating the new beacon\n",__func__);
1834 return -EINVAL;
1835 }
1836
1837 pAdapter->sessionCtx.ap.beacon = new;
1838
1839 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1840 }
1841
1842 EXIT();
1843 return status;
1844}
1845
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001846#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1847
1848#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001849static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1850 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001851#else
1852static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1853 struct net_device *dev)
1854#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001855{
1856 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001857 hdd_context_t *pHddCtx = NULL;
1858 hdd_scaninfo_t *pScanInfo = NULL;
1859 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001860 VOS_STATUS status = 0;
1861
1862 ENTER();
1863
1864 if (NULL == pAdapter)
1865 {
1866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001867 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001868 return -ENODEV;
1869 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001870 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1871 {
1872 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1873 "%s:LOGP in Progress. Ignore!!!", __func__);
1874 return -EAGAIN;
1875 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001876
1877 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1878 if (NULL == pHddCtx)
1879 {
1880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001881 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001882 return -ENODEV;
1883 }
1884
1885 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1886 if (NULL == staAdapter)
1887 {
1888 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1889 if (NULL == staAdapter)
1890 {
1891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001892 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001893 return -ENODEV;
1894 }
1895 }
1896
1897 pScanInfo = &pHddCtx->scan_info;
1898
Jeff Johnson295189b2012-06-20 16:38:30 -07001899 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1900 {
1901 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1902 return -EAGAIN;
1903 }
1904
1905 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1906
1907 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1908 __func__,pAdapter->device_mode);
1909
Jeff Johnsone7245742012-09-05 17:12:55 -07001910 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1911 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001912 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001913 hdd_abort_mac_scan(staAdapter->pHddCtx);
1914 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001915 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07001916 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1917 if (!status)
1918 {
1919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08001920 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001921 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001922 VOS_ASSERT(pScanInfo->mScanPending);
1923 return 0;
1924 }
1925 }
1926
Jeff Johnson295189b2012-06-20 16:38:30 -07001927 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1928#ifdef WLAN_FEATURE_P2P
1929 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1930#endif
1931 )
1932 {
1933 beacon_data_t *old;
1934
1935 old = pAdapter->sessionCtx.ap.beacon;
1936
1937 if (!old)
1938 return -ENOENT;
1939
1940#ifdef CONFIG_CFG80211
1941 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1942#endif
1943
1944 mutex_lock(&pHddCtx->sap_lock);
1945 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1946 {
1947 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
1948 {
1949 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
1950
1951 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1952
1953 if (!VOS_IS_STATUS_SUCCESS(status))
1954 {
1955 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1956 ("ERROR: HDD vos wait for single_event failed!!\n"));
1957 VOS_ASSERT(0);
1958 }
1959 }
1960 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
1961 }
1962 mutex_unlock(&pHddCtx->sap_lock);
1963
1964 if(status != VOS_STATUS_SUCCESS)
1965 {
1966 hddLog(VOS_TRACE_LEVEL_FATAL,
1967 "%s:Error!!! Stopping the BSS\n",__func__);
1968 return -EINVAL;
1969 }
1970
1971 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1972 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
1973 ==eHAL_STATUS_FAILURE)
1974 {
1975 hddLog(LOGE,
1976 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
1977 }
1978
1979 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1980 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1981 eANI_BOOLEAN_FALSE) )
1982 {
1983 hddLog(LOGE,
1984 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1985 }
1986
1987 // Reset WNI_CFG_PROBE_RSP Flags
1988 wlan_hdd_reset_prob_rspies(pAdapter);
1989
1990 pAdapter->sessionCtx.ap.beacon = NULL;
1991 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001992#ifdef WLAN_FEATURE_P2P_DEBUG
1993 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
1994 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
1995 {
1996 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
1997 "GO got removed");
1998 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
1999 }
2000#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002001 }
2002 EXIT();
2003 return status;
2004}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002005
2006#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2007
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302008static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2009 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002010 struct cfg80211_ap_settings *params)
2011{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302012 hdd_adapter_t *pAdapter;
2013 hdd_context_t *pHddCtx;
2014 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002015
2016 ENTER();
2017
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302018 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002019 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2021 "%s: Device is Null", __func__);
2022 return -ENODEV;
2023 }
2024
2025 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2026 if (NULL == pAdapter)
2027 {
2028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2029 "%s: HDD adapter is Null", __func__);
2030 return -ENODEV;
2031 }
2032
2033 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2034 {
2035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2036 "%s: HDD adapter magic is invalid", __func__);
2037 return -ENODEV;
2038 }
2039
2040 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2041 if (NULL == pHddCtx)
2042 {
2043 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2044 "%s: HDD context is Null", __func__);
2045 return -ENODEV;
2046 }
2047
2048 if (pHddCtx->isLogpInProgress)
2049 {
2050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2051 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002052 return -EAGAIN;
2053 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302054
2055 if (pHddCtx->isLoadUnloadInProgress)
2056 {
2057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2058 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2059 return -EAGAIN;
2060 }
2061
2062 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2063 __func__, pAdapter->device_mode);
2064
2065 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002066#ifdef WLAN_FEATURE_P2P
2067 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2068#endif
2069 )
2070 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302071 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002072
2073 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302074
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002075 if (old)
2076 return -EALREADY;
2077
2078 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2079
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302080 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002081 {
2082 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302083 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002084 return -EINVAL;
2085 }
2086 pAdapter->sessionCtx.ap.beacon = new;
2087 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2088 params->ssid_len, params->hidden_ssid);
2089 }
2090
2091 EXIT();
2092 return status;
2093}
2094
2095
2096static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2097 struct net_device *dev,
2098 struct cfg80211_beacon_data *params)
2099{
2100 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2101 int status=VOS_STATUS_SUCCESS;
2102
2103 ENTER();
2104
2105 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2106 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002107 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2108 {
2109 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2110 return -EAGAIN;
2111 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002112
2113 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2114#ifdef WLAN_FEATURE_P2P
2115 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2116#endif
2117 )
2118 {
2119 beacon_data_t *old,*new;
2120
2121 old = pAdapter->sessionCtx.ap.beacon;
2122
2123 if (!old)
2124 return -ENOENT;
2125
2126 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2127
2128 if(status != VOS_STATUS_SUCCESS) {
2129 hddLog(VOS_TRACE_LEVEL_FATAL,
2130 "%s: Error!!! Allocating the new beacon\n",__func__);
2131 return -EINVAL;
2132 }
2133
2134 pAdapter->sessionCtx.ap.beacon = new;
2135
2136 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2137 }
2138
2139 EXIT();
2140 return status;
2141}
2142
2143#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2144
Jeff Johnson295189b2012-06-20 16:38:30 -07002145
2146static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2147 struct net_device *dev,
2148 struct bss_parameters *params)
2149{
2150 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2151
2152 ENTER();
2153
2154 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2155 __func__,pAdapter->device_mode);
2156
2157 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2158#ifdef WLAN_FEATURE_P2P
2159 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2160#endif
2161 )
2162 {
2163 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2164 * want to update this parameter */
2165 if (-1 != params->ap_isolate)
2166 {
2167 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2168 }
2169 }
2170
2171 EXIT();
2172 return 0;
2173}
2174
2175/*
2176 * FUNCTION: wlan_hdd_cfg80211_change_iface
2177 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2178 */
2179int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2180 struct net_device *ndev,
2181 enum nl80211_iftype type,
2182 u32 *flags,
2183 struct vif_params *params
2184 )
2185{
2186 struct wireless_dev *wdev;
2187 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2188 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002189 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002190 tCsrRoamProfile *pRoamProfile = NULL;
2191 eCsrRoamBssType LastBSSType;
2192 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2193 eMib_dot11DesiredBssType connectedBssType;
2194 VOS_STATUS status;
2195
2196 ENTER();
2197
2198 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2199 {
2200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2201 return -EAGAIN;
2202 }
2203
2204 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2205 __func__, pAdapter->device_mode);
2206
2207 wdev = ndev->ieee80211_ptr;
2208
2209#ifdef WLAN_BTAMP_FEATURE
2210 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2211 (NL80211_IFTYPE_ADHOC == type)||
2212 (NL80211_IFTYPE_AP == type)||
2213 (NL80211_IFTYPE_P2P_GO == type))
2214 {
2215 pHddCtx->isAmpAllowed = VOS_FALSE;
2216 // stop AMP traffic
2217 status = WLANBAP_StopAmp();
2218 if(VOS_STATUS_SUCCESS != status )
2219 {
2220 pHddCtx->isAmpAllowed = VOS_TRUE;
2221 hddLog(VOS_TRACE_LEVEL_FATAL,
2222 "%s: Failed to stop AMP", __func__);
2223 return -EINVAL;
2224 }
2225 }
2226#endif //WLAN_BTAMP_FEATURE
2227 /* Reset the current device mode bit mask*/
2228 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2229
2230 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2231#ifdef WLAN_FEATURE_P2P
2232 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002233 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002234#endif
2235 )
2236 {
2237 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2238 pRoamProfile = &pWextState->roamProfile;
2239 LastBSSType = pRoamProfile->BSSType;
2240
2241 switch (type)
2242 {
2243 case NL80211_IFTYPE_STATION:
2244#ifdef WLAN_FEATURE_P2P
2245 case NL80211_IFTYPE_P2P_CLIENT:
2246#endif
2247 hddLog(VOS_TRACE_LEVEL_INFO,
2248 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2249 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002250#ifdef WLAN_FEATURE_11AC
2251 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2252 {
2253 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2254 }
2255#endif
2256 pRoamProfile->phyMode =
2257 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002258 wdev->iftype = type;
2259#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002260 //Check for sub-string p2p to confirm its a p2p interface
2261 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002262 {
2263 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2264 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2265 }
2266 else
2267 {
2268 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002269 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002270 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002271#endif
2272 break;
2273 case NL80211_IFTYPE_ADHOC:
2274 hddLog(VOS_TRACE_LEVEL_INFO,
2275 "%s: setting interface Type to ADHOC", __func__);
2276 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2277 pRoamProfile->phyMode =
2278 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2279 wdev->iftype = type;
2280 break;
2281
2282 case NL80211_IFTYPE_AP:
2283#ifdef WLAN_FEATURE_P2P
2284 case NL80211_IFTYPE_P2P_GO:
2285#endif
2286 {
2287 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2288 "%s: setting interface Type to %s", __func__,
2289 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2290
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002291 //Cancel any remain on channel for GO mode
2292 if (NL80211_IFTYPE_P2P_GO == type)
2293 {
2294 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2295 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002296 if (NL80211_IFTYPE_AP == type)
2297 {
2298 /* As Loading WLAN Driver one interface being created for p2p device
2299 * address. This will take one HW STA and the max number of clients
2300 * that can connect to softAP will be reduced by one. so while changing
2301 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2302 * interface as it is not required in SoftAP mode.
2303 */
2304
2305 // Get P2P Adapter
2306 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2307
2308 if (pP2pAdapter)
2309 {
2310 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2311 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2312 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2313 }
2314 }
2315
Jeff Johnson295189b2012-06-20 16:38:30 -07002316 //De-init the adapter.
2317 hdd_stop_adapter( pHddCtx, pAdapter );
2318 hdd_deinit_adapter( pHddCtx, pAdapter );
2319 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2320#ifdef WLAN_SOFTAP_FEATURE
2321#ifdef WLAN_FEATURE_P2P
2322 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2323 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2324#else
2325 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2326#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002327
2328 //Disable BMPS and IMPS if enabled
2329 //before starting Go
2330 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2331 {
2332 if(VOS_STATUS_E_FAILURE ==
2333 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2334 {
2335 //Fail to Exit BMPS
2336 VOS_ASSERT(0);
2337 }
2338 }
2339
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002340 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2341 (pConfig->apRandomBssidEnabled))
2342 {
2343 /* To meet Android requirements create a randomized
2344 MAC address of the form 02:1A:11:Fx:xx:xx */
2345 get_random_bytes(&ndev->dev_addr[3], 3);
2346 ndev->dev_addr[0] = 0x02;
2347 ndev->dev_addr[1] = 0x1A;
2348 ndev->dev_addr[2] = 0x11;
2349 ndev->dev_addr[3] |= 0xF0;
2350 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2351 VOS_MAC_ADDR_SIZE);
2352 pr_info("wlan: Generated HotSpot BSSID "
2353 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2354 ndev->dev_addr[0],
2355 ndev->dev_addr[1],
2356 ndev->dev_addr[2],
2357 ndev->dev_addr[3],
2358 ndev->dev_addr[4],
2359 ndev->dev_addr[5]);
2360 }
2361
Jeff Johnson295189b2012-06-20 16:38:30 -07002362 hdd_set_ap_ops( pAdapter->dev );
2363
2364 status = hdd_init_ap_mode(pAdapter);
2365 if(status != VOS_STATUS_SUCCESS)
2366 {
2367 hddLog(VOS_TRACE_LEVEL_FATAL,
2368 "%s: Error initializing the ap mode", __func__);
2369 return -EINVAL;
2370 }
2371 hdd_set_conparam(1);
2372
2373#endif
2374 /*interface type changed update in wiphy structure*/
2375 if(wdev)
2376 {
2377 wdev->iftype = type;
2378 pHddCtx->change_iface = type;
2379 }
2380 else
2381 {
2382 hddLog(VOS_TRACE_LEVEL_ERROR,
2383 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2384 return -EINVAL;
2385 }
2386 goto done;
2387 }
2388
2389 default:
2390 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2391 __func__);
2392 return -EOPNOTSUPP;
2393 }
2394 }
2395 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2396#ifdef WLAN_FEATURE_P2P
2397 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2398#endif
2399 )
2400 {
2401 switch(type)
2402 {
2403 case NL80211_IFTYPE_STATION:
2404#ifdef WLAN_FEATURE_P2P
2405 case NL80211_IFTYPE_P2P_CLIENT:
2406#endif
2407 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002408 hdd_stop_adapter( pHddCtx, pAdapter );
2409 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002410 wdev->iftype = type;
2411#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002412 //Check for sub-string p2p to confirm its a p2p interface
2413 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002414 {
2415 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2416 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2417 }
2418 else
2419 {
2420 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002421 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002422 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002423#endif
2424 hdd_set_conparam(0);
2425 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002426 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2427 hdd_set_station_ops( pAdapter->dev );
2428 status = hdd_init_station_mode( pAdapter );
2429 if( VOS_STATUS_SUCCESS != status )
2430 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002431 /* In case of JB, for P2P-GO, only change interface will be called,
2432 * This is the right place to enable back bmps_imps()
2433 */
2434 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002435 goto done;
2436 case NL80211_IFTYPE_AP:
2437#ifdef WLAN_FEATURE_P2P
2438 case NL80211_IFTYPE_P2P_GO:
2439#endif
2440 wdev->iftype = type;
2441#ifdef WLAN_FEATURE_P2P
2442 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2443 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2444#endif
2445 goto done;
2446 default:
2447 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2448 __func__);
2449 return -EOPNOTSUPP;
2450
2451 }
2452
2453 }
2454 else
2455 {
2456 return -EOPNOTSUPP;
2457 }
2458
2459
2460 if(pRoamProfile)
2461 {
2462 if ( LastBSSType != pRoamProfile->BSSType )
2463 {
2464 /*interface type changed update in wiphy structure*/
2465 wdev->iftype = type;
2466
2467 /*the BSS mode changed, We need to issue disconnect
2468 if connected or in IBSS disconnect state*/
2469 if ( hdd_connGetConnectedBssType(
2470 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2471 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2472 {
2473 /*need to issue a disconnect to CSR.*/
2474 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2475 if( eHAL_STATUS_SUCCESS ==
2476 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2477 pAdapter->sessionId,
2478 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2479 {
2480 wait_for_completion_interruptible_timeout(
2481 &pAdapter->disconnect_comp_var,
2482 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2483 }
2484 }
2485 }
2486 }
2487
2488done:
2489 /*set bitmask based on updated value*/
2490 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2491#ifdef WLAN_BTAMP_FEATURE
2492 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2493 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2494 {
2495 //we are ok to do AMP
2496 pHddCtx->isAmpAllowed = VOS_TRUE;
2497 }
2498#endif //WLAN_BTAMP_FEATURE
2499 EXIT();
2500 return 0;
2501}
2502
2503static int wlan_hdd_change_station(struct wiphy *wiphy,
2504 struct net_device *dev,
2505 u8 *mac,
2506 struct station_parameters *params)
2507{
2508 VOS_STATUS status = VOS_STATUS_SUCCESS;
2509 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2510 v_MACADDR_t STAMacAddress;
2511
Jeff Johnsone7245742012-09-05 17:12:55 -07002512 ENTER();
2513
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002514 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2515 {
2516 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2517 "%s:LOGP in Progress. Ignore!!!", __func__);
2518 return -EAGAIN;
2519 }
2520
Jeff Johnson295189b2012-06-20 16:38:30 -07002521 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2522
2523 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2524#ifdef WLAN_FEATURE_P2P
2525 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2526#endif
2527 )
2528 {
2529 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2530 {
2531 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2532 WLANTL_STA_AUTHENTICATED);
2533
2534 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002535 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002536 return -EINVAL;
2537 }
2538 }
2539
Jeff Johnsone7245742012-09-05 17:12:55 -07002540 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002541 return status;
2542}
2543
2544/*
2545 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2546 * This function is used to get peer station index in IBSS mode
2547 */
2548static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2549{
2550 u8 idx = 0;
2551 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2552 ENTER();
2553 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2554 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2555 {
2556 if ( (0 !=
2557 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2558 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2559 temp, VOS_MAC_ADDR_SIZE)
2560 )
2561 {
2562 return idx;
2563 }
2564 }
2565 return idx;
2566}
2567
2568
2569/*
2570 * FUNCTION: wlan_hdd_cfg80211_add_key
2571 * This function is used to initialize the key information
2572 */
2573#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2574static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2575 struct net_device *ndev,
2576 u8 key_index, bool pairwise,
2577 const u8 *mac_addr,
2578 struct key_params *params
2579 )
2580#else
2581static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2582 struct net_device *ndev,
2583 u8 key_index, const u8 *mac_addr,
2584 struct key_params *params
2585 )
2586#endif
2587{
2588 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2589 tCsrRoamSetKey setKey;
2590 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2591 int status = 0;
2592 v_U32_t roamId= 0xFF;
2593 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2594 hdd_hostapd_state_t *pHostapdState;
2595 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002596 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002597
2598 ENTER();
2599
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002600 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2601 {
2602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2603 "%s:LOGP in Progress. Ignore!!!", __func__);
2604 return -EAGAIN;
2605 }
2606
Jeff Johnson295189b2012-06-20 16:38:30 -07002607 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2608 __func__,pAdapter->device_mode);
2609
2610 if (CSR_MAX_NUM_KEY <= key_index)
2611 {
2612 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2613 key_index);
2614
2615 return -EINVAL;
2616 }
2617
2618 hddLog(VOS_TRACE_LEVEL_INFO,
2619 "%s: called with key index = %d & key length %d",
2620 __func__, key_index, params->key_len);
2621
2622 /*extract key idx, key len and key*/
2623 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2624 setKey.keyId = key_index;
2625 setKey.keyLength = params->key_len;
2626 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2627
2628 switch (params->cipher)
2629 {
2630 case WLAN_CIPHER_SUITE_WEP40:
2631 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2632 break;
2633
2634 case WLAN_CIPHER_SUITE_WEP104:
2635 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2636 break;
2637
2638 case WLAN_CIPHER_SUITE_TKIP:
2639 {
2640 u8 *pKey = &setKey.Key[0];
2641 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2642
2643 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2644
2645 /*Supplicant sends the 32bytes key in this order
2646
2647 |--------------|----------|----------|
2648 | Tk1 |TX-MIC | RX Mic |
2649 |--------------|----------|----------|
2650 <---16bytes---><--8bytes--><--8bytes-->
2651
2652 */
2653 /*Sme expects the 32 bytes key to be in the below order
2654
2655 |--------------|----------|----------|
2656 | Tk1 |RX-MIC | TX Mic |
2657 |--------------|----------|----------|
2658 <---16bytes---><--8bytes--><--8bytes-->
2659 */
2660 /* Copy the Temporal Key 1 (TK1) */
2661 vos_mem_copy(pKey, params->key,16);
2662
2663 /*Copy the rx mic first*/
2664 vos_mem_copy(&pKey[16],&params->key[24],8);
2665
2666 /*Copy the tx mic */
2667 vos_mem_copy(&pKey[24],&params->key[16],8);
2668
2669
2670 break;
2671 }
2672
2673 case WLAN_CIPHER_SUITE_CCMP:
2674 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2675 break;
2676
2677#ifdef FEATURE_WLAN_WAPI
2678 case WLAN_CIPHER_SUITE_SMS4:
2679 {
2680 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2681 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2682 params->key, params->key_len);
2683 return 0;
2684 }
2685#endif
2686#ifdef FEATURE_WLAN_CCX
2687 case WLAN_CIPHER_SUITE_KRK:
2688 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2689 break;
2690#endif
2691 default:
2692 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2693 __func__, params->cipher);
2694 return -EOPNOTSUPP;
2695 }
2696
2697 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2698 __func__, setKey.encType);
2699
2700
2701
2702 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2703#ifdef WLAN_FEATURE_P2P
2704 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2705#endif
2706 )
2707 {
2708
2709
2710 if (
2711#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2712 (!pairwise)
2713#else
2714 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2715#endif
2716 )
2717 {
2718 /* set group key*/
2719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002720 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002721 __func__, __LINE__);
2722 setKey.keyDirection = eSIR_RX_ONLY;
2723 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2724 }
2725 else
2726 {
2727 /* set pairwise key*/
2728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2729 "%s- %d: setting pairwise key",
2730 __func__, __LINE__);
2731 setKey.keyDirection = eSIR_TX_RX;
2732 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2733 }
2734
2735 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2736 if( pHostapdState->bssState == BSS_START )
2737 {
2738 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2739
2740 if ( status != eHAL_STATUS_SUCCESS )
2741 {
2742 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2743 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2744 __LINE__, status );
2745 }
2746 }
2747
2748 /* Saving WEP keys */
2749 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2750 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2751 {
2752 //Save the wep key in ap context. Issue setkey after the BSS is started.
2753 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2754 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2755 }
2756 else
2757 {
2758 //Save the key in ap context. Issue setkey after the BSS is started.
2759 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2760 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2761 }
2762 }
2763 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2764#ifdef WLAN_FEATURE_P2P
2765 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2766#endif
2767 )
2768 {
2769 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2770 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2771
2772 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2773
2774 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2775 params->key, params->key_len);
2776
2777 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2778
2779 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2780 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2781 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2782 )
2783 &&
2784 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2785 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2786 )
2787 )
2788 {
2789 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2790 * interface, copy bssid for pairwise key and group macaddr for
2791 * group key initialization*/
2792
2793 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2794
2795 pWextState->roamProfile.negotiatedUCEncryptionType =
2796 pHddStaCtx->conn_info.ucEncryptionType =
2797 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2798 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2799 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2800
2801
2802 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2803 "%s: Negotiated encryption type %d", __func__,
2804 pWextState->roamProfile.negotiatedUCEncryptionType);
2805
2806 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2807 &pWextState->roamProfile, true);
2808 setKey.keyLength = 0;
2809 setKey.keyDirection = eSIR_TX_RX;
2810
2811#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2812 if (pairwise)
2813 {
2814#endif
2815 if (mac_addr)
2816 {
2817 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2818 }
2819 else
2820 {
2821 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2822 * and peerMacAddress in case of IBSS*/
2823 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2824 {
2825 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2826 if (HDD_MAX_NUM_IBSS_STA != staidx)
2827 {
2828 vos_mem_copy(setKey.peerMac,
2829 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2830 WNI_CFG_BSSID_LEN);
2831
2832 }
2833 else
2834 {
2835 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2836 __func__);
2837 return -EOPNOTSUPP;
2838 }
2839 }
2840 else
2841 {
2842 vos_mem_copy(setKey.peerMac,
2843 &pHddStaCtx->conn_info.bssId[0],
2844 WNI_CFG_BSSID_LEN);
2845 }
2846 }
2847#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2848 }
2849 else
2850 {
2851 /* set group key*/
2852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2853 "%s- %d: setting Group key",
2854 __func__, __LINE__);
2855 setKey.keyDirection = eSIR_RX_ONLY;
2856 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2857 }
2858#endif
2859 }
2860 else if (
2861#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2862 (!pairwise)
2863#else
2864 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2865#endif
2866 )
2867 {
2868 /* set group key*/
2869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2870 "%s- %d: setting Group key",
2871 __func__, __LINE__);
2872 setKey.keyDirection = eSIR_RX_ONLY;
2873 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2874 }
2875 else
2876 {
2877 /* set pairwise key*/
2878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2879 "%s- %d: setting pairwise key",
2880 __func__, __LINE__);
2881 setKey.keyDirection = eSIR_TX_RX;
2882 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2883 }
2884
2885 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2886 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2887 __func__, setKey.peerMac[0], setKey.peerMac[1],
2888 setKey.peerMac[2], setKey.peerMac[3],
2889 setKey.peerMac[4], setKey.peerMac[5],
2890 setKey.keyDirection);
2891
2892 vos_status = wlan_hdd_check_ula_done(pAdapter);
2893
2894 if ( vos_status != VOS_STATUS_SUCCESS )
2895 {
2896 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2897 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2898 __LINE__, vos_status );
2899
2900 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2901
2902 return -EINVAL;
2903
2904 }
2905
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002906#ifdef WLAN_FEATURE_VOWIFI_11R
2907 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2908 Save the key in the UMAC and include it in the ADD BSS request */
2909 /*TODO 11r - is this used?? */
2910 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2911 if( halStatus == eHAL_STATUS_SUCCESS )
2912 {
2913 return halStatus;
2914 }
2915#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002916
2917 /* issue set key request to SME*/
2918 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2919 pAdapter->sessionId, &setKey, &roamId );
2920
2921 if ( 0 != status )
2922 {
2923 hddLog(VOS_TRACE_LEVEL_ERROR,
2924 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2925 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2926 return -EINVAL;
2927 }
2928
2929
2930 /* in case of IBSS as there was no information available about WEP keys during
2931 * IBSS join, group key intialized with NULL key, so re-initialize group key
2932 * with correct value*/
2933 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2934 !( ( IW_AUTH_KEY_MGMT_802_1X
2935 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2936 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2937 )
2938 &&
2939 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2940 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2941 )
2942 )
2943 {
2944 setKey.keyDirection = eSIR_RX_ONLY;
2945 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2946
2947 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2948 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2949 __func__, setKey.peerMac[0], setKey.peerMac[1],
2950 setKey.peerMac[2], setKey.peerMac[3],
2951 setKey.peerMac[4], setKey.peerMac[5],
2952 setKey.keyDirection);
2953
2954 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2955 pAdapter->sessionId, &setKey, &roamId );
2956
2957 if ( 0 != status )
2958 {
2959 hddLog(VOS_TRACE_LEVEL_ERROR,
2960 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
2961 __func__, status);
2962 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2963 return -EINVAL;
2964 }
2965 }
2966 }
2967
2968 return 0;
2969}
2970
2971/*
2972 * FUNCTION: wlan_hdd_cfg80211_get_key
2973 * This function is used to get the key information
2974 */
2975#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2976static int wlan_hdd_cfg80211_get_key(
2977 struct wiphy *wiphy,
2978 struct net_device *ndev,
2979 u8 key_index, bool pairwise,
2980 const u8 *mac_addr, void *cookie,
2981 void (*callback)(void *cookie, struct key_params*)
2982 )
2983#else
2984static int wlan_hdd_cfg80211_get_key(
2985 struct wiphy *wiphy,
2986 struct net_device *ndev,
2987 u8 key_index, const u8 *mac_addr, void *cookie,
2988 void (*callback)(void *cookie, struct key_params*)
2989 )
2990#endif
2991{
2992 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2993 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2994 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
2995 struct key_params params;
2996
2997 ENTER();
2998
2999 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3000 __func__,pAdapter->device_mode);
3001
3002 memset(&params, 0, sizeof(params));
3003
3004 if (CSR_MAX_NUM_KEY <= key_index)
3005 {
3006 return -EINVAL;
3007 }
3008
3009 switch(pRoamProfile->EncryptionType.encryptionType[0])
3010 {
3011 case eCSR_ENCRYPT_TYPE_NONE:
3012 params.cipher = IW_AUTH_CIPHER_NONE;
3013 break;
3014
3015 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3016 case eCSR_ENCRYPT_TYPE_WEP40:
3017 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3018 break;
3019
3020 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3021 case eCSR_ENCRYPT_TYPE_WEP104:
3022 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3023 break;
3024
3025 case eCSR_ENCRYPT_TYPE_TKIP:
3026 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3027 break;
3028
3029 case eCSR_ENCRYPT_TYPE_AES:
3030 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3031 break;
3032
3033 default:
3034 params.cipher = IW_AUTH_CIPHER_NONE;
3035 break;
3036 }
3037
3038 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3039 params.seq_len = 0;
3040 params.seq = NULL;
3041 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3042 callback(cookie, &params);
3043 return 0;
3044}
3045
3046/*
3047 * FUNCTION: wlan_hdd_cfg80211_del_key
3048 * This function is used to delete the key information
3049 */
3050#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3051static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3052 struct net_device *ndev,
3053 u8 key_index,
3054 bool pairwise,
3055 const u8 *mac_addr
3056 )
3057#else
3058static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3059 struct net_device *ndev,
3060 u8 key_index,
3061 const u8 *mac_addr
3062 )
3063#endif
3064{
3065 int status = 0;
3066
3067 //This code needs to be revisited. There is sme_removeKey API, we should
3068 //plan to use that. After the change to use correct index in setkey,
3069 //it is observed that this is invalidating peer
3070 //key index whenever re-key is done. This is affecting data link.
3071 //It should be ok to ignore del_key.
3072#if 0
3073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3074 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3075 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3076 tCsrRoamSetKey setKey;
3077 v_U32_t roamId= 0xFF;
3078
3079 ENTER();
3080
3081 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3082 __func__,pAdapter->device_mode);
3083
3084 if (CSR_MAX_NUM_KEY <= key_index)
3085 {
3086 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3087 key_index);
3088
3089 return -EINVAL;
3090 }
3091
3092 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3093 setKey.keyId = key_index;
3094
3095 if (mac_addr)
3096 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3097 else
3098 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3099
3100 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3101
3102 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3103#ifdef WLAN_FEATURE_P2P
3104 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3105#endif
3106 )
3107 {
3108
3109 hdd_hostapd_state_t *pHostapdState =
3110 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3111 if( pHostapdState->bssState == BSS_START)
3112 {
3113 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3114
3115 if ( status != eHAL_STATUS_SUCCESS )
3116 {
3117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3118 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3119 __LINE__, status );
3120 }
3121 }
3122 }
3123 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3124#ifdef WLAN_FEATURE_P2P
3125 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3126#endif
3127 )
3128 {
3129 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3130
3131 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3132
3133 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3134 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3135 __func__, setKey.peerMac[0], setKey.peerMac[1],
3136 setKey.peerMac[2], setKey.peerMac[3],
3137 setKey.peerMac[4], setKey.peerMac[5]);
3138 if(pAdapter->sessionCtx.station.conn_info.connState ==
3139 eConnectionState_Associated)
3140 {
3141 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3142 pAdapter->sessionId, &setKey, &roamId );
3143
3144 if ( 0 != status )
3145 {
3146 hddLog(VOS_TRACE_LEVEL_ERROR,
3147 "%s: sme_RoamSetKey failure, returned %d",
3148 __func__, status);
3149 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3150 return -EINVAL;
3151 }
3152 }
3153 }
3154#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003155 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003156 return status;
3157}
3158
3159/*
3160 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3161 * This function is used to set the default tx key index
3162 */
3163#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3164static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3165 struct net_device *ndev,
3166 u8 key_index,
3167 bool unicast, bool multicast)
3168#else
3169static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3170 struct net_device *ndev,
3171 u8 key_index)
3172#endif
3173{
3174 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3175 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3176 int status = 0;
3177 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3178
3179 ENTER();
3180
3181 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3182 __func__,pAdapter->device_mode, key_index);
3183
3184 if (CSR_MAX_NUM_KEY <= key_index)
3185 {
3186 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3187 key_index);
3188
3189 return -EINVAL;
3190 }
3191
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003192 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3193 {
3194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3195 "%s:LOGP in Progress. Ignore!!!", __func__);
3196 return -EAGAIN;
3197 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003198
3199 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3200#ifdef WLAN_FEATURE_P2P
3201 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3202#endif
3203 )
3204 {
3205 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3206 (eCSR_ENCRYPT_TYPE_TKIP !=
3207 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3208 (eCSR_ENCRYPT_TYPE_AES !=
3209 pWextState->roamProfile.EncryptionType.encryptionType[0])
3210 )
3211 {
3212 /* if default key index is not same as previous one,
3213 * then update the default key index */
3214
3215 tCsrRoamSetKey setKey;
3216 v_U32_t roamId= 0xFF;
3217 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3218
3219 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3220 __func__, key_index);
3221
3222 Keys->defaultIndex = (u8)key_index;
3223 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3224 setKey.keyId = key_index;
3225 setKey.keyLength = Keys->KeyLength[key_index];
3226
3227 vos_mem_copy(&setKey.Key[0],
3228 &Keys->KeyMaterial[key_index][0],
3229 Keys->KeyLength[key_index]);
3230
3231 setKey.keyDirection = eSIR_TX_ONLY;
3232
3233 vos_mem_copy(setKey.peerMac,
3234 &pHddStaCtx->conn_info.bssId[0],
3235 WNI_CFG_BSSID_LEN);
3236
3237 setKey.encType =
3238 pWextState->roamProfile.EncryptionType.encryptionType[0];
3239
3240 /* issue set key request */
3241 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3242 pAdapter->sessionId, &setKey, &roamId );
3243
3244 if ( 0 != status )
3245 {
3246 hddLog(VOS_TRACE_LEVEL_ERROR,
3247 "%s: sme_RoamSetKey failed, returned %d", __func__,
3248 status);
3249 return -EINVAL;
3250 }
3251 }
3252 }
3253
3254 /* In SoftAp mode setting key direction for default mode */
3255 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3256 {
3257 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3258 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3259 (eCSR_ENCRYPT_TYPE_AES !=
3260 pWextState->roamProfile.EncryptionType.encryptionType[0])
3261 )
3262 {
3263 /* Saving key direction for default key index to TX default */
3264 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3265 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3266 }
3267 }
3268
3269 return status;
3270}
3271
3272/**
3273 * FUNCTION: wlan_hdd_cfg80211_set_channel
3274 * This function is used to set the channel number
3275 */
3276int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3277 struct ieee80211_channel *chan,
3278 enum nl80211_channel_type channel_type
3279 )
3280{
3281 v_U32_t num_ch = 0;
3282 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003283 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003284 int freq = chan->center_freq; /* freq is in MHZ */
3285
3286 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003287
3288 if( NULL == dev )
3289 {
3290 hddLog(VOS_TRACE_LEVEL_ERROR,
3291 "%s: Called with dev = NULL.\n", __func__);
3292 return -ENODEV;
3293 }
3294 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003295
3296 hddLog(VOS_TRACE_LEVEL_INFO,
3297 "%s: device_mode = %d freq = %d \n",__func__,
3298 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003299 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3300 {
3301 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3302 return -EAGAIN;
3303 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003304
3305 /*
3306 * Do freq to chan conversion
3307 * TODO: for 11a
3308 */
3309
3310 channel = ieee80211_frequency_to_channel(freq);
3311
3312 /* Check freq range */
3313 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3314 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3315 {
3316 hddLog(VOS_TRACE_LEVEL_ERROR,
3317 "%s: Channel [%d] is outside valid range from %d to %d\n",
3318 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3319 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3320 return -EINVAL;
3321 }
3322
3323 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3324
3325 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3326#ifdef WLAN_FEATURE_P2P
3327 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3328#endif
3329 )
3330 {
3331 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3332 {
3333 hddLog(VOS_TRACE_LEVEL_ERROR,
3334 "%s: Invalid Channel [%d] \n", __func__, channel);
3335 return -EINVAL;
3336 }
3337 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3338 "%s: set channel to [%d] for device mode =%d",
3339 __func__, channel,pAdapter->device_mode);
3340 }
3341 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3342#ifdef WLAN_FEATURE_P2P
3343 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3344#endif
3345 )
3346 {
3347 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3348 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3349 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3350
3351 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3352 {
3353 /* Link is up then return cant set channel*/
3354 hddLog( VOS_TRACE_LEVEL_ERROR,
3355 "%s: IBSS Associated, can't set the channel\n", __func__);
3356 return -EINVAL;
3357 }
3358
3359 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3360 pHddStaCtx->conn_info.operationChannel = channel;
3361 pRoamProfile->ChannelInfo.ChannelList =
3362 &pHddStaCtx->conn_info.operationChannel;
3363 }
3364 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3365#ifdef WLAN_FEATURE_P2P
3366 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3367#endif
3368 )
3369 {
3370 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3371
3372 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3373 {
3374 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3375
3376 /* If auto channel selection is configured as enable/ 1 then ignore
3377 channel set by supplicant
3378 */
3379 if ( cfg_param->apAutoChannelSelection )
3380 {
3381 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3382
3383 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3384 "%s: set channel to auto channel (0) for device mode =%d",
3385 __func__, pAdapter->device_mode);
3386 }
3387 }
3388 }
3389 else
3390 {
3391 hddLog(VOS_TRACE_LEVEL_FATAL,
3392 "%s: Invalid device mode failed to set valid channel", __func__);
3393 return -EINVAL;
3394 }
3395 EXIT();
3396 return 0;
3397}
3398
3399
3400
3401/*
3402 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3403 * This function is used to inform the BSS details to nl80211 interface.
3404 */
3405static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3406 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3407{
3408 struct net_device *dev = pAdapter->dev;
3409 struct wireless_dev *wdev = dev->ieee80211_ptr;
3410 struct wiphy *wiphy = wdev->wiphy;
3411 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3412 int chan_no;
3413 int ie_length;
3414 const char *ie;
3415 unsigned int freq;
3416 struct ieee80211_channel *chan;
3417 int rssi = 0;
3418 struct cfg80211_bss *bss = NULL;
3419
3420 ENTER();
3421
3422 if( NULL == pBssDesc )
3423 {
3424 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3425 return bss;
3426 }
3427
3428 chan_no = pBssDesc->channelId;
3429 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3430 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3431
3432 if( NULL == ie )
3433 {
3434 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3435 return bss;
3436 }
3437
3438#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3439 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3440 {
3441 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3442 }
3443 else
3444 {
3445 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3446 }
3447#else
3448 freq = ieee80211_channel_to_frequency(chan_no);
3449#endif
3450
3451 chan = __ieee80211_get_channel(wiphy, freq);
3452
3453 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3454 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3455 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3456 if (bss == NULL)
3457 {
3458 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3459
3460 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3461 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3462 pBssDesc->capabilityInfo,
3463 pBssDesc->beaconInterval, ie, ie_length,
3464 rssi, GFP_KERNEL ));
3465}
3466 else
3467 {
3468 return bss;
3469 }
3470}
3471
3472
3473
3474/*
3475 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3476 * This function is used to inform the BSS details to nl80211 interface.
3477 */
3478struct cfg80211_bss*
3479wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3480 tSirBssDescription *bss_desc
3481 )
3482{
3483 /*
3484 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3485 already exists in bss data base of cfg80211 for that particular BSS ID.
3486 Using cfg80211_inform_bss_frame to update the bss entry instead of
3487 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3488 now there is no possibility to get the mgmt(probe response) frame from PE,
3489 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3490 cfg80211_inform_bss_frame.
3491 */
3492 struct net_device *dev = pAdapter->dev;
3493 struct wireless_dev *wdev = dev->ieee80211_ptr;
3494 struct wiphy *wiphy = wdev->wiphy;
3495 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003496#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3497 qcom_ie_age *qie_age = NULL;
3498 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3499#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003500 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003501#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003502 const char *ie =
3503 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3504 unsigned int freq;
3505 struct ieee80211_channel *chan;
3506 struct ieee80211_mgmt *mgmt =
3507 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3508 struct cfg80211_bss *bss_status = NULL;
3509 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3510 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003511#ifdef WLAN_OPEN_SOURCE
3512 struct timespec ts;
3513#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003514
3515 ENTER();
3516
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003517 if (!mgmt)
3518 return NULL;
3519
Jeff Johnson295189b2012-06-20 16:38:30 -07003520 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003521
3522#ifdef WLAN_OPEN_SOURCE
3523 /* Android does not want the timestamp from the frame.
3524 Instead it wants a monotonic increasing value */
3525 get_monotonic_boottime(&ts);
3526 mgmt->u.probe_resp.timestamp =
3527 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3528#else
3529 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003530 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3531 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003532
3533#endif
3534
Jeff Johnson295189b2012-06-20 16:38:30 -07003535 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3536 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003537
3538#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3539 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3540 /* Assuming this is the last IE, copy at the end */
3541 ie_length -=sizeof(qcom_ie_age);
3542 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3543 qie_age->element_id = QCOM_VENDOR_IE_ID;
3544 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3545 qie_age->oui_1 = QCOM_OUI1;
3546 qie_age->oui_2 = QCOM_OUI2;
3547 qie_age->oui_3 = QCOM_OUI3;
3548 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3549 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3550#endif
3551
Jeff Johnson295189b2012-06-20 16:38:30 -07003552 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3553
3554 mgmt->frame_control |=
3555 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3556
3557#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3558 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3559 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3560 {
3561 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3562 }
3563 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3564 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3565
3566 {
3567 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3568 }
3569 else
3570 {
3571 kfree(mgmt);
3572 return NULL;
3573 }
3574#else
3575 freq = ieee80211_channel_to_frequency(chan_no);
3576#endif
3577 chan = __ieee80211_get_channel(wiphy, freq);
3578
3579 /*To keep the rssi icon of the connected AP in the scan window
3580 *and the rssi icon of the wireless networks in sync
3581 * */
3582 if (( eConnectionState_Associated ==
3583 pAdapter->sessionCtx.station.conn_info.connState ) &&
3584 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3585 pAdapter->sessionCtx.station.conn_info.bssId,
3586 WNI_CFG_BSSID_LEN)))
3587 {
3588 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3589 rssi = (pAdapter->rssi * 100);
3590 }
3591 else
3592 {
3593 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3594 }
3595
3596 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3597 frame_len, rssi, GFP_KERNEL);
3598 kfree(mgmt);
3599 return bss_status;
3600}
3601
3602/*
3603 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3604 * This function is used to update the BSS data base of CFG8011
3605 */
3606struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3607 tCsrRoamInfo *pRoamInfo
3608 )
3609{
3610 tCsrRoamConnectedProfile roamProfile;
3611 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3612 struct cfg80211_bss *bss = NULL;
3613
3614 ENTER();
3615
3616 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3617 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3618
3619 if (NULL != roamProfile.pBssDesc)
3620 {
3621 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3622 &roamProfile);
3623
3624 if (NULL == bss)
3625 {
3626 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3627 __func__);
3628 }
3629
3630 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3631 }
3632 else
3633 {
3634 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3635 __func__);
3636 }
3637 return bss;
3638}
3639
3640/*
3641 * FUNCTION: wlan_hdd_cfg80211_update_bss
3642 */
3643static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3644 hdd_adapter_t *pAdapter
3645 )
3646{
3647 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3648 tCsrScanResultInfo *pScanResult;
3649 eHalStatus status = 0;
3650 tScanResultHandle pResult;
3651 struct cfg80211_bss *bss_status = NULL;
3652
3653 ENTER();
3654
3655 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3656 {
3657 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3658 return -EAGAIN;
3659 }
3660
3661 /*
3662 * start getting scan results and populate cgf80211 BSS database
3663 */
3664 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3665
3666 /* no scan results */
3667 if (NULL == pResult)
3668 {
3669 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3670 return status;
3671 }
3672
3673 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3674
3675 while (pScanResult)
3676 {
3677 /*
3678 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3679 * entry already exists in bss data base of cfg80211 for that
3680 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3681 * bss entry instead of cfg80211_inform_bss, But this call expects
3682 * mgmt packet as input. As of now there is no possibility to get
3683 * the mgmt(probe response) frame from PE, converting bss_desc to
3684 * ieee80211_mgmt(probe response) and passing to c
3685 * fg80211_inform_bss_frame.
3686 * */
3687
3688 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3689 &pScanResult->BssDescriptor);
3690
3691
3692 if (NULL == bss_status)
3693 {
3694 hddLog(VOS_TRACE_LEVEL_INFO,
3695 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3696 }
3697 else
3698 {
3699 cfg80211_put_bss(bss_status);
3700 }
3701
3702 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3703 }
3704
3705 sme_ScanResultPurge(hHal, pResult);
3706
3707 return 0;
3708}
3709
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003710void
3711hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3712{
3713 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003714 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3715 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3716 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003717} /****** end hddPrintMacAddr() ******/
3718
3719void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003720hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003721{
3722 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003723 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3724 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3725 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3726 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003727} /****** end hddPrintPmkId() ******/
3728
3729//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3730//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3731
3732//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3733//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3734
3735#define dump_bssid(bssid) \
3736 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003737 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3738 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3739 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003740 }
3741
3742#define dump_pmkid(pMac, pmkid) \
3743 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003744 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3745 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3746 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003747 }
3748
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003749#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003750/*
3751 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3752 * This function is used to notify the supplicant of a new PMKSA candidate.
3753 */
3754int wlan_hdd_cfg80211_pmksa_candidate_notify(
3755 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3756 int index, bool preauth )
3757{
Jeff Johnsone7245742012-09-05 17:12:55 -07003758#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003759 struct net_device *dev = pAdapter->dev;
3760
3761 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003762 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003763
3764 if( NULL == pRoamInfo )
3765 {
3766 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3767 return -EINVAL;
3768 }
3769
3770 dump_bssid(pRoamInfo->bssid);
3771 cfg80211_pmksa_candidate_notify(dev, index,
3772 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003773#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003774 return 0;
3775}
3776#endif //FEATURE_WLAN_LFR
3777
Jeff Johnson295189b2012-06-20 16:38:30 -07003778/*
3779 * FUNCTION: hdd_cfg80211_scan_done_callback
3780 * scanning callback function, called after finishing scan
3781 *
3782 */
3783static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3784 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3785{
3786 struct net_device *dev = (struct net_device *) pContext;
3787 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3788 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003789 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3790 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003791 struct cfg80211_scan_request *req = NULL;
3792 int ret = 0;
3793
3794 ENTER();
3795
3796 hddLog(VOS_TRACE_LEVEL_INFO,
3797 "%s called with halHandle = %p, pContext = %p,"
3798 "scanID = %d, returned status = %d\n",
3799 __func__, halHandle, pContext, (int) scanId, (int) status);
3800
3801 //Block on scan req completion variable. Can't wait forever though.
3802 ret = wait_for_completion_interruptible_timeout(
3803 &pScanInfo->scan_req_completion_event,
3804 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3805 if (!ret)
3806 {
3807 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003808 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003809 }
3810
3811 if(pScanInfo->mScanPending != VOS_TRUE)
3812 {
3813 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003814 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003815 }
3816
3817 /* Check the scanId */
3818 if (pScanInfo->scanId != scanId)
3819 {
3820 hddLog(VOS_TRACE_LEVEL_INFO,
3821 "%s called with mismatched scanId pScanInfo->scanId = %d "
3822 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3823 (int) scanId);
3824 }
3825
Jeff Johnson295189b2012-06-20 16:38:30 -07003826 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3827 pAdapter);
3828
3829 if (0 > ret)
3830 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3831
3832
3833 /* If any client wait scan result through WEXT
3834 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003835 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003836 {
3837 /* The other scan request waiting for current scan finish
3838 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003839 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003840 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003841 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003842 }
3843 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003844 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003845 {
3846 struct net_device *dev = pAdapter->dev;
3847 union iwreq_data wrqu;
3848 int we_event;
3849 char *msg;
3850
3851 memset(&wrqu, '\0', sizeof(wrqu));
3852 we_event = SIOCGIWSCAN;
3853 msg = NULL;
3854 wireless_send_event(dev, we_event, &wrqu, msg);
3855 }
3856 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003857 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003858
3859 /* Get the Scan Req */
3860 req = pAdapter->request;
3861
3862 if (!req)
3863 {
3864 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003865 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003866 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003867 }
3868
3869 /*
3870 * setting up 0, just in case.
3871 */
3872 req->n_ssids = 0;
3873 req->n_channels = 0;
3874 req->ie = 0;
3875
Jeff Johnson295189b2012-06-20 16:38:30 -07003876 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003877 /* Scan is no longer pending */
3878 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003879
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003880 /*
3881 * cfg80211_scan_done informing NL80211 about completion
3882 * of scanning
3883 */
3884 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003885 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003886
Jeff Johnsone7245742012-09-05 17:12:55 -07003887allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003888 /* release the wake lock at the end of the scan*/
3889 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003890
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003891 /* Acquire wakelock to handle the case where APP's tries to suspend
3892 * immediatly after the driver gets connect request(i.e after scan)
3893 * from supplicant, this result in app's is suspending and not able
3894 * to process the connect request to AP */
3895 hdd_allow_suspend_timeout(100);
3896
Jeff Johnson295189b2012-06-20 16:38:30 -07003897 EXIT();
3898 return 0;
3899}
3900
3901/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08003902 * FUNCTION: hdd_isScanAllowed
3903 * Go through each adapter and check if scan allowed
3904 *
3905 */
3906v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
3907{
3908 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3909 hdd_station_ctx_t *pHddStaCtx = NULL;
3910 hdd_adapter_t *pAdapter = NULL;
3911 VOS_STATUS status = 0;
3912 v_U8_t staId = 0;
3913 v_U8_t *staMac = NULL;
3914
3915 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3916
3917 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3918 {
3919 pAdapter = pAdapterNode->pAdapter;
3920
3921 if( pAdapter )
3922 {
3923 hddLog(VOS_TRACE_LEVEL_INFO,
3924 "%s: Adapter with device mode %d exists",
3925 __func__, pAdapter->device_mode);
3926 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3927 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3928 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
3929 {
3930 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3931 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
3932 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
3933 {
3934 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
3935 hddLog(VOS_TRACE_LEVEL_ERROR,
3936 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
3937 "middle of WPS/EAPOL exchange.", __func__,
3938 staMac[0], staMac[1], staMac[2],
3939 staMac[3], staMac[4], staMac[5]);
3940 return VOS_FALSE;
3941 }
3942 }
3943 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
3944 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
3945 {
3946 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
3947 {
3948 if ((pAdapter->aStaInfo[staId].isUsed) &&
3949 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
3950 {
3951 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
3952
3953 hddLog(VOS_TRACE_LEVEL_ERROR,
3954 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
3955 "middle of WPS/EAPOL exchange.", __func__,
3956 staMac[0], staMac[1], staMac[2],
3957 staMac[3], staMac[4], staMac[5]);
3958 return VOS_FALSE;
3959 }
3960 }
3961 }
3962 }
3963 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3964 pAdapterNode = pNext;
3965 }
3966 hddLog(VOS_TRACE_LEVEL_INFO,
3967 "%s: Scan allowed", __func__);
3968 return VOS_TRUE;
3969}
3970
3971/*
Jeff Johnson295189b2012-06-20 16:38:30 -07003972 * FUNCTION: wlan_hdd_cfg80211_scan
3973 * this scan respond to scan trigger and update cfg80211 scan database
3974 * later, scan dump command can be used to recieve scan results
3975 */
3976int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3977 struct cfg80211_scan_request *request)
3978{
3979 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3980 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3981 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3982 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3983 tCsrScanRequest scanRequest;
3984 tANI_U8 *channelList = NULL, i;
3985 v_U32_t scanId = 0;
3986 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003987 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003988#ifdef WLAN_FEATURE_P2P
3989 v_U8_t* pP2pIe = NULL;
3990#endif
3991
3992 ENTER();
3993
3994 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3995 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003996
3997 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
3998 (eConnectionState_Connecting ==
3999 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4000 {
4001 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004002 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4003 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004004 return -EBUSY;
4005 }
4006
Jeff Johnson295189b2012-06-20 16:38:30 -07004007#ifdef WLAN_BTAMP_FEATURE
4008 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004009 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004010 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004011 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004012 "%s: No scanning when AMP is on", __func__);
4013 return -EOPNOTSUPP;
4014 }
4015#endif
4016 //Scan on any other interface is not supported.
4017 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4018 {
4019 hddLog(VOS_TRACE_LEVEL_ERROR,
4020 "%s: Not scanning on device_mode = %d",
4021 __func__, pAdapter->device_mode);
4022 return -EOPNOTSUPP;
4023 }
4024
4025 if (TRUE == pScanInfo->mScanPending)
4026 {
4027 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4028 return -EBUSY;
4029 }
4030
4031 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4032 {
4033 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4034 "%s:LOGP in Progress. Ignore!!!", __func__);
4035 return -EAGAIN;
4036 }
4037
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004038 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4039 {
4040 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4041 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4042 return -EAGAIN;
4043 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004044 //Don't Allow Scan and return busy if Remain On
4045 //Channel and action frame is pending
4046 //Otherwise Cancel Remain On Channel and allow Scan
4047 //If no action frame pending
4048 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4049 {
4050 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4051 return -EBUSY;
4052 }
4053
Jeff Johnson295189b2012-06-20 16:38:30 -07004054 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4055 {
4056 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004057 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004058 return -EAGAIN;
4059 }
4060 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4061 {
4062 hddLog(VOS_TRACE_LEVEL_WARN,
4063 "%s: MAX TM Level Scan not allowed", __func__);
4064 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4065 return -EBUSY;
4066 }
4067 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4068
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004069 /* Check if scan is allowed at this point of time.
4070 */
4071 if (!hdd_isScanAllowed(pHddCtx))
4072 {
4073 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4074 return -EBUSY;
4075 }
4076
Jeff Johnson295189b2012-06-20 16:38:30 -07004077 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4078
4079 if (NULL != request)
4080 {
4081 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4082 (int)request->n_ssids);
4083
4084 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4085 * Becasue of this, driver is assuming that this is not wildcard scan and so
4086 * is not aging out the scan results.
4087 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004088 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004089 {
4090 request->n_ssids = 0;
4091 }
4092
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004093 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004094 {
4095 tCsrSSIDInfo *SsidInfo;
4096 int j;
4097 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4098 /* Allocate num_ssid tCsrSSIDInfo structure */
4099 SsidInfo = scanRequest.SSIDs.SSIDList =
4100 ( tCsrSSIDInfo *)vos_mem_malloc(
4101 request->n_ssids*sizeof(tCsrSSIDInfo));
4102
4103 if(NULL == scanRequest.SSIDs.SSIDList)
4104 {
4105 hddLog(VOS_TRACE_LEVEL_ERROR,
4106 "memory alloc failed SSIDInfo buffer");
4107 return -ENOMEM;
4108 }
4109
4110 /* copy all the ssid's and their length */
4111 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4112 {
4113 /* get the ssid length */
4114 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4115 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4116 SsidInfo->SSID.length);
4117 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4118 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4119 j, SsidInfo->SSID.ssId);
4120 }
4121 /* set the scan type to active */
4122 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4123 }
4124 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4125 {
4126 /* set the scan type to active */
4127 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4128 }
4129 else
4130 {
4131 /*Set the scan type to default type, in this case it is ACTIVE*/
4132 scanRequest.scanType = pScanInfo->scan_mode;
4133 }
4134 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4135 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4136 }
4137 else
4138 {
4139 /* set the scan type to active */
4140 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4141 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4142
4143 /* set min and max channel time to zero */
4144 scanRequest.minChnTime = 0;
4145 scanRequest.maxChnTime = 0;
4146 }
4147
4148 /* set BSSType to default type */
4149 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4150
4151 /*TODO: scan the requested channels only*/
4152
4153 /*Right now scanning all the channels */
4154 if( request )
4155 {
4156 if( request->n_channels )
4157 {
4158 channelList = vos_mem_malloc( request->n_channels );
4159 if( NULL == channelList )
4160 {
4161 status = -ENOMEM;
4162 goto free_mem;
4163 }
4164
4165 for( i = 0 ; i < request->n_channels ; i++ )
4166 channelList[i] = request->channels[i]->hw_value;
4167 }
4168
4169 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4170 scanRequest.ChannelInfo.ChannelList = channelList;
4171
4172 /* set requestType to full scan */
4173 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004174
4175 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4176 * search (Flush on both full scan and social scan but not on single
4177 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4178 */
4179
4180 /* Supplicant does single channel scan after 8-way handshake
4181 * and in that case driver shoudnt flush scan results. If
4182 * driver flushes the scan results here and unfortunately if
4183 * the AP doesnt respond to our probe req then association
4184 * fails which is not desired
4185 */
4186
4187 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4188 {
4189 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4190 pAdapter->sessionId );
4191 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004192
4193 if( request->ie_len )
4194 {
4195 /* save this for future association (join requires this) */
4196 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4197 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4198 pScanInfo->scanAddIE.length = request->ie_len;
4199
4200 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004201 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4202 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004203 )
4204 {
4205 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4206 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4207 }
4208
4209 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4210 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4211
4212#ifdef WLAN_FEATURE_P2P
4213 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4214 request->ie_len);
4215 if (pP2pIe != NULL)
4216 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004217#ifdef WLAN_FEATURE_P2P_DEBUG
4218 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4219 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4220 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4221 {
4222 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4223 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4224 "Go nego completed to Connection is started");
4225 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4226 "for 8way Handshake");
4227 }
4228 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4229 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4230 {
4231 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4232 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4233 "Disconnected state to Connection is started");
4234 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4235 "for 4way Handshake");
4236 }
4237#endif
4238
Jeff Johnsone7245742012-09-05 17:12:55 -07004239 /* no_cck will be set during p2p find to disable 11b rates */
4240 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004241 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004242 hddLog(VOS_TRACE_LEVEL_INFO,
4243 "%s: This is a P2P Search", __func__);
4244 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004245
Jeff Johnsone7245742012-09-05 17:12:55 -07004246 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4247 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004248 /* set requestType to P2P Discovery */
4249 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004250 }
4251
4252 /*
4253 Skip Dfs Channel in case of P2P Search
4254 if it is set in ini file
4255 */
4256 if(cfg_param->skipDfsChnlInP2pSearch)
4257 {
4258 scanRequest.skipDfsChnlInP2pSearch = 1;
4259 }
4260 else
4261 {
4262 scanRequest.skipDfsChnlInP2pSearch = 0;
4263 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004264
Jeff Johnson295189b2012-06-20 16:38:30 -07004265 }
4266 }
4267#endif
4268 }
4269 }
4270
4271 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4272
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004273 /* acquire the wakelock to avoid the apps suspend during the scan. To
4274 * address the following issues.
4275 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4276 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4277 * for long time, this result in apps running at full power for long time.
4278 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4279 * be stuck in full power because of resume BMPS
4280 */
4281 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004282
4283 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004284 pAdapter->sessionId, &scanRequest, &scanId,
4285 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004286
Jeff Johnson295189b2012-06-20 16:38:30 -07004287 if (eHAL_STATUS_SUCCESS != status)
4288 {
4289 hddLog(VOS_TRACE_LEVEL_ERROR,
4290 "%s: sme_ScanRequest returned error %d", __func__, status);
4291 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004292 if(eHAL_STATUS_RESOURCES == status)
4293 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004294 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 -07004295 status = -EBUSY;
4296 } else {
4297 status = -EIO;
4298 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004299 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004300 goto free_mem;
4301 }
4302
4303 pScanInfo->mScanPending = TRUE;
4304 pAdapter->request = request;
4305 pScanInfo->scanId = scanId;
4306
4307 complete(&pScanInfo->scan_req_completion_event);
4308
4309free_mem:
4310 if( scanRequest.SSIDs.SSIDList )
4311 {
4312 vos_mem_free(scanRequest.SSIDs.SSIDList);
4313 }
4314
4315 if( channelList )
4316 vos_mem_free( channelList );
4317
4318 EXIT();
4319
4320 return status;
4321}
4322
4323/*
4324 * FUNCTION: wlan_hdd_cfg80211_connect_start
4325 * This function is used to start the association process
4326 */
4327int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004328 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004329{
4330 int status = 0;
4331 hdd_wext_state_t *pWextState;
4332 v_U32_t roamId;
4333 tCsrRoamProfile *pRoamProfile;
4334 eMib_dot11DesiredBssType connectedBssType;
4335 eCsrAuthType RSNAuthType;
4336
4337 ENTER();
4338
4339 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4340
4341 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4342 {
4343 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4344 return -EINVAL;
4345 }
4346
4347 pRoamProfile = &pWextState->roamProfile;
4348
4349 if (pRoamProfile)
4350 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004351 int ret = 0;
4352 hdd_station_ctx_t *pHddStaCtx;
4353 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4354 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4355
4356 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4357 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4358 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004359 {
4360 /* Issue disconnect to CSR */
4361 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4362 if( eHAL_STATUS_SUCCESS ==
4363 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4364 pAdapter->sessionId,
4365 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4366 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004367 ret = wait_for_completion_interruptible_timeout(
4368 &pAdapter->disconnect_comp_var,
4369 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4370 if (0 == ret)
4371 {
4372 VOS_ASSERT(0);
4373 }
4374 }
4375 }
4376 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4377 {
4378 ret = wait_for_completion_interruptible_timeout(
4379 &pAdapter->disconnect_comp_var,
4380 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4381 if (0 == ret)
4382 {
4383 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004384 }
4385 }
4386
4387 if (HDD_WMM_USER_MODE_NO_QOS ==
4388 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4389 {
4390 /*QoS not enabled in cfg file*/
4391 pRoamProfile->uapsd_mask = 0;
4392 }
4393 else
4394 {
4395 /*QoS enabled, update uapsd mask from cfg file*/
4396 pRoamProfile->uapsd_mask =
4397 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4398 }
4399
4400 pRoamProfile->SSIDs.numOfSSIDs = 1;
4401 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4402 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4403 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4404 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4405 ssid, ssid_len);
4406
4407 if (bssid)
4408 {
4409 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4410 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4411 WNI_CFG_BSSID_LEN);
4412 /* Save BSSID in seperate variable as well, as RoamProfile
4413 BSSID is getting zeroed out in the association process. And in
4414 case of join failure we should send valid BSSID to supplicant
4415 */
4416 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4417 WNI_CFG_BSSID_LEN);
4418 }
4419
4420 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4421 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4422 {
4423 /*set gen ie*/
4424 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4425 /*set auth*/
4426 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4427 }
4428 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4429 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4430 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4431 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4432 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4433 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4434 )
4435 {
4436 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4437 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4438 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4439 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4440 eCSR_AUTH_TYPE_AUTOSWITCH;
4441 pWextState->roamProfile.AuthType.authType[0] =
4442 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4443 }
4444#ifdef FEATURE_WLAN_WAPI
4445 if (pAdapter->wapi_info.nWapiMode)
4446 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004447 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004448 switch (pAdapter->wapi_info.wapiAuthMode)
4449 {
4450 case WAPI_AUTH_MODE_PSK:
4451 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004452 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004453 pAdapter->wapi_info.wapiAuthMode);
4454 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4455 break;
4456 }
4457 case WAPI_AUTH_MODE_CERT:
4458 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004459 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004460 pAdapter->wapi_info.wapiAuthMode);
4461 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4462 break;
4463 }
4464 } // End of switch
4465 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4466 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4467 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004468 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004469 pRoamProfile->AuthType.numEntries = 1;
4470 pRoamProfile->EncryptionType.numEntries = 1;
4471 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4472 pRoamProfile->mcEncryptionType.numEntries = 1;
4473 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4474 }
4475 }
4476#endif /* FEATURE_WLAN_WAPI */
4477 pRoamProfile->csrPersona = pAdapter->device_mode;
4478
Jeff Johnson32d95a32012-09-10 13:15:23 -07004479 if( operatingChannel )
4480 {
4481 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4482 pRoamProfile->ChannelInfo.numOfChannels = 1;
4483 }
4484
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004485 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4486 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4487 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4488 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004489 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4490 */
4491 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4492 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4493 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004494
Jeff Johnson295189b2012-06-20 16:38:30 -07004495 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4496 pAdapter->sessionId, pRoamProfile, &roamId);
4497
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004498 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304499 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4500
4501 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004502 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4503 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4504 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304505 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004506 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304507 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004508
4509 pRoamProfile->ChannelInfo.ChannelList = NULL;
4510 pRoamProfile->ChannelInfo.numOfChannels = 0;
4511
Jeff Johnson295189b2012-06-20 16:38:30 -07004512 }
4513 else
4514 {
4515 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4516 return -EINVAL;
4517 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004518 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004519 return status;
4520}
4521
4522/*
4523 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4524 * This function is used to set the authentication type (OPEN/SHARED).
4525 *
4526 */
4527static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4528 enum nl80211_auth_type auth_type)
4529{
4530 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4531 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4532
4533 ENTER();
4534
4535 /*set authentication type*/
4536 switch (auth_type)
4537 {
4538 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4539 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004540#ifdef WLAN_FEATURE_VOWIFI_11R
4541 case NL80211_AUTHTYPE_FT:
4542#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004543 hddLog(VOS_TRACE_LEVEL_INFO,
4544 "%s: set authentication type to OPEN", __func__);
4545 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4546 break;
4547
4548 case NL80211_AUTHTYPE_SHARED_KEY:
4549 hddLog(VOS_TRACE_LEVEL_INFO,
4550 "%s: set authentication type to SHARED", __func__);
4551 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4552 break;
4553#ifdef FEATURE_WLAN_CCX
4554 case NL80211_AUTHTYPE_NETWORK_EAP:
4555 hddLog(VOS_TRACE_LEVEL_INFO,
4556 "%s: set authentication type to CCKM WPA", __func__);
4557 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4558 break;
4559#endif
4560
4561
4562 default:
4563 hddLog(VOS_TRACE_LEVEL_ERROR,
4564 "%s: Unsupported authentication type %d", __func__,
4565 auth_type);
4566 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4567 return -EINVAL;
4568 }
4569
4570 pWextState->roamProfile.AuthType.authType[0] =
4571 pHddStaCtx->conn_info.authType;
4572 return 0;
4573}
4574
4575/*
4576 * FUNCTION: wlan_hdd_set_akm_suite
4577 * This function is used to set the key mgmt type(PSK/8021x).
4578 *
4579 */
4580static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4581 u32 key_mgmt
4582 )
4583{
4584 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4585 ENTER();
4586
4587 /*set key mgmt type*/
4588 switch(key_mgmt)
4589 {
4590 case WLAN_AKM_SUITE_PSK:
4591 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4592 __func__);
4593 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4594 break;
4595
4596 case WLAN_AKM_SUITE_8021X:
4597 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4598 __func__);
4599 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4600 break;
4601#ifdef FEATURE_WLAN_CCX
4602#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4603#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4604 case WLAN_AKM_SUITE_CCKM:
4605 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4606 __func__);
4607 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4608 break;
4609#endif
4610
4611 default:
4612 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4613 __func__, key_mgmt);
4614 return -EINVAL;
4615
4616 }
4617 return 0;
4618}
4619
4620/*
4621 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4622 * This function is used to set the encryption type
4623 * (NONE/WEP40/WEP104/TKIP/CCMP).
4624 */
4625static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4626 u32 cipher,
4627 bool ucast
4628 )
4629{
4630 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4631 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4632 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4633
4634 ENTER();
4635
4636 if (!cipher)
4637 {
4638 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4639 __func__, cipher);
4640 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4641 }
4642 else
4643 {
4644
4645 /*set encryption method*/
4646 switch (cipher)
4647 {
4648 case IW_AUTH_CIPHER_NONE:
4649 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4650 break;
4651
4652 case WLAN_CIPHER_SUITE_WEP40:
4653 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4654 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4655 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4656 else
4657 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4658 break;
4659
4660 case WLAN_CIPHER_SUITE_WEP104:
4661 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4662 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4663 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4664 else
4665 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4666 break;
4667
4668 case WLAN_CIPHER_SUITE_TKIP:
4669 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4670 break;
4671
4672 case WLAN_CIPHER_SUITE_CCMP:
4673 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4674 break;
4675#ifdef FEATURE_WLAN_WAPI
4676 case WLAN_CIPHER_SUITE_SMS4:
4677 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4678 break;
4679#endif
4680
4681#ifdef FEATURE_WLAN_CCX
4682 case WLAN_CIPHER_SUITE_KRK:
4683 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4684 break;
4685#endif
4686 default:
4687 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4688 __func__, cipher);
4689 return -EOPNOTSUPP;
4690 }
4691 }
4692
4693 if (ucast)
4694 {
4695 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4696 __func__, encryptionType);
4697 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4698 pWextState->roamProfile.EncryptionType.numEntries = 1;
4699 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4700 encryptionType;
4701 }
4702 else
4703 {
4704 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4705 __func__, encryptionType);
4706 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4707 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4708 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4709 }
4710
4711 return 0;
4712}
4713
4714
4715/*
4716 * FUNCTION: wlan_hdd_cfg80211_set_ie
4717 * This function is used to parse WPA/RSN IE's.
4718 */
4719int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4720 u8 *ie,
4721 size_t ie_len
4722 )
4723{
4724 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4725 u8 *genie = ie;
4726 v_U16_t remLen = ie_len;
4727#ifdef FEATURE_WLAN_WAPI
4728 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4729 u16 *tmp;
4730 v_U16_t akmsuiteCount;
4731 int *akmlist;
4732#endif
4733 ENTER();
4734
4735 /* clear previous assocAddIE */
4736 pWextState->assocAddIE.length = 0;
4737 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4738
4739 while (remLen >= 2)
4740 {
4741 v_U16_t eLen = 0;
4742 v_U8_t elementId;
4743 elementId = *genie++;
4744 eLen = *genie++;
4745 remLen -= 2;
4746
4747 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4748 __func__, elementId, eLen);
4749
4750 switch ( elementId )
4751 {
4752 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004753 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 -07004754 {
4755 hddLog(VOS_TRACE_LEVEL_ERROR,
4756 "%s: Invalid WPA IE", __func__);
4757 return -EINVAL;
4758 }
4759 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4760 {
4761 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4762 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4763 __func__, eLen + 2);
4764
4765 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4766 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004767 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4768 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 VOS_ASSERT(0);
4770 return -ENOMEM;
4771 }
4772 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4773 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4774 pWextState->assocAddIE.length += eLen + 2;
4775
4776 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4777 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4778 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4779 }
4780 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4781 {
4782 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4783 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4784 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4785 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4786 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4787 }
4788#ifdef WLAN_FEATURE_P2P
4789 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4790 P2P_OUI_TYPE_SIZE))
4791 /*Consider P2P IE, only for P2P Client */
4792 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4793 {
4794 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4795 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4796 __func__, eLen + 2);
4797
4798 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4799 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004800 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4801 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004802 VOS_ASSERT(0);
4803 return -ENOMEM;
4804 }
4805 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4806 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4807 pWextState->assocAddIE.length += eLen + 2;
4808
4809 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4810 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4811 }
4812#endif
4813#ifdef WLAN_FEATURE_WFD
4814 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4815 WFD_OUI_TYPE_SIZE))
4816 /*Consider WFD IE, only for P2P Client */
4817 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4818 {
4819 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4820 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4821 __func__, eLen + 2);
4822
4823 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4824 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004825 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4826 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004827 VOS_ASSERT(0);
4828 return -ENOMEM;
4829 }
4830 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4831 // WPS IE + P2P IE + WFD IE
4832 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4833 pWextState->assocAddIE.length += eLen + 2;
4834
4835 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4836 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4837 }
4838#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004839 /* Appending HS 2.0 Indication Element in Assiciation Request */
4840 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004841 HS20_OUI_TYPE_SIZE)) )
4842 {
4843 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4844 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4845 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004846
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004847 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4848 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004849 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4850 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004851 VOS_ASSERT(0);
4852 return -ENOMEM;
4853 }
4854 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4855 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004856
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004857 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4858 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4859 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004860
Jeff Johnson295189b2012-06-20 16:38:30 -07004861 break;
4862 case DOT11F_EID_RSN:
4863 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4864 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4865 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4866 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4867 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4868 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004869 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4870 case DOT11F_EID_EXTCAP:
4871 {
4872 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4873 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4874 __func__, eLen + 2);
4875
4876 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4877 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004878 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4879 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004880 VOS_ASSERT(0);
4881 return -ENOMEM;
4882 }
4883 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4884 pWextState->assocAddIE.length += eLen + 2;
4885
4886 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4887 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4888 break;
4889 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004890#ifdef FEATURE_WLAN_WAPI
4891 case WLAN_EID_WAPI:
4892 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4893 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4894 pAdapter->wapi_info.nWapiMode);
4895 tmp = (u16 *)ie;
4896 tmp = tmp + 2; // Skip element Id and Len, Version
4897 akmsuiteCount = WPA_GET_LE16(tmp);
4898 tmp = tmp + 1;
4899 akmlist = (int *)(tmp);
4900 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4901 {
4902 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4903 }
4904 else
4905 {
4906 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4907 VOS_ASSERT(0);
4908 return -EINVAL;
4909 }
4910
4911 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4912 {
4913 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004914 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004915 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4916 }
4917 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4918 {
4919 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004920 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004921 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4922 }
4923 break;
4924#endif
4925 default:
4926 hddLog (VOS_TRACE_LEVEL_ERROR,
4927 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004928 /* when Unknown IE is received we should break and continue
4929 * to the next IE in the buffer instead we were returning
4930 * so changing this to break */
4931 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004932 }
4933 genie += eLen;
4934 remLen -= eLen;
4935 }
4936 EXIT();
4937 return 0;
4938}
4939
4940/*
4941 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4942 * This function is used to initialize the security
4943 * parameters during connect operation.
4944 */
4945int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4946 struct cfg80211_connect_params *req
4947 )
4948{
4949 int status = 0;
4950 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4951 ENTER();
4952
4953 /*set wpa version*/
4954 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4955
4956 if (req->crypto.wpa_versions)
4957 {
4958 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4959 && ( (req->ie_len)
4960 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4961 // Make sure that it is including a WPA IE.
4962 /* Currently NL is putting WPA version 1 even for open,
4963 * since p2p ie is also put in same buffer.
4964 * */
4965 {
4966 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4967 }
4968 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4969 {
4970 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4971 }
4972 }
4973
4974 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4975 pWextState->wpaVersion);
4976
4977 /*set authentication type*/
4978 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4979
4980 if (0 > status)
4981 {
4982 hddLog(VOS_TRACE_LEVEL_ERROR,
4983 "%s: failed to set authentication type ", __func__);
4984 return status;
4985 }
4986
4987 /*set key mgmt type*/
4988 if (req->crypto.n_akm_suites)
4989 {
4990 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4991 if (0 > status)
4992 {
4993 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4994 __func__);
4995 return status;
4996 }
4997 }
4998
4999 /*set pairwise cipher type*/
5000 if (req->crypto.n_ciphers_pairwise)
5001 {
5002 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5003 req->crypto.ciphers_pairwise[0], true);
5004 if (0 > status)
5005 {
5006 hddLog(VOS_TRACE_LEVEL_ERROR,
5007 "%s: failed to set unicast cipher type", __func__);
5008 return status;
5009 }
5010 }
5011 else
5012 {
5013 /*Reset previous cipher suite to none*/
5014 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5015 if (0 > status)
5016 {
5017 hddLog(VOS_TRACE_LEVEL_ERROR,
5018 "%s: failed to set unicast cipher type", __func__);
5019 return status;
5020 }
5021 }
5022
5023 /*set group cipher type*/
5024 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5025 false);
5026
5027 if (0 > status)
5028 {
5029 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5030 __func__);
5031 return status;
5032 }
5033
5034 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5035 if (req->ie_len)
5036 {
5037 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5038 if ( 0 > status)
5039 {
5040 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5041 __func__);
5042 return status;
5043 }
5044 }
5045
5046 /*incase of WEP set default key information*/
5047 if (req->key && req->key_len)
5048 {
5049 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5050 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5051 )
5052 {
5053 if ( IW_AUTH_KEY_MGMT_802_1X
5054 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5055 {
5056 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5057 __func__);
5058 return -EOPNOTSUPP;
5059 }
5060 else
5061 {
5062 u8 key_len = req->key_len;
5063 u8 key_idx = req->key_idx;
5064
5065 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5066 && (CSR_MAX_NUM_KEY > key_idx)
5067 )
5068 {
5069 hddLog(VOS_TRACE_LEVEL_INFO,
5070 "%s: setting default wep key, key_idx = %hu key_len %hu",
5071 __func__, key_idx, key_len);
5072 vos_mem_copy(
5073 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5074 req->key, key_len);
5075 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5076 (u8)key_len;
5077 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5078 }
5079 }
5080 }
5081 }
5082
5083 return status;
5084}
5085
5086/*
5087 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5088 * This function is used to initialize the security
5089 * parameters during connect operation.
5090 */
5091static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5092 struct net_device *ndev,
5093 struct cfg80211_connect_params *req
5094 )
5095{
5096 int status = 0;
5097 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5098 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5099 hdd_context_t *pHddCtx = NULL;
5100
5101 ENTER();
5102
5103 hddLog(VOS_TRACE_LEVEL_INFO,
5104 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5105
5106 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5107 {
5108 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5109 "%s:LOGP in Progress. Ignore!!!", __func__);
5110 return -EAGAIN;
5111 }
5112
5113#ifdef WLAN_BTAMP_FEATURE
5114 //Infra connect not supported when AMP traffic is on.
5115 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5116 {
5117 hddLog(VOS_TRACE_LEVEL_ERROR,
5118 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005119 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005120 }
5121#endif
5122 /*initialise security parameters*/
5123 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5124
5125 if ( 0 > status)
5126 {
5127 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5128 __func__);
5129 return status;
5130 }
5131
5132 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005133 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005134 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5135 (vos_concurrent_sessions_running()))
5136 {
5137 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5138
5139 if (NULL != pVosContext)
5140 {
5141 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5142 if(NULL != pHddCtx)
5143 {
5144 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5145 }
5146 }
5147 }
5148
Mohit Khanna765234a2012-09-11 15:08:35 -07005149 if ( req->channel )
5150 {
5151 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5152 req->ssid_len, req->bssid,
5153 req->channel->hw_value);
5154 }
5155 else
5156 {
5157 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5158 req->ssid_len, req->bssid,
5159 0);
5160 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005161
5162 if (0 > status)
5163 {
5164 //ReEnable BMPS if disabled
5165 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5166 (NULL != pHddCtx))
5167 {
5168 //ReEnable Bmps and Imps back
5169 hdd_enable_bmps_imps(pHddCtx);
5170 }
5171
5172 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5173 return status;
5174 }
5175 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5176 EXIT();
5177 return status;
5178}
5179
5180
5181/*
5182 * FUNCTION: wlan_hdd_cfg80211_disconnect
5183 * This function is used to issue a disconnect request to SME
5184 */
5185static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5186 struct net_device *dev,
5187 u16 reason
5188 )
5189{
5190 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5191 tCsrRoamProfile *pRoamProfile =
5192 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5193 int status = 0;
5194 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5195
5196 ENTER();
5197
5198 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5199 __func__,pAdapter->device_mode);
5200
5201 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5202 __func__, reason);
5203
5204 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5205 {
5206 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5207 "%s:LOGP in Progress. Ignore!!!",__func__);
5208 return -EAGAIN;
5209 }
5210 if (NULL != pRoamProfile)
5211 {
5212 /*issue disconnect request to SME, if station is in connected state*/
5213 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5214 {
5215 eCsrRoamDisconnectReason reasonCode =
5216 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5217 switch(reason)
5218 {
5219 case WLAN_REASON_MIC_FAILURE:
5220 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5221 break;
5222
5223 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5224 case WLAN_REASON_DISASSOC_AP_BUSY:
5225 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5226 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5227 break;
5228
5229 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5230 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5231 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5232 break;
5233
5234 case WLAN_REASON_DEAUTH_LEAVING:
5235 default:
5236 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5237 break;
5238 }
5239 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5240 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5241 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5242
5243 /*issue disconnect*/
5244 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5245 pAdapter->sessionId, reasonCode);
5246
5247 if ( 0 != status)
5248 {
5249 hddLog(VOS_TRACE_LEVEL_ERROR,
5250 "%s csrRoamDisconnect failure, returned %d \n",
5251 __func__, (int)status );
5252 return -EINVAL;
5253 }
5254
5255 wait_for_completion_interruptible_timeout(
5256 &pAdapter->disconnect_comp_var,
5257 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5258
5259
5260 /*stop tx queues*/
5261 netif_tx_disable(dev);
5262 netif_carrier_off(dev);
5263 }
5264 }
5265 else
5266 {
5267 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5268 }
5269
5270 return status;
5271}
5272
5273/*
5274 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5275 * This function is used to initialize the security
5276 * settings in IBSS mode.
5277 */
5278static int wlan_hdd_cfg80211_set_privacy_ibss(
5279 hdd_adapter_t *pAdapter,
5280 struct cfg80211_ibss_params *params
5281 )
5282{
5283 int status = 0;
5284 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5285 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5286 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5287
5288 ENTER();
5289
5290 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5291
5292 if (params->ie_len && ( NULL != params->ie) )
5293 {
5294 if (WLAN_EID_RSN == params->ie[0])
5295 {
5296 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5297 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5298 }
5299 else
5300 {
5301 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5302 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5303 }
5304 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5305
5306 if (0 > status)
5307 {
5308 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5309 __func__);
5310 return status;
5311 }
5312 }
5313
5314 pWextState->roamProfile.AuthType.authType[0] =
5315 pHddStaCtx->conn_info.authType =
5316 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5317
5318 if (params->privacy)
5319 {
5320 /* Security enabled IBSS, At this time there is no information available
5321 * about the security paramters, so initialise the encryption type to
5322 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5323 * The correct security parameters will be updated later in
5324 * wlan_hdd_cfg80211_add_key */
5325 /* Hal expects encryption type to be set inorder
5326 *enable privacy bit in beacons */
5327
5328 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5329 }
5330
5331 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5332 pWextState->roamProfile.EncryptionType.numEntries = 1;
5333 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5334
5335 return status;
5336}
5337
5338/*
5339 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5340 * This function is used to create/join an IBSS
5341 */
5342static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5343 struct net_device *dev,
5344 struct cfg80211_ibss_params *params
5345 )
5346{
5347 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5348 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5349 tCsrRoamProfile *pRoamProfile;
5350 int status;
5351 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5352
5353 ENTER();
5354
5355 hddLog(VOS_TRACE_LEVEL_INFO,
5356 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5357
5358 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5359 {
5360 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5361 "%s:LOGP in Progress. Ignore!!!", __func__);
5362 return -EAGAIN;
5363 }
5364
5365 if (NULL == pWextState)
5366 {
5367 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5368 __func__);
5369 return -EIO;
5370 }
5371
5372 pRoamProfile = &pWextState->roamProfile;
5373
5374 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5375 {
5376 hddLog (VOS_TRACE_LEVEL_ERROR,
5377 "%s Interface type is not set to IBSS \n", __func__);
5378 return -EINVAL;
5379 }
5380
5381 /* Set Channel */
5382 if (NULL != params->channel)
5383 {
5384 u8 channelNum;
5385 if (IEEE80211_BAND_5GHZ == params->channel->band)
5386 {
5387 hddLog(VOS_TRACE_LEVEL_ERROR,
5388 "%s: IBSS join is called with unsupported band %d",
5389 __func__, params->channel->band);
5390 return -EOPNOTSUPP;
5391 }
5392
5393 /* Get channel number */
5394 channelNum =
5395 ieee80211_frequency_to_channel(params->channel->center_freq);
5396
5397 /*TODO: use macro*/
5398 if (14 >= channelNum)
5399 {
5400 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5401 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5402 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5403 int indx;
5404
5405 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5406 validChan, &numChans))
5407 {
5408 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5409 __func__);
5410 return -EOPNOTSUPP;
5411 }
5412
5413 for (indx = 0; indx < numChans; indx++)
5414 {
5415 if (channelNum == validChan[indx])
5416 {
5417 break;
5418 }
5419 }
5420 if (indx >= numChans)
5421 {
5422 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5423 __func__, channelNum);
5424 return -EINVAL;
5425 }
5426 /* Set the Operational Channel */
5427 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5428 channelNum);
5429 pRoamProfile->ChannelInfo.numOfChannels = 1;
5430 pHddStaCtx->conn_info.operationChannel = channelNum;
5431 pRoamProfile->ChannelInfo.ChannelList =
5432 &pHddStaCtx->conn_info.operationChannel;
5433 }
5434 else
5435 {
5436 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5437 __func__, channelNum);
5438 return -EINVAL;
5439 }
5440 }
5441
5442 /* Initialize security parameters */
5443 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5444 if (status < 0)
5445 {
5446 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5447 __func__);
5448 return status;
5449 }
5450
5451 /* Issue connect start */
5452 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005453 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005454
5455 if (0 > status)
5456 {
5457 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5458 return status;
5459 }
5460
5461 return 0;
5462}
5463
5464/*
5465 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5466 * This function is used to leave an IBSS
5467 */
5468static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5469 struct net_device *dev
5470 )
5471{
5472 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5473 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5474 tCsrRoamProfile *pRoamProfile;
5475
5476 ENTER();
5477
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005478 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5479 {
5480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5481 "%s:LOGP in Progress. Ignore!!!", __func__);
5482 return -EAGAIN;
5483 }
5484
Jeff Johnson295189b2012-06-20 16:38:30 -07005485 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5486 if (NULL == pWextState)
5487 {
5488 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5489 __func__);
5490 return -EIO;
5491 }
5492
5493 pRoamProfile = &pWextState->roamProfile;
5494
5495 /* Issue disconnect only if interface type is set to IBSS */
5496 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5497 {
5498 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5499 __func__);
5500 return -EINVAL;
5501 }
5502
5503 /* Issue Disconnect request */
5504 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5505 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5506 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5507
5508 return 0;
5509}
5510
5511/*
5512 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5513 * This function is used to set the phy parameters
5514 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5515 */
5516static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5517 u32 changed)
5518{
5519 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5520 tHalHandle hHal = pHddCtx->hHal;
5521
5522 ENTER();
5523
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005524 if ( pHddCtx->isLogpInProgress )
5525 {
5526 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5527 "%s:LOGP in Progress. Ignore!!!", __func__);
5528 return -EAGAIN;
5529 }
5530
Jeff Johnson295189b2012-06-20 16:38:30 -07005531 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5532 {
5533 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5534 WNI_CFG_RTS_THRESHOLD_STAMAX :
5535 wiphy->rts_threshold;
5536
5537 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5538 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5539 {
5540 hddLog(VOS_TRACE_LEVEL_ERROR,
5541 "%s: Invalid RTS Threshold value %hu",
5542 __func__, rts_threshold);
5543 return -EINVAL;
5544 }
5545
5546 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5547 rts_threshold, ccmCfgSetCallback,
5548 eANI_BOOLEAN_TRUE))
5549 {
5550 hddLog(VOS_TRACE_LEVEL_ERROR,
5551 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5552 __func__, rts_threshold);
5553 return -EIO;
5554 }
5555
5556 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5557 rts_threshold);
5558 }
5559
5560 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5561 {
5562 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5563 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5564 wiphy->frag_threshold;
5565
5566 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5567 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5568 {
5569 hddLog(VOS_TRACE_LEVEL_ERROR,
5570 "%s: Invalid frag_threshold value %hu", __func__,
5571 frag_threshold);
5572 return -EINVAL;
5573 }
5574
5575 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5576 frag_threshold, ccmCfgSetCallback,
5577 eANI_BOOLEAN_TRUE))
5578 {
5579 hddLog(VOS_TRACE_LEVEL_ERROR,
5580 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5581 __func__, frag_threshold);
5582 return -EIO;
5583 }
5584
5585 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5586 frag_threshold);
5587 }
5588
5589 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5590 || (changed & WIPHY_PARAM_RETRY_LONG))
5591 {
5592 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5593 wiphy->retry_short :
5594 wiphy->retry_long;
5595
5596 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5597 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5598 {
5599 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5600 __func__, retry_value);
5601 return -EINVAL;
5602 }
5603
5604 if (changed & WIPHY_PARAM_RETRY_SHORT)
5605 {
5606 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5607 retry_value, ccmCfgSetCallback,
5608 eANI_BOOLEAN_TRUE))
5609 {
5610 hddLog(VOS_TRACE_LEVEL_ERROR,
5611 "%s: ccmCfgSetInt failed for long retry count %hu",
5612 __func__, retry_value);
5613 return -EIO;
5614 }
5615 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5616 __func__, retry_value);
5617 }
5618 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5619 {
5620 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5621 retry_value, ccmCfgSetCallback,
5622 eANI_BOOLEAN_TRUE))
5623 {
5624 hddLog(VOS_TRACE_LEVEL_ERROR,
5625 "%s: ccmCfgSetInt failed for short retry count %hu",
5626 __func__, retry_value);
5627 return -EIO;
5628 }
5629 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5630 __func__, retry_value);
5631 }
5632 }
5633
5634 return 0;
5635}
5636
5637/*
5638 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5639 * This function is used to set the txpower
5640 */
5641static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5642#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5643 enum tx_power_setting type,
5644#else
5645 enum nl80211_tx_power_setting type,
5646#endif
5647 int dbm)
5648{
5649 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5650 tHalHandle hHal = pHddCtx->hHal;
5651 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5652 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5653
5654 ENTER();
5655
5656 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5657 dbm, ccmCfgSetCallback,
5658 eANI_BOOLEAN_TRUE))
5659 {
5660 hddLog(VOS_TRACE_LEVEL_ERROR,
5661 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5662 return -EIO;
5663 }
5664
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005665 if ( pHddCtx->isLogpInProgress )
5666 {
5667 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5668 "%s:LOGP in Progress. Ignore!!!", __func__);
5669 return -EAGAIN;
5670 }
5671
Jeff Johnson295189b2012-06-20 16:38:30 -07005672 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5673 dbm);
5674
5675 switch(type)
5676 {
5677 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5678 /* Fall through */
5679 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5680 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5681 {
5682 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5683 __func__);
5684 return -EIO;
5685 }
5686 break;
5687 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5688 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5689 __func__);
5690 return -EOPNOTSUPP;
5691 break;
5692 default:
5693 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5694 __func__, type);
5695 return -EIO;
5696 }
5697
5698 return 0;
5699}
5700
5701/*
5702 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5703 * This function is used to read the txpower
5704 */
5705static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5706{
5707
5708 hdd_adapter_t *pAdapter;
5709 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5710
Jeff Johnsone7245742012-09-05 17:12:55 -07005711 ENTER();
5712
Jeff Johnson295189b2012-06-20 16:38:30 -07005713 if (NULL == pHddCtx)
5714 {
5715 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5716 *dbm = 0;
5717 return -ENOENT;
5718 }
5719
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005720 if ( pHddCtx->isLogpInProgress )
5721 {
5722 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5723 "%s:LOGP in Progress. Ignore!!!", __func__);
5724 return -EAGAIN;
5725 }
5726
Jeff Johnson295189b2012-06-20 16:38:30 -07005727 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5728 if (NULL == pAdapter)
5729 {
5730 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5731 return -ENOENT;
5732 }
5733
5734 wlan_hdd_get_classAstats(pAdapter);
5735 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5736
Jeff Johnsone7245742012-09-05 17:12:55 -07005737 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005738 return 0;
5739}
5740
5741static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5742 u8* mac, struct station_info *sinfo)
5743{
5744 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5745 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5746 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5747 tANI_U8 rate_flags;
5748
5749 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5750 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5751 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5752
5753 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5754 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5755 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5756 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5757 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5758 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5759 tANI_U16 maxRate = 0;
5760 tANI_U16 myRate;
5761 tANI_U16 currentRate = 0;
5762 tANI_U8 maxSpeedMCS = 0;
5763 tANI_U8 maxMCSIdx = 0;
5764 tANI_U8 rateFlag = 1;
5765 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005766 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005767
Jeff Johnsone7245742012-09-05 17:12:55 -07005768 ENTER();
5769
Jeff Johnson295189b2012-06-20 16:38:30 -07005770 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5771 (0 == ssidlen))
5772 {
5773 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5774 " Invalid ssidlen, %d", __func__, ssidlen);
5775 /*To keep GUI happy*/
5776 return 0;
5777 }
5778
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005779 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5780 {
5781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5782 "%s:LOGP in Progress. Ignore!!!", __func__);
5783 return -EAGAIN;
5784 }
5785
Jeff Johnson295189b2012-06-20 16:38:30 -07005786 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5787 sinfo->filled |= STATION_INFO_SIGNAL;
5788
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005789 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005790 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5791
5792 //convert to the UI units of 100kbps
5793 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5794
5795#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005796 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 -07005797 sinfo->signal,
5798 pCfg->reportMaxLinkSpeed,
5799 myRate,
5800 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005801 (int) pCfg->linkSpeedRssiMid,
5802 (int) pCfg->linkSpeedRssiLow,
5803 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005804#endif //LINKSPEED_DEBUG_ENABLED
5805
5806 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5807 {
5808 // we do not want to necessarily report the current speed
5809 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5810 {
5811 // report the max possible speed
5812 rssidx = 0;
5813 }
5814 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5815 {
5816 // report the max possible speed with RSSI scaling
5817 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5818 {
5819 // report the max possible speed
5820 rssidx = 0;
5821 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005822 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005823 {
5824 // report middle speed
5825 rssidx = 1;
5826 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005827 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5828 {
5829 // report middle speed
5830 rssidx = 2;
5831 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005832 else
5833 {
5834 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005835 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005836 }
5837 }
5838 else
5839 {
5840 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5841 hddLog(VOS_TRACE_LEVEL_ERROR,
5842 "%s: Invalid value for reportMaxLinkSpeed: %u",
5843 __func__, pCfg->reportMaxLinkSpeed);
5844 rssidx = 0;
5845 }
5846
5847 maxRate = 0;
5848
5849 /* Get Basic Rate Set */
5850 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5851 for (i = 0; i < ORLeng; i++)
5852 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005853 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005854 {
5855 /* Validate Rate Set */
5856 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5857 {
5858 currentRate = supported_data_rate[j].supported_rate[rssidx];
5859 break;
5860 }
5861 }
5862 /* Update MAX rate */
5863 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5864 }
5865
5866 /* Get Extended Rate Set */
5867 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5868 for (i = 0; i < ERLeng; i++)
5869 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005870 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005871 {
5872 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5873 {
5874 currentRate = supported_data_rate[j].supported_rate[rssidx];
5875 break;
5876 }
5877 }
5878 /* Update MAX rate */
5879 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5880 }
5881
5882 /* Get MCS Rate Set -- but only if we are connected at MCS
5883 rates or if we are always reporting max speed or if we have
5884 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005885 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 {
5887 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5888 rateFlag = 0;
5889 if (rate_flags & eHAL_TX_RATE_HT40)
5890 {
5891 rateFlag |= 1;
5892 }
5893 if (rate_flags & eHAL_TX_RATE_SGI)
5894 {
5895 rateFlag |= 2;
5896 }
5897
5898 for (i = 0; i < MCSLeng; i++)
5899 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005900 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5901 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 {
5903 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5904 {
5905 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5906 break;
5907 }
5908 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005909 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005910 {
5911 maxRate = currentRate;
5912 maxSpeedMCS = 1;
5913 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5914 }
5915 }
5916 }
5917
5918 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005919 if (((maxRate < myRate) && (0 == rssidx)) ||
5920 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005921 {
5922 maxRate = myRate;
5923 if (rate_flags & eHAL_TX_RATE_LEGACY)
5924 {
5925 maxSpeedMCS = 0;
5926 }
5927 else
5928 {
5929 maxSpeedMCS = 1;
5930 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5931 }
5932 }
5933
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005934 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005935 {
5936 sinfo->txrate.legacy = maxRate;
5937#ifdef LINKSPEED_DEBUG_ENABLED
5938 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5939#endif //LINKSPEED_DEBUG_ENABLED
5940 }
5941 else
5942 {
5943 sinfo->txrate.mcs = maxMCSIdx;
5944 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5945 if (rate_flags & eHAL_TX_RATE_SGI)
5946 {
5947 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5948 }
5949 if (rate_flags & eHAL_TX_RATE_HT40)
5950 {
5951 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5952 }
5953#ifdef LINKSPEED_DEBUG_ENABLED
5954 pr_info("Reporting MCS rate %d flags %x\n",
5955 sinfo->txrate.mcs,
5956 sinfo->txrate.flags );
5957#endif //LINKSPEED_DEBUG_ENABLED
5958 }
5959 }
5960 else
5961 {
5962 // report current rate instead of max rate
5963
5964 if (rate_flags & eHAL_TX_RATE_LEGACY)
5965 {
5966 //provide to the UI in units of 100kbps
5967 sinfo->txrate.legacy = myRate;
5968#ifdef LINKSPEED_DEBUG_ENABLED
5969 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5970#endif //LINKSPEED_DEBUG_ENABLED
5971 }
5972 else
5973 {
5974 //must be MCS
5975 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5976 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5977 if (rate_flags & eHAL_TX_RATE_SGI)
5978 {
5979 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5980 }
5981 if (rate_flags & eHAL_TX_RATE_HT40)
5982 {
5983 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5984 }
5985#ifdef LINKSPEED_DEBUG_ENABLED
5986 pr_info("Reporting actual MCS rate %d flags %x\n",
5987 sinfo->txrate.mcs,
5988 sinfo->txrate.flags );
5989#endif //LINKSPEED_DEBUG_ENABLED
5990 }
5991 }
5992 sinfo->filled |= STATION_INFO_TX_BITRATE;
5993
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005994 sinfo->tx_packets =
5995 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5996 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5997 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5998 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5999
6000 sinfo->tx_retries =
6001 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6002 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6003 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6004 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6005
6006 sinfo->tx_failed =
6007 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6008 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6009 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6010 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6011
6012 sinfo->filled |=
6013 STATION_INFO_TX_PACKETS |
6014 STATION_INFO_TX_RETRIES |
6015 STATION_INFO_TX_FAILED;
6016
6017 EXIT();
6018 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006019}
6020
6021static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6022 struct net_device *dev, bool mode, v_SINT_t timeout)
6023{
6024 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6025 VOS_STATUS vos_status;
6026
Jeff Johnsone7245742012-09-05 17:12:55 -07006027 ENTER();
6028
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 if (NULL == pAdapter)
6030 {
6031 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6032 return -ENODEV;
6033 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006034 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6035 {
6036 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6037 "%s:LOGP in Progress. Ignore!!!", __func__);
6038 return -EAGAIN;
6039 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006040
6041 /**The get power cmd from the supplicant gets updated by the nl only
6042 *on successful execution of the function call
6043 *we are oppositely mapped w.r.t mode in the driver
6044 **/
6045 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6046
Jeff Johnsone7245742012-09-05 17:12:55 -07006047 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006048 if (VOS_STATUS_E_FAILURE == vos_status)
6049 {
6050 return -EINVAL;
6051 }
6052 return 0;
6053}
6054
6055
6056#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6057static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6058 struct net_device *netdev,
6059 u8 key_index)
6060{
Jeff Johnsone7245742012-09-05 17:12:55 -07006061 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006062 return 0;
6063}
6064#endif //LINUX_VERSION_CODE
6065
6066#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6067static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6068 struct net_device *dev,
6069 struct ieee80211_txq_params *params)
6070{
Jeff Johnsone7245742012-09-05 17:12:55 -07006071 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006072 return 0;
6073}
6074#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6075static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6076 struct ieee80211_txq_params *params)
6077{
Jeff Johnsone7245742012-09-05 17:12:55 -07006078 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006079 return 0;
6080}
6081#endif //LINUX_VERSION_CODE
6082
6083static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6084 struct net_device *dev, u8 *mac)
6085{
6086 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006087 VOS_STATUS vos_status;
6088 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006089
Jeff Johnsone7245742012-09-05 17:12:55 -07006090 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006091 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6092 {
6093 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6094 return -EINVAL;
6095 }
6096
6097 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6098 {
6099 hddLog( LOGE,
6100 "%s: Wlan Load/Unload is in progress", __func__);
6101 return -EBUSY;
6102 }
6103
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006104 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6105 {
6106 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6107 "%s:LOGP in Progress. Ignore!!!", __func__);
6108 return -EAGAIN;
6109 }
6110
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6112#ifdef WLAN_FEATURE_P2P
6113 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6114#endif
6115 )
6116 {
6117 if( NULL == mac )
6118 {
6119 v_U16_t i;
6120 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6121 {
6122 if(pAdapter->aStaInfo[i].isUsed)
6123 {
6124 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6125 hddLog(VOS_TRACE_LEVEL_INFO,
6126 "%s: Delete STA with MAC::"
6127 "%02x:%02x:%02x:%02x:%02x:%02x",
6128 __func__,
6129 macAddr[0], macAddr[1], macAddr[2],
6130 macAddr[3], macAddr[4], macAddr[5]);
6131 hdd_softap_sta_deauth(pAdapter, macAddr);
6132 }
6133 }
6134 }
6135 else
6136 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006137
6138 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6139 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6140 {
6141 hddLog(VOS_TRACE_LEVEL_INFO,
6142 "%s: Skip this DEL STA as this is not used::"
6143 "%02x:%02x:%02x:%02x:%02x:%02x",
6144 __func__,
6145 mac[0], mac[1], mac[2],
6146 mac[3], mac[4], mac[5]);
6147 return -ENOENT;
6148 }
6149
6150 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6151 {
6152 hddLog(VOS_TRACE_LEVEL_INFO,
6153 "%s: Skip this DEL STA as deauth is in progress::"
6154 "%02x:%02x:%02x:%02x:%02x:%02x",
6155 __func__,
6156 mac[0], mac[1], mac[2],
6157 mac[3], mac[4], mac[5]);
6158 return -ENOENT;
6159 }
6160
6161 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6162
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 hddLog(VOS_TRACE_LEVEL_INFO,
6164 "%s: Delete STA with MAC::"
6165 "%02x:%02x:%02x:%02x:%02x:%02x",
6166 __func__,
6167 mac[0], mac[1], mac[2],
6168 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006169
6170 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6171 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6172 {
6173 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6174 hddLog(VOS_TRACE_LEVEL_INFO,
6175 "%s: STA removal failed for ::"
6176 "%02x:%02x:%02x:%02x:%02x:%02x",
6177 __func__,
6178 mac[0], mac[1], mac[2],
6179 mac[3], mac[4], mac[5]);
6180 return -ENOENT;
6181 }
6182
Jeff Johnson295189b2012-06-20 16:38:30 -07006183 }
6184 }
6185
6186 EXIT();
6187
6188 return 0;
6189}
6190
6191static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6192 struct net_device *dev, u8 *mac, struct station_parameters *params)
6193{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006194#ifdef FEATURE_WLAN_TDLS
6195 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6196 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6197 u32 mask, set;
6198 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006199 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006200
6201 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6202 {
6203 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6204 "Invalid arguments");
6205 return -EINVAL;
6206 }
6207
6208 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6209 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6210 {
6211 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6212 "TDLS Disabled in INI OR not enabled in FW.\
6213 Cannot process TDLS commands \n");
6214 return -ENOTSUPP;
6215 }
6216
6217 mask = params->sta_flags_mask;
6218
6219 set = params->sta_flags_set;
6220
6221
6222 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6223 "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
6224
6225 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6226 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6228 "Add TDLS peer");
6229
6230
6231 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6232 pAdapter->sessionId, mac);
6233
6234 if (VOS_STATUS_SUCCESS != status) {
6235 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6236 "%s: sme_AddTdlsPeerSta failed!", __func__);
6237 }
6238 }
6239 }
6240#endif
6241
Jeff Johnson295189b2012-06-20 16:38:30 -07006242 return 0;
6243}
6244
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006245
6246#ifdef FEATURE_WLAN_LFR
6247static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006248 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006249{
6250#define MAX_PMKSAIDS_IN_CACHE 8
6251 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006252 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006253 tANI_U32 j=0;
6254 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6255 tHalHandle halHandle;
6256 eHalStatus result;
6257 tANI_U8 BSSIDMatched = 0;
6258
Jeff Johnsone7245742012-09-05 17:12:55 -07006259 ENTER();
6260
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006261 // Validate pAdapter
6262 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6263 {
6264 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6265 return -EINVAL;
6266 }
6267
6268 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6269 {
6270 hddLog( LOGE,
6271 "%s: Wlan Load/Unload is in progress", __func__);
6272 return -EBUSY;
6273 }
6274
6275 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6276 {
6277 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6278 "%s:LOGP in Progress. Ignore!!!", __func__);
6279 return -EAGAIN;
6280 }
6281
6282 // Retrieve halHandle
6283 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6284
6285 for (j = 0; j < i; j++)
6286 {
6287 if(vos_mem_compare(PMKIDCache[j].BSSID,
6288 pmksa->bssid, WNI_CFG_BSSID_LEN))
6289 {
6290 /* BSSID matched previous entry. Overwrite it. */
6291 BSSIDMatched = 1;
6292 vos_mem_copy(PMKIDCache[j].BSSID,
6293 pmksa->bssid, WNI_CFG_BSSID_LEN);
6294 vos_mem_copy(PMKIDCache[j].PMKID,
6295 pmksa->pmkid,
6296 CSR_RSN_PMKID_SIZE);
6297 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006298 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006299 dump_bssid(pmksa->bssid);
6300 dump_pmkid(halHandle, pmksa->pmkid);
6301 break;
6302 }
6303 }
6304
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006305 /* Check we compared all entries,if then take the first slot now */
6306 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6307
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006308 if (!BSSIDMatched)
6309 {
6310 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6311 vos_mem_copy(PMKIDCache[i].BSSID,
6312 pmksa->bssid, ETHER_ADDR_LEN);
6313 vos_mem_copy(PMKIDCache[i].PMKID,
6314 pmksa->pmkid,
6315 CSR_RSN_PMKID_SIZE);
6316 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006317 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006318 dump_bssid(pmksa->bssid);
6319 dump_pmkid(halHandle, pmksa->pmkid);
6320 // Increment the HDD Local Cache index
6321 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6322 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6323 }
6324
6325
6326 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6327 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006328 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006329 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006330 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006331 // Finally set the PMKSA ID Cache in CSR
6332 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6333 PMKIDCache,
6334 i );
6335 return 0;
6336}
6337
6338
6339static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006340 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006341{
Jeff Johnsone7245742012-09-05 17:12:55 -07006342 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006343 // TODO: Implement this later.
6344 return 0;
6345}
6346
6347static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6348{
Jeff Johnsone7245742012-09-05 17:12:55 -07006349 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006350 // TODO: Implement this later.
6351 return 0;
6352}
6353#endif
6354
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006355#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6356static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6357 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6358{
6359 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6360 hdd_station_ctx_t *pHddStaCtx;
6361
6362 if (NULL == pAdapter)
6363 {
6364 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6365 return -ENODEV;
6366 }
6367
6368 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6369
6370 // Added for debug on reception of Re-assoc Req.
6371 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6372 {
6373 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6374 ftie->ie_len);
6375 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6376 }
6377
6378#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6379 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6380 ftie->ie_len);
6381#endif
6382
6383 // Pass the received FT IEs to SME
6384 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6385 ftie->ie_len);
6386 return 0;
6387}
6388#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006389
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006390#ifdef FEATURE_WLAN_TDLS
6391static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6392 u8 *peer, u8 action_code, u8 dialog_token,
6393 u16 status_code, const u8 *buf, size_t len)
6394{
6395
6396 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6397 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6398 u8 *buf_1;
6399 size_t len_1 = len;
6400 u8 peerMac[6];
6401 VOS_STATUS status;
6402
6403 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6404 {
6405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6406 "Invalid arguments");
6407 return -EINVAL;
6408 }
6409
6410 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6411 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6412 {
6413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6414 "TDLS Disabled in INI OR not enabled in FW.\
6415 Cannot process TDLS commands \n");
6416 return -ENOTSUPP;
6417 }
6418 vos_mem_copy( peerMac, peer, 6);
6419
6420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6421 "Request to send TDLS management: action = %d, status = %d, \
Ng Chilamfc416462012-12-27 17:26:52 -08006422 len = %d", action_code, status_code, len);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006423
6424 buf_1 = vos_mem_malloc(len);
6425 if(buf_1 == NULL) {
6426 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6427 "%s: malloc failed!", __func__);
6428 return -ENOMEM;
6429 }
6430 vos_mem_copy(buf_1, buf, len);
6431
6432 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6433 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6434
6435 if (VOS_STATUS_SUCCESS != status) {
6436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6437 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6438 }
6439
6440 vos_mem_free(buf_1);
6441
6442 return 0;
6443}
6444
6445static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6446 u8 *peer, enum nl80211_tdls_operation oper)
6447{
6448 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6449 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6450
6451 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6452 {
6453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6454 "Invalid arguments");
6455 return -EINVAL;
6456 }
6457
6458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6459 "Request for TDLS oper: %d", (int)oper);
6460
6461 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6462 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6463 {
6464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6465 "TDLS Disabled in INI OR not enabled in FW.\
6466 Cannot process TDLS commands \n");
6467 return -ENOTSUPP;
6468 }
6469
6470 switch (oper) {
6471 case NL80211_TDLS_ENABLE_LINK:
6472 {
6473 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6474 v_U8_t my_peer[6];
6475 v_U8_t ucSTAId;
6476 VOS_STATUS status;
6477
6478 if (peer) {
6479 vos_mem_copy(my_peer, peer, 6);
6480 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6481
6482 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6483 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6484 __func__, peer[0], peer[1],
6485 peer[2], peer[3],
6486 peer[4], peer[5] );
6487
6488 if (-1 == ucSTAId ) {
6489 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
6490 return 0;
6491 }
6492
6493 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6494 WLANTL_STA_AUTHENTICATED );
6495
6496 if (0 != status) {
6497 hddLog(VOS_TRACE_LEVEL_ERROR,
6498 "%s: WLANTL_ChangeSTAState failed, returned %d",
6499 __func__, status);
6500 return status;
6501 }
6502 } else {
6503 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6504 }
6505 }
6506 break;
6507 case NL80211_TDLS_DISABLE_LINK:
6508 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6509 pAdapter->sessionId, peer );
6510 return 0;
6511 case NL80211_TDLS_TEARDOWN:
6512 case NL80211_TDLS_SETUP:
6513 case NL80211_TDLS_DISCOVERY_REQ:
6514 /* We don't support in-driver setup/teardown/discovery */
6515 return -ENOTSUPP;
6516 default:
6517 return -ENOTSUPP;
6518 }
6519 return 0;
6520}
6521#endif
6522
Jeff Johnson295189b2012-06-20 16:38:30 -07006523/* cfg80211_ops */
6524static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6525{
6526 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6527 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6528 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6529 .change_station = wlan_hdd_change_station,
6530#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6531 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6532 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6533 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006534#else
6535 .start_ap = wlan_hdd_cfg80211_start_ap,
6536 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6537 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006538#endif
6539 .change_bss = wlan_hdd_cfg80211_change_bss,
6540 .add_key = wlan_hdd_cfg80211_add_key,
6541 .get_key = wlan_hdd_cfg80211_get_key,
6542 .del_key = wlan_hdd_cfg80211_del_key,
6543 .set_default_key = wlan_hdd_cfg80211_set_default_key,
6544 .set_channel = wlan_hdd_cfg80211_set_channel,
6545 .scan = wlan_hdd_cfg80211_scan,
6546 .connect = wlan_hdd_cfg80211_connect,
6547 .disconnect = wlan_hdd_cfg80211_disconnect,
6548 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6549 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6550 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6551 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6552 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6553#ifdef WLAN_FEATURE_P2P
6554 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6555 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6556 .mgmt_tx = wlan_hdd_action,
6557#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6558 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6559 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6560 .set_txq_params = wlan_hdd_set_txq_params,
6561#endif
6562#endif
6563 .get_station = wlan_hdd_cfg80211_get_station,
6564 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6565 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006566 .add_station = wlan_hdd_cfg80211_add_station,
6567#ifdef FEATURE_WLAN_LFR
6568 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6569 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6570 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6571#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006572#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6573 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6574#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006575#ifdef FEATURE_WLAN_TDLS
6576 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6577 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6578#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006579};
6580
6581#endif // CONFIG_CFG80211