blob: f0188100bf3f1e5d3582c3c6a9754fda9dea4ea6 [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 {
Ng Chilamfc416462012-12-27 17:26:52 -08001426 if(1 != pHddCtx->is_dynamic_channel_range_set)
1427 {
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001428 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1429 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 }
Ng Chilamfc416462012-12-27 17:26:52 -08001432
1433 pHddCtx->is_dynamic_channel_range_set = 0;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001434 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001435 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001436 else
1437 {
1438 pConfig->ieee80211d = 0;
1439 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001440 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001441 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001442 {
1443 pConfig->ieee80211d = 0;
1444 }
1445 pConfig->authType = eSAP_AUTO_SWITCH;
1446
1447 capab_info = pMgmt_frame->u.beacon.capab_info;
1448
1449 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1450 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1451
1452 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1453
1454 /*Set wps station to configured*/
1455 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1456
1457 if(pIe)
1458 {
1459 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1460 {
1461 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1462 return -EINVAL;
1463 }
1464 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1465 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001466 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001467 /* Check 15 bit of WPS IE as it contain information for wps state
1468 * WPS state
1469 */
1470 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1471 {
1472 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1473 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1474 {
1475 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1476 }
1477 }
1478 }
1479 else
1480 {
1481 pConfig->wps_state = SAP_WPS_DISABLED;
1482 }
1483 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1484
1485 pConfig->RSNWPAReqIELength = 0;
1486 pConfig->pRSNWPAReqIE = NULL;
1487 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1488 WLAN_EID_RSN);
1489 if(pIe && pIe[1])
1490 {
1491 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1492 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1493 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1494 /* The actual processing may eventually be more extensive than
1495 * this. Right now, just consume any PMKIDs that are sent in
1496 * by the app.
1497 * */
1498 status = hdd_softap_unpackIE(
1499 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1500 &RSNEncryptType,
1501 &mcRSNEncryptType,
1502 &RSNAuthType,
1503 pConfig->pRSNWPAReqIE[1]+2,
1504 pConfig->pRSNWPAReqIE );
1505
1506 if( VOS_STATUS_SUCCESS == status )
1507 {
1508 /* Now copy over all the security attributes you have
1509 * parsed out
1510 * */
1511 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1512 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1513 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1514 = RSNEncryptType;
1515 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1516 "EncryptionType = %d mcEncryptionType = %d\n"),
1517 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1518 }
1519 }
1520
1521 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1522 pBeacon->tail, pBeacon->tail_len);
1523
1524 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1525 {
1526 if (pConfig->pRSNWPAReqIE)
1527 {
1528 /*Mixed mode WPA/WPA2*/
1529 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1530 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1531 }
1532 else
1533 {
1534 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1535 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1536 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1537 status = hdd_softap_unpackIE(
1538 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1539 &RSNEncryptType,
1540 &mcRSNEncryptType,
1541 &RSNAuthType,
1542 pConfig->pRSNWPAReqIE[1]+2,
1543 pConfig->pRSNWPAReqIE );
1544
1545 if( VOS_STATUS_SUCCESS == status )
1546 {
1547 /* Now copy over all the security attributes you have
1548 * parsed out
1549 * */
1550 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1551 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1552 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1553 = RSNEncryptType;
1554 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1555 "EncryptionType = %d mcEncryptionType = %d\n"),
1556 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1557 }
1558 }
1559 }
1560
1561 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1562
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001563#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001564 if (params->ssid != NULL)
1565 {
1566 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1567 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1568 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1569 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1570 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001571#else
1572 if (ssid != NULL)
1573 {
1574 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1575 pConfig->SSIDinfo.ssid.length = ssid_len;
1576 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1577 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1578 }
1579#endif
1580
Jeff Johnson295189b2012-06-20 16:38:30 -07001581 vos_mem_copy(pConfig->self_macaddr.bytes,
1582 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1583
1584 /* default value */
1585 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1586 pConfig->num_accept_mac = 0;
1587 pConfig->num_deny_mac = 0;
1588
1589 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1590 pBeacon->tail, pBeacon->tail_len);
1591
1592 /* pIe for black list is following form:
1593 type : 1 byte
1594 length : 1 byte
1595 OUI : 4 bytes
1596 acl type : 1 byte
1597 no of mac addr in black list: 1 byte
1598 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1599 */
1600 if ((pIe != NULL) && (pIe[1] != 0))
1601 {
1602 pConfig->SapMacaddr_acl = pIe[6];
1603 pConfig->num_deny_mac = pIe[7];
1604 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1605 pIe[6], pIe[7]);
1606 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1607 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1608 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1609 for (i = 0; i < pConfig->num_deny_mac; i++)
1610 {
1611 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1612 acl_entry++;
1613 }
1614 }
1615 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1616 pBeacon->tail, pBeacon->tail_len);
1617
1618 /* pIe for white list is following form:
1619 type : 1 byte
1620 length : 1 byte
1621 OUI : 4 bytes
1622 acl type : 1 byte
1623 no of mac addr in white list: 1 byte
1624 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1625 */
1626 if ((pIe != NULL) && (pIe[1] != 0))
1627 {
1628 pConfig->SapMacaddr_acl = pIe[6];
1629 pConfig->num_accept_mac = pIe[7];
1630 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1631 pIe[6], pIe[7]);
1632 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1633 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1634 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1635 for (i = 0; i < pConfig->num_accept_mac; i++)
1636 {
1637 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1638 acl_entry++;
1639 }
1640 }
1641 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1642
Jeff Johnsone7245742012-09-05 17:12:55 -07001643#ifdef WLAN_FEATURE_11AC
1644 if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1645 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1646 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) )
1647 {
1648 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1649 }
1650#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301651
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001652 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1653 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001654 // ht_capab is not what the name conveys,this is used for protection bitmap
1655 pConfig->ht_capab =
1656 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1657
1658 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1659 {
1660 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1661 return -EINVAL;
1662 }
1663
1664 //Uapsd Enabled Bit
1665 pConfig->UapsdEnable =
1666 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1667 //Enable OBSS protection
1668 pConfig->obssProtEnabled =
1669 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1670
1671 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1672 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1673 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1674 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1675 (int)pConfig->channel);
1676 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1677 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1678 pConfig->authType);
1679 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1680 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1681 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1682 pConfig->protEnabled, pConfig->obssProtEnabled);
1683
1684 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1685 {
1686 //Bss already started. just return.
1687 //TODO Probably it should update some beacon params.
1688 hddLog( LOGE, "Bss Already started...Ignore the request");
1689 EXIT();
1690 return 0;
1691 }
1692
1693 pConfig->persona = pHostapdAdapter->device_mode;
1694
1695 pSapEventCallback = hdd_hostapd_SAPEventCB;
1696 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1697 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1698 {
1699 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1700 return -EINVAL;
1701 }
1702
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001703 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1705
1706 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1707
1708 if (!VOS_IS_STATUS_SUCCESS(status))
1709 {
1710 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1711 ("ERROR: HDD vos wait for single_event failed!!\n"));
1712 VOS_ASSERT(0);
1713 }
1714
1715 //Succesfully started Bss update the state bit.
1716 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1717
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001718#ifdef WLAN_FEATURE_P2P_DEBUG
1719 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1720 {
1721 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1722 {
1723 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1724 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001725 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001726 }
1727 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1728 {
1729 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1730 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001731 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001732 }
1733 }
1734#endif
1735
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 pHostapdState->bCommit = TRUE;
1737 EXIT();
1738
1739 return 0;
1740}
1741
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001742#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001743static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1744 struct net_device *dev,
1745 struct beacon_parameters *params)
1746{
1747 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1748 int status=VOS_STATUS_SUCCESS;
1749
1750 ENTER();
1751
1752 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1753
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001754 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1755 {
1756 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1757 "%s:LOGP in Progress. Ignore!!!", __func__);
1758 return -EAGAIN;
1759 }
1760
Jeff Johnson295189b2012-06-20 16:38:30 -07001761 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1762#ifdef WLAN_FEATURE_P2P
1763 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1764#endif
1765 )
1766 {
1767 beacon_data_t *old,*new;
1768
1769 old = pAdapter->sessionCtx.ap.beacon;
1770
1771 if (old)
1772 return -EALREADY;
1773
1774 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1775
1776 if(status != VOS_STATUS_SUCCESS)
1777 {
1778 hddLog(VOS_TRACE_LEVEL_FATAL,
1779 "%s:Error!!! Allocating the new beacon\n",__func__);
1780 return -EINVAL;
1781 }
1782
1783 pAdapter->sessionCtx.ap.beacon = new;
1784
1785 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1786 }
1787
1788 EXIT();
1789 return status;
1790}
1791
1792static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1793 struct net_device *dev,
1794 struct beacon_parameters *params)
1795{
1796 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1797 int status=VOS_STATUS_SUCCESS;
1798
1799 ENTER();
1800
1801 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1802 __func__,pAdapter->device_mode);
1803
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001804 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1805 {
1806 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1807 "%s:LOGP in Progress. Ignore!!!", __func__);
1808 return -EAGAIN;
1809 }
1810
Jeff Johnson295189b2012-06-20 16:38:30 -07001811 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1812#ifdef WLAN_FEATURE_P2P
1813 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1814#endif
1815 )
1816 {
1817 beacon_data_t *old,*new;
1818
1819 old = pAdapter->sessionCtx.ap.beacon;
1820
1821 if (!old)
1822 return -ENOENT;
1823
1824 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1825
1826 if(status != VOS_STATUS_SUCCESS) {
1827 hddLog(VOS_TRACE_LEVEL_FATAL,
1828 "%s: Error!!! Allocating the new beacon\n",__func__);
1829 return -EINVAL;
1830 }
1831
1832 pAdapter->sessionCtx.ap.beacon = new;
1833
1834 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1835 }
1836
1837 EXIT();
1838 return status;
1839}
1840
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001841#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1842
1843#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001844static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1845 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001846#else
1847static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1848 struct net_device *dev)
1849#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001850{
1851 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001852 hdd_context_t *pHddCtx = NULL;
1853 hdd_scaninfo_t *pScanInfo = NULL;
1854 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001855 VOS_STATUS status = 0;
1856
1857 ENTER();
1858
1859 if (NULL == pAdapter)
1860 {
1861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001862 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001863 return -ENODEV;
1864 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001865 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1866 {
1867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1868 "%s:LOGP in Progress. Ignore!!!", __func__);
1869 return -EAGAIN;
1870 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001871
1872 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1873 if (NULL == pHddCtx)
1874 {
1875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001876 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001877 return -ENODEV;
1878 }
1879
1880 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1881 if (NULL == staAdapter)
1882 {
1883 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1884 if (NULL == staAdapter)
1885 {
1886 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001887 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001888 return -ENODEV;
1889 }
1890 }
1891
1892 pScanInfo = &pHddCtx->scan_info;
1893
Jeff Johnson295189b2012-06-20 16:38:30 -07001894 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1895 {
1896 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1897 return -EAGAIN;
1898 }
1899
1900 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1901
1902 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1903 __func__,pAdapter->device_mode);
1904
Jeff Johnsone7245742012-09-05 17:12:55 -07001905 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1906 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001907 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001908 hdd_abort_mac_scan(staAdapter->pHddCtx);
1909 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001910 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07001911 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1912 if (!status)
1913 {
1914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08001915 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001916 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001917 VOS_ASSERT(pScanInfo->mScanPending);
1918 return 0;
1919 }
1920 }
1921
Jeff Johnson295189b2012-06-20 16:38:30 -07001922 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1923#ifdef WLAN_FEATURE_P2P
1924 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1925#endif
1926 )
1927 {
1928 beacon_data_t *old;
1929
1930 old = pAdapter->sessionCtx.ap.beacon;
1931
1932 if (!old)
1933 return -ENOENT;
1934
1935#ifdef CONFIG_CFG80211
1936 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1937#endif
1938
1939 mutex_lock(&pHddCtx->sap_lock);
1940 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1941 {
1942 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
1943 {
1944 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
1945
1946 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1947
1948 if (!VOS_IS_STATUS_SUCCESS(status))
1949 {
1950 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1951 ("ERROR: HDD vos wait for single_event failed!!\n"));
1952 VOS_ASSERT(0);
1953 }
1954 }
1955 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
1956 }
1957 mutex_unlock(&pHddCtx->sap_lock);
1958
1959 if(status != VOS_STATUS_SUCCESS)
1960 {
1961 hddLog(VOS_TRACE_LEVEL_FATAL,
1962 "%s:Error!!! Stopping the BSS\n",__func__);
1963 return -EINVAL;
1964 }
1965
1966 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1967 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
1968 ==eHAL_STATUS_FAILURE)
1969 {
1970 hddLog(LOGE,
1971 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
1972 }
1973
1974 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1975 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1976 eANI_BOOLEAN_FALSE) )
1977 {
1978 hddLog(LOGE,
1979 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1980 }
1981
1982 // Reset WNI_CFG_PROBE_RSP Flags
1983 wlan_hdd_reset_prob_rspies(pAdapter);
1984
1985 pAdapter->sessionCtx.ap.beacon = NULL;
1986 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001987#ifdef WLAN_FEATURE_P2P_DEBUG
1988 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
1989 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
1990 {
1991 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
1992 "GO got removed");
1993 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
1994 }
1995#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001996 }
1997 EXIT();
1998 return status;
1999}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002000
2001#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2002
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302003static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2004 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002005 struct cfg80211_ap_settings *params)
2006{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302007 hdd_adapter_t *pAdapter;
2008 hdd_context_t *pHddCtx;
2009 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002010
2011 ENTER();
2012
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302013 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002014 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2016 "%s: Device is Null", __func__);
2017 return -ENODEV;
2018 }
2019
2020 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2021 if (NULL == pAdapter)
2022 {
2023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2024 "%s: HDD adapter is Null", __func__);
2025 return -ENODEV;
2026 }
2027
2028 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2029 {
2030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2031 "%s: HDD adapter magic is invalid", __func__);
2032 return -ENODEV;
2033 }
2034
2035 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2036 if (NULL == pHddCtx)
2037 {
2038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2039 "%s: HDD context is Null", __func__);
2040 return -ENODEV;
2041 }
2042
2043 if (pHddCtx->isLogpInProgress)
2044 {
2045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2046 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002047 return -EAGAIN;
2048 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302049
2050 if (pHddCtx->isLoadUnloadInProgress)
2051 {
2052 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2053 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2054 return -EAGAIN;
2055 }
2056
2057 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2058 __func__, pAdapter->device_mode);
2059
2060 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002061#ifdef WLAN_FEATURE_P2P
2062 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2063#endif
2064 )
2065 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302066 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002067
2068 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302069
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002070 if (old)
2071 return -EALREADY;
2072
2073 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2074
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302075 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002076 {
2077 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302078 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002079 return -EINVAL;
2080 }
2081 pAdapter->sessionCtx.ap.beacon = new;
2082 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2083 params->ssid_len, params->hidden_ssid);
2084 }
2085
2086 EXIT();
2087 return status;
2088}
2089
2090
2091static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2092 struct net_device *dev,
2093 struct cfg80211_beacon_data *params)
2094{
2095 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2096 int status=VOS_STATUS_SUCCESS;
2097
2098 ENTER();
2099
2100 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2101 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002102 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2103 {
2104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2105 return -EAGAIN;
2106 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002107
2108 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2109#ifdef WLAN_FEATURE_P2P
2110 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2111#endif
2112 )
2113 {
2114 beacon_data_t *old,*new;
2115
2116 old = pAdapter->sessionCtx.ap.beacon;
2117
2118 if (!old)
2119 return -ENOENT;
2120
2121 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2122
2123 if(status != VOS_STATUS_SUCCESS) {
2124 hddLog(VOS_TRACE_LEVEL_FATAL,
2125 "%s: Error!!! Allocating the new beacon\n",__func__);
2126 return -EINVAL;
2127 }
2128
2129 pAdapter->sessionCtx.ap.beacon = new;
2130
2131 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2132 }
2133
2134 EXIT();
2135 return status;
2136}
2137
2138#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2139
Jeff Johnson295189b2012-06-20 16:38:30 -07002140
2141static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2142 struct net_device *dev,
2143 struct bss_parameters *params)
2144{
2145 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2146
2147 ENTER();
2148
2149 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2150 __func__,pAdapter->device_mode);
2151
2152 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2153#ifdef WLAN_FEATURE_P2P
2154 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2155#endif
2156 )
2157 {
2158 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2159 * want to update this parameter */
2160 if (-1 != params->ap_isolate)
2161 {
2162 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2163 }
2164 }
2165
2166 EXIT();
2167 return 0;
2168}
2169
2170/*
2171 * FUNCTION: wlan_hdd_cfg80211_change_iface
2172 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2173 */
2174int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2175 struct net_device *ndev,
2176 enum nl80211_iftype type,
2177 u32 *flags,
2178 struct vif_params *params
2179 )
2180{
2181 struct wireless_dev *wdev;
2182 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2183 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002184 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002185 tCsrRoamProfile *pRoamProfile = NULL;
2186 eCsrRoamBssType LastBSSType;
2187 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2188 eMib_dot11DesiredBssType connectedBssType;
2189 VOS_STATUS status;
2190
2191 ENTER();
2192
2193 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2194 {
2195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2196 return -EAGAIN;
2197 }
2198
2199 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2200 __func__, pAdapter->device_mode);
2201
2202 wdev = ndev->ieee80211_ptr;
2203
2204#ifdef WLAN_BTAMP_FEATURE
2205 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2206 (NL80211_IFTYPE_ADHOC == type)||
2207 (NL80211_IFTYPE_AP == type)||
2208 (NL80211_IFTYPE_P2P_GO == type))
2209 {
2210 pHddCtx->isAmpAllowed = VOS_FALSE;
2211 // stop AMP traffic
2212 status = WLANBAP_StopAmp();
2213 if(VOS_STATUS_SUCCESS != status )
2214 {
2215 pHddCtx->isAmpAllowed = VOS_TRUE;
2216 hddLog(VOS_TRACE_LEVEL_FATAL,
2217 "%s: Failed to stop AMP", __func__);
2218 return -EINVAL;
2219 }
2220 }
2221#endif //WLAN_BTAMP_FEATURE
2222 /* Reset the current device mode bit mask*/
2223 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2224
2225 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2226#ifdef WLAN_FEATURE_P2P
2227 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002228 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002229#endif
2230 )
2231 {
2232 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2233 pRoamProfile = &pWextState->roamProfile;
2234 LastBSSType = pRoamProfile->BSSType;
2235
2236 switch (type)
2237 {
2238 case NL80211_IFTYPE_STATION:
2239#ifdef WLAN_FEATURE_P2P
2240 case NL80211_IFTYPE_P2P_CLIENT:
2241#endif
2242 hddLog(VOS_TRACE_LEVEL_INFO,
2243 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2244 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002245#ifdef WLAN_FEATURE_11AC
2246 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2247 {
2248 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2249 }
2250#endif
2251 pRoamProfile->phyMode =
2252 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002253 wdev->iftype = type;
2254#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002255 //Check for sub-string p2p to confirm its a p2p interface
2256 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002257 {
2258 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2259 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2260 }
2261 else
2262 {
2263 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002264 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002265 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002266#endif
2267 break;
2268 case NL80211_IFTYPE_ADHOC:
2269 hddLog(VOS_TRACE_LEVEL_INFO,
2270 "%s: setting interface Type to ADHOC", __func__);
2271 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2272 pRoamProfile->phyMode =
2273 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2274 wdev->iftype = type;
2275 break;
2276
2277 case NL80211_IFTYPE_AP:
2278#ifdef WLAN_FEATURE_P2P
2279 case NL80211_IFTYPE_P2P_GO:
2280#endif
2281 {
2282 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2283 "%s: setting interface Type to %s", __func__,
2284 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2285
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002286 //Cancel any remain on channel for GO mode
2287 if (NL80211_IFTYPE_P2P_GO == type)
2288 {
2289 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2290 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002291 if (NL80211_IFTYPE_AP == type)
2292 {
2293 /* As Loading WLAN Driver one interface being created for p2p device
2294 * address. This will take one HW STA and the max number of clients
2295 * that can connect to softAP will be reduced by one. so while changing
2296 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2297 * interface as it is not required in SoftAP mode.
2298 */
2299
2300 // Get P2P Adapter
2301 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2302
2303 if (pP2pAdapter)
2304 {
2305 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2306 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2307 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2308 }
2309 }
2310
Jeff Johnson295189b2012-06-20 16:38:30 -07002311 //De-init the adapter.
2312 hdd_stop_adapter( pHddCtx, pAdapter );
2313 hdd_deinit_adapter( pHddCtx, pAdapter );
2314 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2315#ifdef WLAN_SOFTAP_FEATURE
2316#ifdef WLAN_FEATURE_P2P
2317 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2318 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2319#else
2320 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2321#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002322
2323 //Disable BMPS and IMPS if enabled
2324 //before starting Go
2325 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2326 {
2327 if(VOS_STATUS_E_FAILURE ==
2328 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2329 {
2330 //Fail to Exit BMPS
2331 VOS_ASSERT(0);
2332 }
2333 }
2334
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002335 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2336 (pConfig->apRandomBssidEnabled))
2337 {
2338 /* To meet Android requirements create a randomized
2339 MAC address of the form 02:1A:11:Fx:xx:xx */
2340 get_random_bytes(&ndev->dev_addr[3], 3);
2341 ndev->dev_addr[0] = 0x02;
2342 ndev->dev_addr[1] = 0x1A;
2343 ndev->dev_addr[2] = 0x11;
2344 ndev->dev_addr[3] |= 0xF0;
2345 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2346 VOS_MAC_ADDR_SIZE);
2347 pr_info("wlan: Generated HotSpot BSSID "
2348 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2349 ndev->dev_addr[0],
2350 ndev->dev_addr[1],
2351 ndev->dev_addr[2],
2352 ndev->dev_addr[3],
2353 ndev->dev_addr[4],
2354 ndev->dev_addr[5]);
2355 }
2356
Jeff Johnson295189b2012-06-20 16:38:30 -07002357 hdd_set_ap_ops( pAdapter->dev );
2358
2359 status = hdd_init_ap_mode(pAdapter);
2360 if(status != VOS_STATUS_SUCCESS)
2361 {
2362 hddLog(VOS_TRACE_LEVEL_FATAL,
2363 "%s: Error initializing the ap mode", __func__);
2364 return -EINVAL;
2365 }
2366 hdd_set_conparam(1);
2367
2368#endif
2369 /*interface type changed update in wiphy structure*/
2370 if(wdev)
2371 {
2372 wdev->iftype = type;
2373 pHddCtx->change_iface = type;
2374 }
2375 else
2376 {
2377 hddLog(VOS_TRACE_LEVEL_ERROR,
2378 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2379 return -EINVAL;
2380 }
2381 goto done;
2382 }
2383
2384 default:
2385 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2386 __func__);
2387 return -EOPNOTSUPP;
2388 }
2389 }
2390 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2391#ifdef WLAN_FEATURE_P2P
2392 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2393#endif
2394 )
2395 {
2396 switch(type)
2397 {
2398 case NL80211_IFTYPE_STATION:
2399#ifdef WLAN_FEATURE_P2P
2400 case NL80211_IFTYPE_P2P_CLIENT:
2401#endif
2402 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002403 hdd_stop_adapter( pHddCtx, pAdapter );
2404 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002405 wdev->iftype = type;
2406#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002407 //Check for sub-string p2p to confirm its a p2p interface
2408 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002409 {
2410 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2411 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2412 }
2413 else
2414 {
2415 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002416 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002417 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002418#endif
2419 hdd_set_conparam(0);
2420 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002421 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2422 hdd_set_station_ops( pAdapter->dev );
2423 status = hdd_init_station_mode( pAdapter );
2424 if( VOS_STATUS_SUCCESS != status )
2425 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002426 /* In case of JB, for P2P-GO, only change interface will be called,
2427 * This is the right place to enable back bmps_imps()
2428 */
2429 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002430 goto done;
2431 case NL80211_IFTYPE_AP:
2432#ifdef WLAN_FEATURE_P2P
2433 case NL80211_IFTYPE_P2P_GO:
2434#endif
2435 wdev->iftype = type;
2436#ifdef WLAN_FEATURE_P2P
2437 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2438 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2439#endif
2440 goto done;
2441 default:
2442 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2443 __func__);
2444 return -EOPNOTSUPP;
2445
2446 }
2447
2448 }
2449 else
2450 {
2451 return -EOPNOTSUPP;
2452 }
2453
2454
2455 if(pRoamProfile)
2456 {
2457 if ( LastBSSType != pRoamProfile->BSSType )
2458 {
2459 /*interface type changed update in wiphy structure*/
2460 wdev->iftype = type;
2461
2462 /*the BSS mode changed, We need to issue disconnect
2463 if connected or in IBSS disconnect state*/
2464 if ( hdd_connGetConnectedBssType(
2465 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2466 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2467 {
2468 /*need to issue a disconnect to CSR.*/
2469 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2470 if( eHAL_STATUS_SUCCESS ==
2471 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2472 pAdapter->sessionId,
2473 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2474 {
2475 wait_for_completion_interruptible_timeout(
2476 &pAdapter->disconnect_comp_var,
2477 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2478 }
2479 }
2480 }
2481 }
2482
2483done:
2484 /*set bitmask based on updated value*/
2485 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2486#ifdef WLAN_BTAMP_FEATURE
2487 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2488 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2489 {
2490 //we are ok to do AMP
2491 pHddCtx->isAmpAllowed = VOS_TRUE;
2492 }
2493#endif //WLAN_BTAMP_FEATURE
2494 EXIT();
2495 return 0;
2496}
2497
2498static int wlan_hdd_change_station(struct wiphy *wiphy,
2499 struct net_device *dev,
2500 u8 *mac,
2501 struct station_parameters *params)
2502{
2503 VOS_STATUS status = VOS_STATUS_SUCCESS;
2504 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2505 v_MACADDR_t STAMacAddress;
2506
Jeff Johnsone7245742012-09-05 17:12:55 -07002507 ENTER();
2508
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002509 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2510 {
2511 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2512 "%s:LOGP in Progress. Ignore!!!", __func__);
2513 return -EAGAIN;
2514 }
2515
Jeff Johnson295189b2012-06-20 16:38:30 -07002516 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2517
2518 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2519#ifdef WLAN_FEATURE_P2P
2520 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2521#endif
2522 )
2523 {
2524 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2525 {
2526 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2527 WLANTL_STA_AUTHENTICATED);
2528
2529 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002530 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002531 return -EINVAL;
2532 }
2533 }
2534
Jeff Johnsone7245742012-09-05 17:12:55 -07002535 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002536 return status;
2537}
2538
2539/*
2540 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2541 * This function is used to get peer station index in IBSS mode
2542 */
2543static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2544{
2545 u8 idx = 0;
2546 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2547 ENTER();
2548 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2549 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2550 {
2551 if ( (0 !=
2552 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2553 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2554 temp, VOS_MAC_ADDR_SIZE)
2555 )
2556 {
2557 return idx;
2558 }
2559 }
2560 return idx;
2561}
2562
2563
2564/*
2565 * FUNCTION: wlan_hdd_cfg80211_add_key
2566 * This function is used to initialize the key information
2567 */
2568#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2569static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2570 struct net_device *ndev,
2571 u8 key_index, bool pairwise,
2572 const u8 *mac_addr,
2573 struct key_params *params
2574 )
2575#else
2576static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2577 struct net_device *ndev,
2578 u8 key_index, const u8 *mac_addr,
2579 struct key_params *params
2580 )
2581#endif
2582{
2583 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2584 tCsrRoamSetKey setKey;
2585 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2586 int status = 0;
2587 v_U32_t roamId= 0xFF;
2588 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2589 hdd_hostapd_state_t *pHostapdState;
2590 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002591 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002592
2593 ENTER();
2594
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002595 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2596 {
2597 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2598 "%s:LOGP in Progress. Ignore!!!", __func__);
2599 return -EAGAIN;
2600 }
2601
Jeff Johnson295189b2012-06-20 16:38:30 -07002602 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2603 __func__,pAdapter->device_mode);
2604
2605 if (CSR_MAX_NUM_KEY <= key_index)
2606 {
2607 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2608 key_index);
2609
2610 return -EINVAL;
2611 }
2612
2613 hddLog(VOS_TRACE_LEVEL_INFO,
2614 "%s: called with key index = %d & key length %d",
2615 __func__, key_index, params->key_len);
2616
2617 /*extract key idx, key len and key*/
2618 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2619 setKey.keyId = key_index;
2620 setKey.keyLength = params->key_len;
2621 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2622
2623 switch (params->cipher)
2624 {
2625 case WLAN_CIPHER_SUITE_WEP40:
2626 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2627 break;
2628
2629 case WLAN_CIPHER_SUITE_WEP104:
2630 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2631 break;
2632
2633 case WLAN_CIPHER_SUITE_TKIP:
2634 {
2635 u8 *pKey = &setKey.Key[0];
2636 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2637
2638 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2639
2640 /*Supplicant sends the 32bytes key in this order
2641
2642 |--------------|----------|----------|
2643 | Tk1 |TX-MIC | RX Mic |
2644 |--------------|----------|----------|
2645 <---16bytes---><--8bytes--><--8bytes-->
2646
2647 */
2648 /*Sme expects the 32 bytes key to be in the below order
2649
2650 |--------------|----------|----------|
2651 | Tk1 |RX-MIC | TX Mic |
2652 |--------------|----------|----------|
2653 <---16bytes---><--8bytes--><--8bytes-->
2654 */
2655 /* Copy the Temporal Key 1 (TK1) */
2656 vos_mem_copy(pKey, params->key,16);
2657
2658 /*Copy the rx mic first*/
2659 vos_mem_copy(&pKey[16],&params->key[24],8);
2660
2661 /*Copy the tx mic */
2662 vos_mem_copy(&pKey[24],&params->key[16],8);
2663
2664
2665 break;
2666 }
2667
2668 case WLAN_CIPHER_SUITE_CCMP:
2669 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2670 break;
2671
2672#ifdef FEATURE_WLAN_WAPI
2673 case WLAN_CIPHER_SUITE_SMS4:
2674 {
2675 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2676 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2677 params->key, params->key_len);
2678 return 0;
2679 }
2680#endif
2681#ifdef FEATURE_WLAN_CCX
2682 case WLAN_CIPHER_SUITE_KRK:
2683 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2684 break;
2685#endif
2686 default:
2687 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2688 __func__, params->cipher);
2689 return -EOPNOTSUPP;
2690 }
2691
2692 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2693 __func__, setKey.encType);
2694
2695
2696
2697 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2698#ifdef WLAN_FEATURE_P2P
2699 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2700#endif
2701 )
2702 {
2703
2704
2705 if (
2706#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2707 (!pairwise)
2708#else
2709 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2710#endif
2711 )
2712 {
2713 /* set group key*/
2714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002715 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002716 __func__, __LINE__);
2717 setKey.keyDirection = eSIR_RX_ONLY;
2718 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2719 }
2720 else
2721 {
2722 /* set pairwise key*/
2723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2724 "%s- %d: setting pairwise key",
2725 __func__, __LINE__);
2726 setKey.keyDirection = eSIR_TX_RX;
2727 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2728 }
2729
2730 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2731 if( pHostapdState->bssState == BSS_START )
2732 {
2733 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2734
2735 if ( status != eHAL_STATUS_SUCCESS )
2736 {
2737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2738 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2739 __LINE__, status );
2740 }
2741 }
2742
2743 /* Saving WEP keys */
2744 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2745 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2746 {
2747 //Save the wep key in ap context. Issue setkey after the BSS is started.
2748 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2749 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2750 }
2751 else
2752 {
2753 //Save the key in ap context. Issue setkey after the BSS is started.
2754 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2755 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2756 }
2757 }
2758 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2759#ifdef WLAN_FEATURE_P2P
2760 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2761#endif
2762 )
2763 {
2764 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2765 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2766
2767 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2768
2769 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2770 params->key, params->key_len);
2771
2772 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2773
2774 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2775 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2776 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2777 )
2778 &&
2779 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2780 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2781 )
2782 )
2783 {
2784 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2785 * interface, copy bssid for pairwise key and group macaddr for
2786 * group key initialization*/
2787
2788 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2789
2790 pWextState->roamProfile.negotiatedUCEncryptionType =
2791 pHddStaCtx->conn_info.ucEncryptionType =
2792 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2793 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2794 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2795
2796
2797 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2798 "%s: Negotiated encryption type %d", __func__,
2799 pWextState->roamProfile.negotiatedUCEncryptionType);
2800
2801 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2802 &pWextState->roamProfile, true);
2803 setKey.keyLength = 0;
2804 setKey.keyDirection = eSIR_TX_RX;
2805
2806#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2807 if (pairwise)
2808 {
2809#endif
2810 if (mac_addr)
2811 {
2812 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2813 }
2814 else
2815 {
2816 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2817 * and peerMacAddress in case of IBSS*/
2818 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2819 {
2820 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2821 if (HDD_MAX_NUM_IBSS_STA != staidx)
2822 {
2823 vos_mem_copy(setKey.peerMac,
2824 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2825 WNI_CFG_BSSID_LEN);
2826
2827 }
2828 else
2829 {
2830 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2831 __func__);
2832 return -EOPNOTSUPP;
2833 }
2834 }
2835 else
2836 {
2837 vos_mem_copy(setKey.peerMac,
2838 &pHddStaCtx->conn_info.bssId[0],
2839 WNI_CFG_BSSID_LEN);
2840 }
2841 }
2842#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2843 }
2844 else
2845 {
2846 /* set group key*/
2847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2848 "%s- %d: setting Group key",
2849 __func__, __LINE__);
2850 setKey.keyDirection = eSIR_RX_ONLY;
2851 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2852 }
2853#endif
2854 }
2855 else if (
2856#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2857 (!pairwise)
2858#else
2859 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2860#endif
2861 )
2862 {
2863 /* set group key*/
2864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2865 "%s- %d: setting Group key",
2866 __func__, __LINE__);
2867 setKey.keyDirection = eSIR_RX_ONLY;
2868 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2869 }
2870 else
2871 {
2872 /* set pairwise key*/
2873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2874 "%s- %d: setting pairwise key",
2875 __func__, __LINE__);
2876 setKey.keyDirection = eSIR_TX_RX;
2877 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2878 }
2879
2880 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2881 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2882 __func__, setKey.peerMac[0], setKey.peerMac[1],
2883 setKey.peerMac[2], setKey.peerMac[3],
2884 setKey.peerMac[4], setKey.peerMac[5],
2885 setKey.keyDirection);
2886
2887 vos_status = wlan_hdd_check_ula_done(pAdapter);
2888
2889 if ( vos_status != VOS_STATUS_SUCCESS )
2890 {
2891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2892 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2893 __LINE__, vos_status );
2894
2895 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2896
2897 return -EINVAL;
2898
2899 }
2900
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002901#ifdef WLAN_FEATURE_VOWIFI_11R
2902 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2903 Save the key in the UMAC and include it in the ADD BSS request */
2904 /*TODO 11r - is this used?? */
2905 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2906 if( halStatus == eHAL_STATUS_SUCCESS )
2907 {
2908 return halStatus;
2909 }
2910#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002911
2912 /* issue set key request to SME*/
2913 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2914 pAdapter->sessionId, &setKey, &roamId );
2915
2916 if ( 0 != status )
2917 {
2918 hddLog(VOS_TRACE_LEVEL_ERROR,
2919 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2920 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2921 return -EINVAL;
2922 }
2923
2924
2925 /* in case of IBSS as there was no information available about WEP keys during
2926 * IBSS join, group key intialized with NULL key, so re-initialize group key
2927 * with correct value*/
2928 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2929 !( ( IW_AUTH_KEY_MGMT_802_1X
2930 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2931 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2932 )
2933 &&
2934 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2935 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2936 )
2937 )
2938 {
2939 setKey.keyDirection = eSIR_RX_ONLY;
2940 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2941
2942 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2943 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2944 __func__, setKey.peerMac[0], setKey.peerMac[1],
2945 setKey.peerMac[2], setKey.peerMac[3],
2946 setKey.peerMac[4], setKey.peerMac[5],
2947 setKey.keyDirection);
2948
2949 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2950 pAdapter->sessionId, &setKey, &roamId );
2951
2952 if ( 0 != status )
2953 {
2954 hddLog(VOS_TRACE_LEVEL_ERROR,
2955 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
2956 __func__, status);
2957 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2958 return -EINVAL;
2959 }
2960 }
2961 }
2962
2963 return 0;
2964}
2965
2966/*
2967 * FUNCTION: wlan_hdd_cfg80211_get_key
2968 * This function is used to get the key information
2969 */
2970#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2971static int wlan_hdd_cfg80211_get_key(
2972 struct wiphy *wiphy,
2973 struct net_device *ndev,
2974 u8 key_index, bool pairwise,
2975 const u8 *mac_addr, void *cookie,
2976 void (*callback)(void *cookie, struct key_params*)
2977 )
2978#else
2979static int wlan_hdd_cfg80211_get_key(
2980 struct wiphy *wiphy,
2981 struct net_device *ndev,
2982 u8 key_index, const u8 *mac_addr, void *cookie,
2983 void (*callback)(void *cookie, struct key_params*)
2984 )
2985#endif
2986{
2987 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2988 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2989 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
2990 struct key_params params;
2991
2992 ENTER();
2993
2994 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2995 __func__,pAdapter->device_mode);
2996
2997 memset(&params, 0, sizeof(params));
2998
2999 if (CSR_MAX_NUM_KEY <= key_index)
3000 {
3001 return -EINVAL;
3002 }
3003
3004 switch(pRoamProfile->EncryptionType.encryptionType[0])
3005 {
3006 case eCSR_ENCRYPT_TYPE_NONE:
3007 params.cipher = IW_AUTH_CIPHER_NONE;
3008 break;
3009
3010 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3011 case eCSR_ENCRYPT_TYPE_WEP40:
3012 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3013 break;
3014
3015 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3016 case eCSR_ENCRYPT_TYPE_WEP104:
3017 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3018 break;
3019
3020 case eCSR_ENCRYPT_TYPE_TKIP:
3021 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3022 break;
3023
3024 case eCSR_ENCRYPT_TYPE_AES:
3025 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3026 break;
3027
3028 default:
3029 params.cipher = IW_AUTH_CIPHER_NONE;
3030 break;
3031 }
3032
3033 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3034 params.seq_len = 0;
3035 params.seq = NULL;
3036 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3037 callback(cookie, &params);
3038 return 0;
3039}
3040
3041/*
3042 * FUNCTION: wlan_hdd_cfg80211_del_key
3043 * This function is used to delete the key information
3044 */
3045#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3046static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3047 struct net_device *ndev,
3048 u8 key_index,
3049 bool pairwise,
3050 const u8 *mac_addr
3051 )
3052#else
3053static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3054 struct net_device *ndev,
3055 u8 key_index,
3056 const u8 *mac_addr
3057 )
3058#endif
3059{
3060 int status = 0;
3061
3062 //This code needs to be revisited. There is sme_removeKey API, we should
3063 //plan to use that. After the change to use correct index in setkey,
3064 //it is observed that this is invalidating peer
3065 //key index whenever re-key is done. This is affecting data link.
3066 //It should be ok to ignore del_key.
3067#if 0
3068 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3069 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3070 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3071 tCsrRoamSetKey setKey;
3072 v_U32_t roamId= 0xFF;
3073
3074 ENTER();
3075
3076 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3077 __func__,pAdapter->device_mode);
3078
3079 if (CSR_MAX_NUM_KEY <= key_index)
3080 {
3081 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3082 key_index);
3083
3084 return -EINVAL;
3085 }
3086
3087 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3088 setKey.keyId = key_index;
3089
3090 if (mac_addr)
3091 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3092 else
3093 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3094
3095 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3096
3097 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3098#ifdef WLAN_FEATURE_P2P
3099 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3100#endif
3101 )
3102 {
3103
3104 hdd_hostapd_state_t *pHostapdState =
3105 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3106 if( pHostapdState->bssState == BSS_START)
3107 {
3108 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3109
3110 if ( status != eHAL_STATUS_SUCCESS )
3111 {
3112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3113 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3114 __LINE__, status );
3115 }
3116 }
3117 }
3118 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3119#ifdef WLAN_FEATURE_P2P
3120 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3121#endif
3122 )
3123 {
3124 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3125
3126 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3127
3128 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3129 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3130 __func__, setKey.peerMac[0], setKey.peerMac[1],
3131 setKey.peerMac[2], setKey.peerMac[3],
3132 setKey.peerMac[4], setKey.peerMac[5]);
3133 if(pAdapter->sessionCtx.station.conn_info.connState ==
3134 eConnectionState_Associated)
3135 {
3136 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3137 pAdapter->sessionId, &setKey, &roamId );
3138
3139 if ( 0 != status )
3140 {
3141 hddLog(VOS_TRACE_LEVEL_ERROR,
3142 "%s: sme_RoamSetKey failure, returned %d",
3143 __func__, status);
3144 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3145 return -EINVAL;
3146 }
3147 }
3148 }
3149#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003150 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003151 return status;
3152}
3153
3154/*
3155 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3156 * This function is used to set the default tx key index
3157 */
3158#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3159static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3160 struct net_device *ndev,
3161 u8 key_index,
3162 bool unicast, bool multicast)
3163#else
3164static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3165 struct net_device *ndev,
3166 u8 key_index)
3167#endif
3168{
3169 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3170 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3171 int status = 0;
3172 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3173
3174 ENTER();
3175
3176 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3177 __func__,pAdapter->device_mode, key_index);
3178
3179 if (CSR_MAX_NUM_KEY <= key_index)
3180 {
3181 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3182 key_index);
3183
3184 return -EINVAL;
3185 }
3186
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003187 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3188 {
3189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3190 "%s:LOGP in Progress. Ignore!!!", __func__);
3191 return -EAGAIN;
3192 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003193
3194 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3195#ifdef WLAN_FEATURE_P2P
3196 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3197#endif
3198 )
3199 {
3200 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3201 (eCSR_ENCRYPT_TYPE_TKIP !=
3202 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3203 (eCSR_ENCRYPT_TYPE_AES !=
3204 pWextState->roamProfile.EncryptionType.encryptionType[0])
3205 )
3206 {
3207 /* if default key index is not same as previous one,
3208 * then update the default key index */
3209
3210 tCsrRoamSetKey setKey;
3211 v_U32_t roamId= 0xFF;
3212 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3213
3214 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3215 __func__, key_index);
3216
3217 Keys->defaultIndex = (u8)key_index;
3218 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3219 setKey.keyId = key_index;
3220 setKey.keyLength = Keys->KeyLength[key_index];
3221
3222 vos_mem_copy(&setKey.Key[0],
3223 &Keys->KeyMaterial[key_index][0],
3224 Keys->KeyLength[key_index]);
3225
3226 setKey.keyDirection = eSIR_TX_ONLY;
3227
3228 vos_mem_copy(setKey.peerMac,
3229 &pHddStaCtx->conn_info.bssId[0],
3230 WNI_CFG_BSSID_LEN);
3231
3232 setKey.encType =
3233 pWextState->roamProfile.EncryptionType.encryptionType[0];
3234
3235 /* issue set key request */
3236 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3237 pAdapter->sessionId, &setKey, &roamId );
3238
3239 if ( 0 != status )
3240 {
3241 hddLog(VOS_TRACE_LEVEL_ERROR,
3242 "%s: sme_RoamSetKey failed, returned %d", __func__,
3243 status);
3244 return -EINVAL;
3245 }
3246 }
3247 }
3248
3249 /* In SoftAp mode setting key direction for default mode */
3250 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3251 {
3252 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3253 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3254 (eCSR_ENCRYPT_TYPE_AES !=
3255 pWextState->roamProfile.EncryptionType.encryptionType[0])
3256 )
3257 {
3258 /* Saving key direction for default key index to TX default */
3259 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3260 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3261 }
3262 }
3263
3264 return status;
3265}
3266
3267/**
3268 * FUNCTION: wlan_hdd_cfg80211_set_channel
3269 * This function is used to set the channel number
3270 */
3271int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3272 struct ieee80211_channel *chan,
3273 enum nl80211_channel_type channel_type
3274 )
3275{
3276 v_U32_t num_ch = 0;
3277 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003278 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003279 int freq = chan->center_freq; /* freq is in MHZ */
3280
3281 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003282
3283 if( NULL == dev )
3284 {
3285 hddLog(VOS_TRACE_LEVEL_ERROR,
3286 "%s: Called with dev = NULL.\n", __func__);
3287 return -ENODEV;
3288 }
3289 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003290
3291 hddLog(VOS_TRACE_LEVEL_INFO,
3292 "%s: device_mode = %d freq = %d \n",__func__,
3293 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003294 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3295 {
3296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3297 return -EAGAIN;
3298 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003299
3300 /*
3301 * Do freq to chan conversion
3302 * TODO: for 11a
3303 */
3304
3305 channel = ieee80211_frequency_to_channel(freq);
3306
3307 /* Check freq range */
3308 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3309 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3310 {
3311 hddLog(VOS_TRACE_LEVEL_ERROR,
3312 "%s: Channel [%d] is outside valid range from %d to %d\n",
3313 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3314 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3315 return -EINVAL;
3316 }
3317
3318 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3319
3320 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3321#ifdef WLAN_FEATURE_P2P
3322 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3323#endif
3324 )
3325 {
3326 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3327 {
3328 hddLog(VOS_TRACE_LEVEL_ERROR,
3329 "%s: Invalid Channel [%d] \n", __func__, channel);
3330 return -EINVAL;
3331 }
3332 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3333 "%s: set channel to [%d] for device mode =%d",
3334 __func__, channel,pAdapter->device_mode);
3335 }
3336 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3337#ifdef WLAN_FEATURE_P2P
3338 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3339#endif
3340 )
3341 {
3342 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3343 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3344 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3345
3346 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3347 {
3348 /* Link is up then return cant set channel*/
3349 hddLog( VOS_TRACE_LEVEL_ERROR,
3350 "%s: IBSS Associated, can't set the channel\n", __func__);
3351 return -EINVAL;
3352 }
3353
3354 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3355 pHddStaCtx->conn_info.operationChannel = channel;
3356 pRoamProfile->ChannelInfo.ChannelList =
3357 &pHddStaCtx->conn_info.operationChannel;
3358 }
3359 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3360#ifdef WLAN_FEATURE_P2P
3361 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3362#endif
3363 )
3364 {
3365 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3366
3367 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3368 {
3369 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3370
3371 /* If auto channel selection is configured as enable/ 1 then ignore
3372 channel set by supplicant
3373 */
3374 if ( cfg_param->apAutoChannelSelection )
3375 {
3376 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3377
3378 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3379 "%s: set channel to auto channel (0) for device mode =%d",
3380 __func__, pAdapter->device_mode);
3381 }
3382 }
3383 }
3384 else
3385 {
3386 hddLog(VOS_TRACE_LEVEL_FATAL,
3387 "%s: Invalid device mode failed to set valid channel", __func__);
3388 return -EINVAL;
3389 }
3390 EXIT();
3391 return 0;
3392}
3393
3394
3395
3396/*
3397 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3398 * This function is used to inform the BSS details to nl80211 interface.
3399 */
3400static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3401 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3402{
3403 struct net_device *dev = pAdapter->dev;
3404 struct wireless_dev *wdev = dev->ieee80211_ptr;
3405 struct wiphy *wiphy = wdev->wiphy;
3406 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3407 int chan_no;
3408 int ie_length;
3409 const char *ie;
3410 unsigned int freq;
3411 struct ieee80211_channel *chan;
3412 int rssi = 0;
3413 struct cfg80211_bss *bss = NULL;
3414
3415 ENTER();
3416
3417 if( NULL == pBssDesc )
3418 {
3419 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3420 return bss;
3421 }
3422
3423 chan_no = pBssDesc->channelId;
3424 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3425 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3426
3427 if( NULL == ie )
3428 {
3429 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3430 return bss;
3431 }
3432
3433#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3434 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3435 {
3436 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3437 }
3438 else
3439 {
3440 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3441 }
3442#else
3443 freq = ieee80211_channel_to_frequency(chan_no);
3444#endif
3445
3446 chan = __ieee80211_get_channel(wiphy, freq);
3447
3448 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3449 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3450 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3451 if (bss == NULL)
3452 {
3453 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3454
3455 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3456 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3457 pBssDesc->capabilityInfo,
3458 pBssDesc->beaconInterval, ie, ie_length,
3459 rssi, GFP_KERNEL ));
3460}
3461 else
3462 {
3463 return bss;
3464 }
3465}
3466
3467
3468
3469/*
3470 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3471 * This function is used to inform the BSS details to nl80211 interface.
3472 */
3473struct cfg80211_bss*
3474wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3475 tSirBssDescription *bss_desc
3476 )
3477{
3478 /*
3479 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3480 already exists in bss data base of cfg80211 for that particular BSS ID.
3481 Using cfg80211_inform_bss_frame to update the bss entry instead of
3482 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3483 now there is no possibility to get the mgmt(probe response) frame from PE,
3484 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3485 cfg80211_inform_bss_frame.
3486 */
3487 struct net_device *dev = pAdapter->dev;
3488 struct wireless_dev *wdev = dev->ieee80211_ptr;
3489 struct wiphy *wiphy = wdev->wiphy;
3490 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003491#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3492 qcom_ie_age *qie_age = NULL;
3493 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3494#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003495 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003496#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003497 const char *ie =
3498 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3499 unsigned int freq;
3500 struct ieee80211_channel *chan;
3501 struct ieee80211_mgmt *mgmt =
3502 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3503 struct cfg80211_bss *bss_status = NULL;
3504 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3505 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003506#ifdef WLAN_OPEN_SOURCE
3507 struct timespec ts;
3508#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003509
3510 ENTER();
3511
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003512 if (!mgmt)
3513 return NULL;
3514
Jeff Johnson295189b2012-06-20 16:38:30 -07003515 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003516
3517#ifdef WLAN_OPEN_SOURCE
3518 /* Android does not want the timestamp from the frame.
3519 Instead it wants a monotonic increasing value */
3520 get_monotonic_boottime(&ts);
3521 mgmt->u.probe_resp.timestamp =
3522 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3523#else
3524 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003525 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3526 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003527
3528#endif
3529
Jeff Johnson295189b2012-06-20 16:38:30 -07003530 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3531 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003532
3533#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3534 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3535 /* Assuming this is the last IE, copy at the end */
3536 ie_length -=sizeof(qcom_ie_age);
3537 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3538 qie_age->element_id = QCOM_VENDOR_IE_ID;
3539 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3540 qie_age->oui_1 = QCOM_OUI1;
3541 qie_age->oui_2 = QCOM_OUI2;
3542 qie_age->oui_3 = QCOM_OUI3;
3543 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3544 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3545#endif
3546
Jeff Johnson295189b2012-06-20 16:38:30 -07003547 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3548
3549 mgmt->frame_control |=
3550 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3551
3552#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3553 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3554 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3555 {
3556 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3557 }
3558 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3559 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3560
3561 {
3562 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3563 }
3564 else
3565 {
3566 kfree(mgmt);
3567 return NULL;
3568 }
3569#else
3570 freq = ieee80211_channel_to_frequency(chan_no);
3571#endif
3572 chan = __ieee80211_get_channel(wiphy, freq);
3573
3574 /*To keep the rssi icon of the connected AP in the scan window
3575 *and the rssi icon of the wireless networks in sync
3576 * */
3577 if (( eConnectionState_Associated ==
3578 pAdapter->sessionCtx.station.conn_info.connState ) &&
3579 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3580 pAdapter->sessionCtx.station.conn_info.bssId,
3581 WNI_CFG_BSSID_LEN)))
3582 {
3583 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3584 rssi = (pAdapter->rssi * 100);
3585 }
3586 else
3587 {
3588 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3589 }
3590
3591 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3592 frame_len, rssi, GFP_KERNEL);
3593 kfree(mgmt);
3594 return bss_status;
3595}
3596
3597/*
3598 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3599 * This function is used to update the BSS data base of CFG8011
3600 */
3601struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3602 tCsrRoamInfo *pRoamInfo
3603 )
3604{
3605 tCsrRoamConnectedProfile roamProfile;
3606 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3607 struct cfg80211_bss *bss = NULL;
3608
3609 ENTER();
3610
3611 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3612 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3613
3614 if (NULL != roamProfile.pBssDesc)
3615 {
3616 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3617 &roamProfile);
3618
3619 if (NULL == bss)
3620 {
3621 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3622 __func__);
3623 }
3624
3625 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3626 }
3627 else
3628 {
3629 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3630 __func__);
3631 }
3632 return bss;
3633}
3634
3635/*
3636 * FUNCTION: wlan_hdd_cfg80211_update_bss
3637 */
3638static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3639 hdd_adapter_t *pAdapter
3640 )
3641{
3642 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3643 tCsrScanResultInfo *pScanResult;
3644 eHalStatus status = 0;
3645 tScanResultHandle pResult;
3646 struct cfg80211_bss *bss_status = NULL;
3647
3648 ENTER();
3649
3650 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3651 {
3652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3653 return -EAGAIN;
3654 }
3655
3656 /*
3657 * start getting scan results and populate cgf80211 BSS database
3658 */
3659 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3660
3661 /* no scan results */
3662 if (NULL == pResult)
3663 {
3664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3665 return status;
3666 }
3667
3668 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3669
3670 while (pScanResult)
3671 {
3672 /*
3673 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3674 * entry already exists in bss data base of cfg80211 for that
3675 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3676 * bss entry instead of cfg80211_inform_bss, But this call expects
3677 * mgmt packet as input. As of now there is no possibility to get
3678 * the mgmt(probe response) frame from PE, converting bss_desc to
3679 * ieee80211_mgmt(probe response) and passing to c
3680 * fg80211_inform_bss_frame.
3681 * */
3682
3683 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3684 &pScanResult->BssDescriptor);
3685
3686
3687 if (NULL == bss_status)
3688 {
3689 hddLog(VOS_TRACE_LEVEL_INFO,
3690 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3691 }
3692 else
3693 {
3694 cfg80211_put_bss(bss_status);
3695 }
3696
3697 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3698 }
3699
3700 sme_ScanResultPurge(hHal, pResult);
3701
3702 return 0;
3703}
3704
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003705void
3706hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3707{
3708 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003709 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3710 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3711 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003712} /****** end hddPrintMacAddr() ******/
3713
3714void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003715hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003716{
3717 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003718 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3719 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3720 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3721 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003722} /****** end hddPrintPmkId() ******/
3723
3724//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3725//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3726
3727//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3728//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3729
3730#define dump_bssid(bssid) \
3731 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003732 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3733 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3734 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003735 }
3736
3737#define dump_pmkid(pMac, pmkid) \
3738 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003739 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3740 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3741 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003742 }
3743
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003744#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003745/*
3746 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3747 * This function is used to notify the supplicant of a new PMKSA candidate.
3748 */
3749int wlan_hdd_cfg80211_pmksa_candidate_notify(
3750 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3751 int index, bool preauth )
3752{
Jeff Johnsone7245742012-09-05 17:12:55 -07003753#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003754 struct net_device *dev = pAdapter->dev;
3755
3756 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003757 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003758
3759 if( NULL == pRoamInfo )
3760 {
3761 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3762 return -EINVAL;
3763 }
3764
3765 dump_bssid(pRoamInfo->bssid);
3766 cfg80211_pmksa_candidate_notify(dev, index,
3767 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003768#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003769 return 0;
3770}
3771#endif //FEATURE_WLAN_LFR
3772
Jeff Johnson295189b2012-06-20 16:38:30 -07003773/*
3774 * FUNCTION: hdd_cfg80211_scan_done_callback
3775 * scanning callback function, called after finishing scan
3776 *
3777 */
3778static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3779 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3780{
3781 struct net_device *dev = (struct net_device *) pContext;
3782 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3783 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003784 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3785 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003786 struct cfg80211_scan_request *req = NULL;
3787 int ret = 0;
3788
3789 ENTER();
3790
3791 hddLog(VOS_TRACE_LEVEL_INFO,
3792 "%s called with halHandle = %p, pContext = %p,"
3793 "scanID = %d, returned status = %d\n",
3794 __func__, halHandle, pContext, (int) scanId, (int) status);
3795
3796 //Block on scan req completion variable. Can't wait forever though.
3797 ret = wait_for_completion_interruptible_timeout(
3798 &pScanInfo->scan_req_completion_event,
3799 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3800 if (!ret)
3801 {
3802 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003803 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 }
3805
3806 if(pScanInfo->mScanPending != VOS_TRUE)
3807 {
3808 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003809 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 }
3811
3812 /* Check the scanId */
3813 if (pScanInfo->scanId != scanId)
3814 {
3815 hddLog(VOS_TRACE_LEVEL_INFO,
3816 "%s called with mismatched scanId pScanInfo->scanId = %d "
3817 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3818 (int) scanId);
3819 }
3820
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3822 pAdapter);
3823
3824 if (0 > ret)
3825 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3826
3827
3828 /* If any client wait scan result through WEXT
3829 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003830 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003831 {
3832 /* The other scan request waiting for current scan finish
3833 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003834 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003835 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003836 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 }
3838 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003839 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003840 {
3841 struct net_device *dev = pAdapter->dev;
3842 union iwreq_data wrqu;
3843 int we_event;
3844 char *msg;
3845
3846 memset(&wrqu, '\0', sizeof(wrqu));
3847 we_event = SIOCGIWSCAN;
3848 msg = NULL;
3849 wireless_send_event(dev, we_event, &wrqu, msg);
3850 }
3851 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003852 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003853
3854 /* Get the Scan Req */
3855 req = pAdapter->request;
3856
3857 if (!req)
3858 {
3859 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003860 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003861 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 }
3863
3864 /*
3865 * setting up 0, just in case.
3866 */
3867 req->n_ssids = 0;
3868 req->n_channels = 0;
3869 req->ie = 0;
3870
Jeff Johnson295189b2012-06-20 16:38:30 -07003871 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003872 /* Scan is no longer pending */
3873 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003874
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003875 /*
3876 * cfg80211_scan_done informing NL80211 about completion
3877 * of scanning
3878 */
3879 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003880 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003881
Jeff Johnsone7245742012-09-05 17:12:55 -07003882allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003883 /* release the wake lock at the end of the scan*/
3884 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003885
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003886 /* Acquire wakelock to handle the case where APP's tries to suspend
3887 * immediatly after the driver gets connect request(i.e after scan)
3888 * from supplicant, this result in app's is suspending and not able
3889 * to process the connect request to AP */
3890 hdd_allow_suspend_timeout(100);
3891
Jeff Johnson295189b2012-06-20 16:38:30 -07003892 EXIT();
3893 return 0;
3894}
3895
3896/*
3897 * FUNCTION: wlan_hdd_cfg80211_scan
3898 * this scan respond to scan trigger and update cfg80211 scan database
3899 * later, scan dump command can be used to recieve scan results
3900 */
3901int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3902 struct cfg80211_scan_request *request)
3903{
3904 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3905 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3906 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3907 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3908 tCsrScanRequest scanRequest;
3909 tANI_U8 *channelList = NULL, i;
3910 v_U32_t scanId = 0;
3911 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003912 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003913#ifdef WLAN_FEATURE_P2P
3914 v_U8_t* pP2pIe = NULL;
3915#endif
3916
3917 ENTER();
3918
3919 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3920 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003921
3922 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
3923 (eConnectionState_Connecting ==
3924 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
3925 {
3926 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08003927 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
3928 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003929 return -EBUSY;
3930 }
3931
Jeff Johnson295189b2012-06-20 16:38:30 -07003932#ifdef WLAN_BTAMP_FEATURE
3933 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003934 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07003935 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003936 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003937 "%s: No scanning when AMP is on", __func__);
3938 return -EOPNOTSUPP;
3939 }
3940#endif
3941 //Scan on any other interface is not supported.
3942 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
3943 {
3944 hddLog(VOS_TRACE_LEVEL_ERROR,
3945 "%s: Not scanning on device_mode = %d",
3946 __func__, pAdapter->device_mode);
3947 return -EOPNOTSUPP;
3948 }
3949
3950 if (TRUE == pScanInfo->mScanPending)
3951 {
3952 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
3953 return -EBUSY;
3954 }
3955
3956 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3957 {
3958 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3959 "%s:LOGP in Progress. Ignore!!!", __func__);
3960 return -EAGAIN;
3961 }
3962
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07003963 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
3964 {
3965 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3966 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
3967 return -EAGAIN;
3968 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07003969 //Don't Allow Scan and return busy if Remain On
3970 //Channel and action frame is pending
3971 //Otherwise Cancel Remain On Channel and allow Scan
3972 //If no action frame pending
3973 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
3974 {
3975 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
3976 return -EBUSY;
3977 }
3978
Jeff Johnson295189b2012-06-20 16:38:30 -07003979 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
3980 {
3981 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08003982 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003983 return -EAGAIN;
3984 }
3985 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
3986 {
3987 hddLog(VOS_TRACE_LEVEL_WARN,
3988 "%s: MAX TM Level Scan not allowed", __func__);
3989 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3990 return -EBUSY;
3991 }
3992 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3993
3994 vos_mem_zero( &scanRequest, sizeof(scanRequest));
3995
3996 if (NULL != request)
3997 {
3998 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
3999 (int)request->n_ssids);
4000
4001 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4002 * Becasue of this, driver is assuming that this is not wildcard scan and so
4003 * is not aging out the scan results.
4004 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004005 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004006 {
4007 request->n_ssids = 0;
4008 }
4009
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004010 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004011 {
4012 tCsrSSIDInfo *SsidInfo;
4013 int j;
4014 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4015 /* Allocate num_ssid tCsrSSIDInfo structure */
4016 SsidInfo = scanRequest.SSIDs.SSIDList =
4017 ( tCsrSSIDInfo *)vos_mem_malloc(
4018 request->n_ssids*sizeof(tCsrSSIDInfo));
4019
4020 if(NULL == scanRequest.SSIDs.SSIDList)
4021 {
4022 hddLog(VOS_TRACE_LEVEL_ERROR,
4023 "memory alloc failed SSIDInfo buffer");
4024 return -ENOMEM;
4025 }
4026
4027 /* copy all the ssid's and their length */
4028 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4029 {
4030 /* get the ssid length */
4031 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4032 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4033 SsidInfo->SSID.length);
4034 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4035 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4036 j, SsidInfo->SSID.ssId);
4037 }
4038 /* set the scan type to active */
4039 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4040 }
4041 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4042 {
4043 /* set the scan type to active */
4044 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4045 }
4046 else
4047 {
4048 /*Set the scan type to default type, in this case it is ACTIVE*/
4049 scanRequest.scanType = pScanInfo->scan_mode;
4050 }
4051 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4052 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4053 }
4054 else
4055 {
4056 /* set the scan type to active */
4057 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4058 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4059
4060 /* set min and max channel time to zero */
4061 scanRequest.minChnTime = 0;
4062 scanRequest.maxChnTime = 0;
4063 }
4064
4065 /* set BSSType to default type */
4066 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4067
4068 /*TODO: scan the requested channels only*/
4069
4070 /*Right now scanning all the channels */
4071 if( request )
4072 {
4073 if( request->n_channels )
4074 {
4075 channelList = vos_mem_malloc( request->n_channels );
4076 if( NULL == channelList )
4077 {
4078 status = -ENOMEM;
4079 goto free_mem;
4080 }
4081
4082 for( i = 0 ; i < request->n_channels ; i++ )
4083 channelList[i] = request->channels[i]->hw_value;
4084 }
4085
4086 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4087 scanRequest.ChannelInfo.ChannelList = channelList;
4088
4089 /* set requestType to full scan */
4090 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004091
4092 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4093 * search (Flush on both full scan and social scan but not on single
4094 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4095 */
4096
4097 /* Supplicant does single channel scan after 8-way handshake
4098 * and in that case driver shoudnt flush scan results. If
4099 * driver flushes the scan results here and unfortunately if
4100 * the AP doesnt respond to our probe req then association
4101 * fails which is not desired
4102 */
4103
4104 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4105 {
4106 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4107 pAdapter->sessionId );
4108 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004109
4110 if( request->ie_len )
4111 {
4112 /* save this for future association (join requires this) */
4113 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4114 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4115 pScanInfo->scanAddIE.length = request->ie_len;
4116
4117 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004118 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4119 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004120 )
4121 {
4122 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4123 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4124 }
4125
4126 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4127 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4128
4129#ifdef WLAN_FEATURE_P2P
4130 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4131 request->ie_len);
4132 if (pP2pIe != NULL)
4133 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004134#ifdef WLAN_FEATURE_P2P_DEBUG
4135 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4136 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4137 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4138 {
4139 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4140 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4141 "Go nego completed to Connection is started");
4142 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4143 "for 8way Handshake");
4144 }
4145 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4146 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4147 {
4148 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4149 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4150 "Disconnected state to Connection is started");
4151 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4152 "for 4way Handshake");
4153 }
4154#endif
4155
Jeff Johnsone7245742012-09-05 17:12:55 -07004156 /* no_cck will be set during p2p find to disable 11b rates */
4157 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004158 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004159 hddLog(VOS_TRACE_LEVEL_INFO,
4160 "%s: This is a P2P Search", __func__);
4161 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004162
Jeff Johnsone7245742012-09-05 17:12:55 -07004163 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4164 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004165 /* set requestType to P2P Discovery */
4166 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004167 }
4168
4169 /*
4170 Skip Dfs Channel in case of P2P Search
4171 if it is set in ini file
4172 */
4173 if(cfg_param->skipDfsChnlInP2pSearch)
4174 {
4175 scanRequest.skipDfsChnlInP2pSearch = 1;
4176 }
4177 else
4178 {
4179 scanRequest.skipDfsChnlInP2pSearch = 0;
4180 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004181
Jeff Johnson295189b2012-06-20 16:38:30 -07004182 }
4183 }
4184#endif
4185 }
4186 }
4187
4188 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4189
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004190 /* acquire the wakelock to avoid the apps suspend during the scan. To
4191 * address the following issues.
4192 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4193 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4194 * for long time, this result in apps running at full power for long time.
4195 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4196 * be stuck in full power because of resume BMPS
4197 */
4198 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004199
4200 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004201 pAdapter->sessionId, &scanRequest, &scanId,
4202 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004203
Jeff Johnson295189b2012-06-20 16:38:30 -07004204 if (eHAL_STATUS_SUCCESS != status)
4205 {
4206 hddLog(VOS_TRACE_LEVEL_ERROR,
4207 "%s: sme_ScanRequest returned error %d", __func__, status);
4208 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004209 if(eHAL_STATUS_RESOURCES == status)
4210 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004211 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 -07004212 status = -EBUSY;
4213 } else {
4214 status = -EIO;
4215 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004216 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004217 goto free_mem;
4218 }
4219
4220 pScanInfo->mScanPending = TRUE;
4221 pAdapter->request = request;
4222 pScanInfo->scanId = scanId;
4223
4224 complete(&pScanInfo->scan_req_completion_event);
4225
4226free_mem:
4227 if( scanRequest.SSIDs.SSIDList )
4228 {
4229 vos_mem_free(scanRequest.SSIDs.SSIDList);
4230 }
4231
4232 if( channelList )
4233 vos_mem_free( channelList );
4234
4235 EXIT();
4236
4237 return status;
4238}
4239
4240/*
4241 * FUNCTION: wlan_hdd_cfg80211_connect_start
4242 * This function is used to start the association process
4243 */
4244int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004245 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004246{
4247 int status = 0;
4248 hdd_wext_state_t *pWextState;
4249 v_U32_t roamId;
4250 tCsrRoamProfile *pRoamProfile;
4251 eMib_dot11DesiredBssType connectedBssType;
4252 eCsrAuthType RSNAuthType;
4253
4254 ENTER();
4255
4256 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4257
4258 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4259 {
4260 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4261 return -EINVAL;
4262 }
4263
4264 pRoamProfile = &pWextState->roamProfile;
4265
4266 if (pRoamProfile)
4267 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004268 int ret = 0;
4269 hdd_station_ctx_t *pHddStaCtx;
4270 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4271 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4272
4273 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4274 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4275 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004276 {
4277 /* Issue disconnect to CSR */
4278 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4279 if( eHAL_STATUS_SUCCESS ==
4280 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4281 pAdapter->sessionId,
4282 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4283 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004284 ret = wait_for_completion_interruptible_timeout(
4285 &pAdapter->disconnect_comp_var,
4286 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4287 if (0 == ret)
4288 {
4289 VOS_ASSERT(0);
4290 }
4291 }
4292 }
4293 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4294 {
4295 ret = wait_for_completion_interruptible_timeout(
4296 &pAdapter->disconnect_comp_var,
4297 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4298 if (0 == ret)
4299 {
4300 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004301 }
4302 }
4303
4304 if (HDD_WMM_USER_MODE_NO_QOS ==
4305 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4306 {
4307 /*QoS not enabled in cfg file*/
4308 pRoamProfile->uapsd_mask = 0;
4309 }
4310 else
4311 {
4312 /*QoS enabled, update uapsd mask from cfg file*/
4313 pRoamProfile->uapsd_mask =
4314 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4315 }
4316
4317 pRoamProfile->SSIDs.numOfSSIDs = 1;
4318 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4319 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4320 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4321 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4322 ssid, ssid_len);
4323
4324 if (bssid)
4325 {
4326 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4327 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4328 WNI_CFG_BSSID_LEN);
4329 /* Save BSSID in seperate variable as well, as RoamProfile
4330 BSSID is getting zeroed out in the association process. And in
4331 case of join failure we should send valid BSSID to supplicant
4332 */
4333 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4334 WNI_CFG_BSSID_LEN);
4335 }
4336
4337 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4338 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4339 {
4340 /*set gen ie*/
4341 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4342 /*set auth*/
4343 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4344 }
4345 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4346 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4347 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4348 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4349 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4350 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4351 )
4352 {
4353 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4354 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4355 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4356 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4357 eCSR_AUTH_TYPE_AUTOSWITCH;
4358 pWextState->roamProfile.AuthType.authType[0] =
4359 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4360 }
4361#ifdef FEATURE_WLAN_WAPI
4362 if (pAdapter->wapi_info.nWapiMode)
4363 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004364 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004365 switch (pAdapter->wapi_info.wapiAuthMode)
4366 {
4367 case WAPI_AUTH_MODE_PSK:
4368 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004369 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 pAdapter->wapi_info.wapiAuthMode);
4371 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4372 break;
4373 }
4374 case WAPI_AUTH_MODE_CERT:
4375 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004376 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004377 pAdapter->wapi_info.wapiAuthMode);
4378 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4379 break;
4380 }
4381 } // End of switch
4382 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4383 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4384 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004385 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004386 pRoamProfile->AuthType.numEntries = 1;
4387 pRoamProfile->EncryptionType.numEntries = 1;
4388 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4389 pRoamProfile->mcEncryptionType.numEntries = 1;
4390 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4391 }
4392 }
4393#endif /* FEATURE_WLAN_WAPI */
4394 pRoamProfile->csrPersona = pAdapter->device_mode;
4395
Jeff Johnson32d95a32012-09-10 13:15:23 -07004396 if( operatingChannel )
4397 {
4398 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4399 pRoamProfile->ChannelInfo.numOfChannels = 1;
4400 }
4401
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004402 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4403 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4404 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4405 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004406 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4407 */
4408 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4409 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4410 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004411
Jeff Johnson295189b2012-06-20 16:38:30 -07004412 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4413 pAdapter->sessionId, pRoamProfile, &roamId);
4414
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004415 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304416 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4417
4418 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004419 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4420 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4421 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304422 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004423 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304424 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004425
4426 pRoamProfile->ChannelInfo.ChannelList = NULL;
4427 pRoamProfile->ChannelInfo.numOfChannels = 0;
4428
Jeff Johnson295189b2012-06-20 16:38:30 -07004429 }
4430 else
4431 {
4432 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4433 return -EINVAL;
4434 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004435 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004436 return status;
4437}
4438
4439/*
4440 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4441 * This function is used to set the authentication type (OPEN/SHARED).
4442 *
4443 */
4444static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4445 enum nl80211_auth_type auth_type)
4446{
4447 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4448 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4449
4450 ENTER();
4451
4452 /*set authentication type*/
4453 switch (auth_type)
4454 {
4455 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4456 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004457#ifdef WLAN_FEATURE_VOWIFI_11R
4458 case NL80211_AUTHTYPE_FT:
4459#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004460 hddLog(VOS_TRACE_LEVEL_INFO,
4461 "%s: set authentication type to OPEN", __func__);
4462 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4463 break;
4464
4465 case NL80211_AUTHTYPE_SHARED_KEY:
4466 hddLog(VOS_TRACE_LEVEL_INFO,
4467 "%s: set authentication type to SHARED", __func__);
4468 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4469 break;
4470#ifdef FEATURE_WLAN_CCX
4471 case NL80211_AUTHTYPE_NETWORK_EAP:
4472 hddLog(VOS_TRACE_LEVEL_INFO,
4473 "%s: set authentication type to CCKM WPA", __func__);
4474 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4475 break;
4476#endif
4477
4478
4479 default:
4480 hddLog(VOS_TRACE_LEVEL_ERROR,
4481 "%s: Unsupported authentication type %d", __func__,
4482 auth_type);
4483 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4484 return -EINVAL;
4485 }
4486
4487 pWextState->roamProfile.AuthType.authType[0] =
4488 pHddStaCtx->conn_info.authType;
4489 return 0;
4490}
4491
4492/*
4493 * FUNCTION: wlan_hdd_set_akm_suite
4494 * This function is used to set the key mgmt type(PSK/8021x).
4495 *
4496 */
4497static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4498 u32 key_mgmt
4499 )
4500{
4501 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4502 ENTER();
4503
4504 /*set key mgmt type*/
4505 switch(key_mgmt)
4506 {
4507 case WLAN_AKM_SUITE_PSK:
4508 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4509 __func__);
4510 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4511 break;
4512
4513 case WLAN_AKM_SUITE_8021X:
4514 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4515 __func__);
4516 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4517 break;
4518#ifdef FEATURE_WLAN_CCX
4519#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4520#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4521 case WLAN_AKM_SUITE_CCKM:
4522 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4523 __func__);
4524 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4525 break;
4526#endif
4527
4528 default:
4529 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4530 __func__, key_mgmt);
4531 return -EINVAL;
4532
4533 }
4534 return 0;
4535}
4536
4537/*
4538 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4539 * This function is used to set the encryption type
4540 * (NONE/WEP40/WEP104/TKIP/CCMP).
4541 */
4542static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4543 u32 cipher,
4544 bool ucast
4545 )
4546{
4547 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4548 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4549 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4550
4551 ENTER();
4552
4553 if (!cipher)
4554 {
4555 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4556 __func__, cipher);
4557 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4558 }
4559 else
4560 {
4561
4562 /*set encryption method*/
4563 switch (cipher)
4564 {
4565 case IW_AUTH_CIPHER_NONE:
4566 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4567 break;
4568
4569 case WLAN_CIPHER_SUITE_WEP40:
4570 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4571 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4572 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4573 else
4574 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4575 break;
4576
4577 case WLAN_CIPHER_SUITE_WEP104:
4578 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4579 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4580 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4581 else
4582 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4583 break;
4584
4585 case WLAN_CIPHER_SUITE_TKIP:
4586 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4587 break;
4588
4589 case WLAN_CIPHER_SUITE_CCMP:
4590 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4591 break;
4592#ifdef FEATURE_WLAN_WAPI
4593 case WLAN_CIPHER_SUITE_SMS4:
4594 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4595 break;
4596#endif
4597
4598#ifdef FEATURE_WLAN_CCX
4599 case WLAN_CIPHER_SUITE_KRK:
4600 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4601 break;
4602#endif
4603 default:
4604 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4605 __func__, cipher);
4606 return -EOPNOTSUPP;
4607 }
4608 }
4609
4610 if (ucast)
4611 {
4612 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4613 __func__, encryptionType);
4614 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4615 pWextState->roamProfile.EncryptionType.numEntries = 1;
4616 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4617 encryptionType;
4618 }
4619 else
4620 {
4621 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4622 __func__, encryptionType);
4623 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4624 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4625 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4626 }
4627
4628 return 0;
4629}
4630
4631
4632/*
4633 * FUNCTION: wlan_hdd_cfg80211_set_ie
4634 * This function is used to parse WPA/RSN IE's.
4635 */
4636int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4637 u8 *ie,
4638 size_t ie_len
4639 )
4640{
4641 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4642 u8 *genie = ie;
4643 v_U16_t remLen = ie_len;
4644#ifdef FEATURE_WLAN_WAPI
4645 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4646 u16 *tmp;
4647 v_U16_t akmsuiteCount;
4648 int *akmlist;
4649#endif
4650 ENTER();
4651
4652 /* clear previous assocAddIE */
4653 pWextState->assocAddIE.length = 0;
4654 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4655
4656 while (remLen >= 2)
4657 {
4658 v_U16_t eLen = 0;
4659 v_U8_t elementId;
4660 elementId = *genie++;
4661 eLen = *genie++;
4662 remLen -= 2;
4663
4664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4665 __func__, elementId, eLen);
4666
4667 switch ( elementId )
4668 {
4669 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004670 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 -07004671 {
4672 hddLog(VOS_TRACE_LEVEL_ERROR,
4673 "%s: Invalid WPA IE", __func__);
4674 return -EINVAL;
4675 }
4676 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4677 {
4678 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4679 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4680 __func__, eLen + 2);
4681
4682 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4683 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004684 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4685 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004686 VOS_ASSERT(0);
4687 return -ENOMEM;
4688 }
4689 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4690 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4691 pWextState->assocAddIE.length += eLen + 2;
4692
4693 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4694 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4695 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4696 }
4697 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4698 {
4699 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4700 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4701 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4702 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4703 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4704 }
4705#ifdef WLAN_FEATURE_P2P
4706 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4707 P2P_OUI_TYPE_SIZE))
4708 /*Consider P2P IE, only for P2P Client */
4709 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4710 {
4711 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4712 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4713 __func__, eLen + 2);
4714
4715 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4716 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004717 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4718 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004719 VOS_ASSERT(0);
4720 return -ENOMEM;
4721 }
4722 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4723 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4724 pWextState->assocAddIE.length += eLen + 2;
4725
4726 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4727 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4728 }
4729#endif
4730#ifdef WLAN_FEATURE_WFD
4731 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4732 WFD_OUI_TYPE_SIZE))
4733 /*Consider WFD IE, only for P2P Client */
4734 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4735 {
4736 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4737 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4738 __func__, eLen + 2);
4739
4740 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4741 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004742 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4743 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004744 VOS_ASSERT(0);
4745 return -ENOMEM;
4746 }
4747 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4748 // WPS IE + P2P IE + WFD IE
4749 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4750 pWextState->assocAddIE.length += eLen + 2;
4751
4752 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4753 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4754 }
4755#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004756 /* Appending HS 2.0 Indication Element in Assiciation Request */
4757 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004758 HS20_OUI_TYPE_SIZE)) )
4759 {
4760 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4761 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4762 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004763
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004764 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4765 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004766 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4767 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004768 VOS_ASSERT(0);
4769 return -ENOMEM;
4770 }
4771 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4772 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004773
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004774 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4775 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4776 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004777
Jeff Johnson295189b2012-06-20 16:38:30 -07004778 break;
4779 case DOT11F_EID_RSN:
4780 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4781 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4782 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4783 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4784 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4785 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004786 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4787 case DOT11F_EID_EXTCAP:
4788 {
4789 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4790 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4791 __func__, eLen + 2);
4792
4793 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4794 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004795 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4796 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004797 VOS_ASSERT(0);
4798 return -ENOMEM;
4799 }
4800 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4801 pWextState->assocAddIE.length += eLen + 2;
4802
4803 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4804 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4805 break;
4806 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004807#ifdef FEATURE_WLAN_WAPI
4808 case WLAN_EID_WAPI:
4809 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4810 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4811 pAdapter->wapi_info.nWapiMode);
4812 tmp = (u16 *)ie;
4813 tmp = tmp + 2; // Skip element Id and Len, Version
4814 akmsuiteCount = WPA_GET_LE16(tmp);
4815 tmp = tmp + 1;
4816 akmlist = (int *)(tmp);
4817 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4818 {
4819 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4820 }
4821 else
4822 {
4823 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4824 VOS_ASSERT(0);
4825 return -EINVAL;
4826 }
4827
4828 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4829 {
4830 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004831 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004832 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4833 }
4834 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4835 {
4836 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004837 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004838 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4839 }
4840 break;
4841#endif
4842 default:
4843 hddLog (VOS_TRACE_LEVEL_ERROR,
4844 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004845 /* when Unknown IE is received we should break and continue
4846 * to the next IE in the buffer instead we were returning
4847 * so changing this to break */
4848 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004849 }
4850 genie += eLen;
4851 remLen -= eLen;
4852 }
4853 EXIT();
4854 return 0;
4855}
4856
4857/*
4858 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4859 * This function is used to initialize the security
4860 * parameters during connect operation.
4861 */
4862int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4863 struct cfg80211_connect_params *req
4864 )
4865{
4866 int status = 0;
4867 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4868 ENTER();
4869
4870 /*set wpa version*/
4871 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4872
4873 if (req->crypto.wpa_versions)
4874 {
4875 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4876 && ( (req->ie_len)
4877 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4878 // Make sure that it is including a WPA IE.
4879 /* Currently NL is putting WPA version 1 even for open,
4880 * since p2p ie is also put in same buffer.
4881 * */
4882 {
4883 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4884 }
4885 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4886 {
4887 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4888 }
4889 }
4890
4891 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4892 pWextState->wpaVersion);
4893
4894 /*set authentication type*/
4895 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4896
4897 if (0 > status)
4898 {
4899 hddLog(VOS_TRACE_LEVEL_ERROR,
4900 "%s: failed to set authentication type ", __func__);
4901 return status;
4902 }
4903
4904 /*set key mgmt type*/
4905 if (req->crypto.n_akm_suites)
4906 {
4907 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4908 if (0 > status)
4909 {
4910 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4911 __func__);
4912 return status;
4913 }
4914 }
4915
4916 /*set pairwise cipher type*/
4917 if (req->crypto.n_ciphers_pairwise)
4918 {
4919 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4920 req->crypto.ciphers_pairwise[0], true);
4921 if (0 > status)
4922 {
4923 hddLog(VOS_TRACE_LEVEL_ERROR,
4924 "%s: failed to set unicast cipher type", __func__);
4925 return status;
4926 }
4927 }
4928 else
4929 {
4930 /*Reset previous cipher suite to none*/
4931 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
4932 if (0 > status)
4933 {
4934 hddLog(VOS_TRACE_LEVEL_ERROR,
4935 "%s: failed to set unicast cipher type", __func__);
4936 return status;
4937 }
4938 }
4939
4940 /*set group cipher type*/
4941 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
4942 false);
4943
4944 if (0 > status)
4945 {
4946 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
4947 __func__);
4948 return status;
4949 }
4950
4951 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
4952 if (req->ie_len)
4953 {
4954 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
4955 if ( 0 > status)
4956 {
4957 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
4958 __func__);
4959 return status;
4960 }
4961 }
4962
4963 /*incase of WEP set default key information*/
4964 if (req->key && req->key_len)
4965 {
4966 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
4967 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
4968 )
4969 {
4970 if ( IW_AUTH_KEY_MGMT_802_1X
4971 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
4972 {
4973 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
4974 __func__);
4975 return -EOPNOTSUPP;
4976 }
4977 else
4978 {
4979 u8 key_len = req->key_len;
4980 u8 key_idx = req->key_idx;
4981
4982 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
4983 && (CSR_MAX_NUM_KEY > key_idx)
4984 )
4985 {
4986 hddLog(VOS_TRACE_LEVEL_INFO,
4987 "%s: setting default wep key, key_idx = %hu key_len %hu",
4988 __func__, key_idx, key_len);
4989 vos_mem_copy(
4990 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
4991 req->key, key_len);
4992 pWextState->roamProfile.Keys.KeyLength[key_idx] =
4993 (u8)key_len;
4994 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
4995 }
4996 }
4997 }
4998 }
4999
5000 return status;
5001}
5002
5003/*
5004 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5005 * This function is used to initialize the security
5006 * parameters during connect operation.
5007 */
5008static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5009 struct net_device *ndev,
5010 struct cfg80211_connect_params *req
5011 )
5012{
5013 int status = 0;
5014 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5015 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5016 hdd_context_t *pHddCtx = NULL;
5017
5018 ENTER();
5019
5020 hddLog(VOS_TRACE_LEVEL_INFO,
5021 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5022
5023 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5024 {
5025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5026 "%s:LOGP in Progress. Ignore!!!", __func__);
5027 return -EAGAIN;
5028 }
5029
5030#ifdef WLAN_BTAMP_FEATURE
5031 //Infra connect not supported when AMP traffic is on.
5032 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5033 {
5034 hddLog(VOS_TRACE_LEVEL_ERROR,
5035 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005036 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 }
5038#endif
5039 /*initialise security parameters*/
5040 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5041
5042 if ( 0 > status)
5043 {
5044 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5045 __func__);
5046 return status;
5047 }
5048
5049 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005050 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005051 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5052 (vos_concurrent_sessions_running()))
5053 {
5054 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5055
5056 if (NULL != pVosContext)
5057 {
5058 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5059 if(NULL != pHddCtx)
5060 {
5061 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5062 }
5063 }
5064 }
5065
Mohit Khanna765234a2012-09-11 15:08:35 -07005066 if ( req->channel )
5067 {
5068 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5069 req->ssid_len, req->bssid,
5070 req->channel->hw_value);
5071 }
5072 else
5073 {
5074 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5075 req->ssid_len, req->bssid,
5076 0);
5077 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005078
5079 if (0 > status)
5080 {
5081 //ReEnable BMPS if disabled
5082 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5083 (NULL != pHddCtx))
5084 {
5085 //ReEnable Bmps and Imps back
5086 hdd_enable_bmps_imps(pHddCtx);
5087 }
5088
5089 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5090 return status;
5091 }
5092 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5093 EXIT();
5094 return status;
5095}
5096
5097
5098/*
5099 * FUNCTION: wlan_hdd_cfg80211_disconnect
5100 * This function is used to issue a disconnect request to SME
5101 */
5102static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5103 struct net_device *dev,
5104 u16 reason
5105 )
5106{
5107 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5108 tCsrRoamProfile *pRoamProfile =
5109 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5110 int status = 0;
5111 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5112
5113 ENTER();
5114
5115 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5116 __func__,pAdapter->device_mode);
5117
5118 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5119 __func__, reason);
5120
5121 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5122 {
5123 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5124 "%s:LOGP in Progress. Ignore!!!",__func__);
5125 return -EAGAIN;
5126 }
5127 if (NULL != pRoamProfile)
5128 {
5129 /*issue disconnect request to SME, if station is in connected state*/
5130 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5131 {
5132 eCsrRoamDisconnectReason reasonCode =
5133 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5134 switch(reason)
5135 {
5136 case WLAN_REASON_MIC_FAILURE:
5137 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5138 break;
5139
5140 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5141 case WLAN_REASON_DISASSOC_AP_BUSY:
5142 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5143 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5144 break;
5145
5146 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5147 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5148 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5149 break;
5150
5151 case WLAN_REASON_DEAUTH_LEAVING:
5152 default:
5153 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5154 break;
5155 }
5156 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5157 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5158 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5159
5160 /*issue disconnect*/
5161 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5162 pAdapter->sessionId, reasonCode);
5163
5164 if ( 0 != status)
5165 {
5166 hddLog(VOS_TRACE_LEVEL_ERROR,
5167 "%s csrRoamDisconnect failure, returned %d \n",
5168 __func__, (int)status );
5169 return -EINVAL;
5170 }
5171
5172 wait_for_completion_interruptible_timeout(
5173 &pAdapter->disconnect_comp_var,
5174 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5175
5176
5177 /*stop tx queues*/
5178 netif_tx_disable(dev);
5179 netif_carrier_off(dev);
5180 }
5181 }
5182 else
5183 {
5184 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5185 }
5186
5187 return status;
5188}
5189
5190/*
5191 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5192 * This function is used to initialize the security
5193 * settings in IBSS mode.
5194 */
5195static int wlan_hdd_cfg80211_set_privacy_ibss(
5196 hdd_adapter_t *pAdapter,
5197 struct cfg80211_ibss_params *params
5198 )
5199{
5200 int status = 0;
5201 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5202 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5203 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5204
5205 ENTER();
5206
5207 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5208
5209 if (params->ie_len && ( NULL != params->ie) )
5210 {
5211 if (WLAN_EID_RSN == params->ie[0])
5212 {
5213 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5214 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5215 }
5216 else
5217 {
5218 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5219 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5220 }
5221 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5222
5223 if (0 > status)
5224 {
5225 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5226 __func__);
5227 return status;
5228 }
5229 }
5230
5231 pWextState->roamProfile.AuthType.authType[0] =
5232 pHddStaCtx->conn_info.authType =
5233 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5234
5235 if (params->privacy)
5236 {
5237 /* Security enabled IBSS, At this time there is no information available
5238 * about the security paramters, so initialise the encryption type to
5239 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5240 * The correct security parameters will be updated later in
5241 * wlan_hdd_cfg80211_add_key */
5242 /* Hal expects encryption type to be set inorder
5243 *enable privacy bit in beacons */
5244
5245 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5246 }
5247
5248 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5249 pWextState->roamProfile.EncryptionType.numEntries = 1;
5250 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5251
5252 return status;
5253}
5254
5255/*
5256 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5257 * This function is used to create/join an IBSS
5258 */
5259static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5260 struct net_device *dev,
5261 struct cfg80211_ibss_params *params
5262 )
5263{
5264 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5265 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5266 tCsrRoamProfile *pRoamProfile;
5267 int status;
5268 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5269
5270 ENTER();
5271
5272 hddLog(VOS_TRACE_LEVEL_INFO,
5273 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5274
5275 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5276 {
5277 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5278 "%s:LOGP in Progress. Ignore!!!", __func__);
5279 return -EAGAIN;
5280 }
5281
5282 if (NULL == pWextState)
5283 {
5284 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5285 __func__);
5286 return -EIO;
5287 }
5288
5289 pRoamProfile = &pWextState->roamProfile;
5290
5291 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5292 {
5293 hddLog (VOS_TRACE_LEVEL_ERROR,
5294 "%s Interface type is not set to IBSS \n", __func__);
5295 return -EINVAL;
5296 }
5297
5298 /* Set Channel */
5299 if (NULL != params->channel)
5300 {
5301 u8 channelNum;
5302 if (IEEE80211_BAND_5GHZ == params->channel->band)
5303 {
5304 hddLog(VOS_TRACE_LEVEL_ERROR,
5305 "%s: IBSS join is called with unsupported band %d",
5306 __func__, params->channel->band);
5307 return -EOPNOTSUPP;
5308 }
5309
5310 /* Get channel number */
5311 channelNum =
5312 ieee80211_frequency_to_channel(params->channel->center_freq);
5313
5314 /*TODO: use macro*/
5315 if (14 >= channelNum)
5316 {
5317 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5318 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5319 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5320 int indx;
5321
5322 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5323 validChan, &numChans))
5324 {
5325 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5326 __func__);
5327 return -EOPNOTSUPP;
5328 }
5329
5330 for (indx = 0; indx < numChans; indx++)
5331 {
5332 if (channelNum == validChan[indx])
5333 {
5334 break;
5335 }
5336 }
5337 if (indx >= numChans)
5338 {
5339 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5340 __func__, channelNum);
5341 return -EINVAL;
5342 }
5343 /* Set the Operational Channel */
5344 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5345 channelNum);
5346 pRoamProfile->ChannelInfo.numOfChannels = 1;
5347 pHddStaCtx->conn_info.operationChannel = channelNum;
5348 pRoamProfile->ChannelInfo.ChannelList =
5349 &pHddStaCtx->conn_info.operationChannel;
5350 }
5351 else
5352 {
5353 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5354 __func__, channelNum);
5355 return -EINVAL;
5356 }
5357 }
5358
5359 /* Initialize security parameters */
5360 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5361 if (status < 0)
5362 {
5363 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5364 __func__);
5365 return status;
5366 }
5367
5368 /* Issue connect start */
5369 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005370 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005371
5372 if (0 > status)
5373 {
5374 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5375 return status;
5376 }
5377
5378 return 0;
5379}
5380
5381/*
5382 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5383 * This function is used to leave an IBSS
5384 */
5385static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5386 struct net_device *dev
5387 )
5388{
5389 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5390 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5391 tCsrRoamProfile *pRoamProfile;
5392
5393 ENTER();
5394
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005395 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5396 {
5397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5398 "%s:LOGP in Progress. Ignore!!!", __func__);
5399 return -EAGAIN;
5400 }
5401
Jeff Johnson295189b2012-06-20 16:38:30 -07005402 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5403 if (NULL == pWextState)
5404 {
5405 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5406 __func__);
5407 return -EIO;
5408 }
5409
5410 pRoamProfile = &pWextState->roamProfile;
5411
5412 /* Issue disconnect only if interface type is set to IBSS */
5413 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5414 {
5415 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5416 __func__);
5417 return -EINVAL;
5418 }
5419
5420 /* Issue Disconnect request */
5421 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5422 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5423 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5424
5425 return 0;
5426}
5427
5428/*
5429 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5430 * This function is used to set the phy parameters
5431 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5432 */
5433static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5434 u32 changed)
5435{
5436 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5437 tHalHandle hHal = pHddCtx->hHal;
5438
5439 ENTER();
5440
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005441 if ( pHddCtx->isLogpInProgress )
5442 {
5443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5444 "%s:LOGP in Progress. Ignore!!!", __func__);
5445 return -EAGAIN;
5446 }
5447
Jeff Johnson295189b2012-06-20 16:38:30 -07005448 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5449 {
5450 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5451 WNI_CFG_RTS_THRESHOLD_STAMAX :
5452 wiphy->rts_threshold;
5453
5454 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5455 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5456 {
5457 hddLog(VOS_TRACE_LEVEL_ERROR,
5458 "%s: Invalid RTS Threshold value %hu",
5459 __func__, rts_threshold);
5460 return -EINVAL;
5461 }
5462
5463 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5464 rts_threshold, ccmCfgSetCallback,
5465 eANI_BOOLEAN_TRUE))
5466 {
5467 hddLog(VOS_TRACE_LEVEL_ERROR,
5468 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5469 __func__, rts_threshold);
5470 return -EIO;
5471 }
5472
5473 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5474 rts_threshold);
5475 }
5476
5477 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5478 {
5479 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5480 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5481 wiphy->frag_threshold;
5482
5483 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5484 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5485 {
5486 hddLog(VOS_TRACE_LEVEL_ERROR,
5487 "%s: Invalid frag_threshold value %hu", __func__,
5488 frag_threshold);
5489 return -EINVAL;
5490 }
5491
5492 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5493 frag_threshold, ccmCfgSetCallback,
5494 eANI_BOOLEAN_TRUE))
5495 {
5496 hddLog(VOS_TRACE_LEVEL_ERROR,
5497 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5498 __func__, frag_threshold);
5499 return -EIO;
5500 }
5501
5502 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5503 frag_threshold);
5504 }
5505
5506 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5507 || (changed & WIPHY_PARAM_RETRY_LONG))
5508 {
5509 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5510 wiphy->retry_short :
5511 wiphy->retry_long;
5512
5513 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5514 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5515 {
5516 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5517 __func__, retry_value);
5518 return -EINVAL;
5519 }
5520
5521 if (changed & WIPHY_PARAM_RETRY_SHORT)
5522 {
5523 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5524 retry_value, ccmCfgSetCallback,
5525 eANI_BOOLEAN_TRUE))
5526 {
5527 hddLog(VOS_TRACE_LEVEL_ERROR,
5528 "%s: ccmCfgSetInt failed for long retry count %hu",
5529 __func__, retry_value);
5530 return -EIO;
5531 }
5532 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5533 __func__, retry_value);
5534 }
5535 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5536 {
5537 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5538 retry_value, ccmCfgSetCallback,
5539 eANI_BOOLEAN_TRUE))
5540 {
5541 hddLog(VOS_TRACE_LEVEL_ERROR,
5542 "%s: ccmCfgSetInt failed for short retry count %hu",
5543 __func__, retry_value);
5544 return -EIO;
5545 }
5546 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5547 __func__, retry_value);
5548 }
5549 }
5550
5551 return 0;
5552}
5553
5554/*
5555 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5556 * This function is used to set the txpower
5557 */
5558static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5559#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5560 enum tx_power_setting type,
5561#else
5562 enum nl80211_tx_power_setting type,
5563#endif
5564 int dbm)
5565{
5566 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5567 tHalHandle hHal = pHddCtx->hHal;
5568 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5569 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5570
5571 ENTER();
5572
5573 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5574 dbm, ccmCfgSetCallback,
5575 eANI_BOOLEAN_TRUE))
5576 {
5577 hddLog(VOS_TRACE_LEVEL_ERROR,
5578 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5579 return -EIO;
5580 }
5581
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005582 if ( pHddCtx->isLogpInProgress )
5583 {
5584 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5585 "%s:LOGP in Progress. Ignore!!!", __func__);
5586 return -EAGAIN;
5587 }
5588
Jeff Johnson295189b2012-06-20 16:38:30 -07005589 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5590 dbm);
5591
5592 switch(type)
5593 {
5594 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5595 /* Fall through */
5596 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5597 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5598 {
5599 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5600 __func__);
5601 return -EIO;
5602 }
5603 break;
5604 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5605 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5606 __func__);
5607 return -EOPNOTSUPP;
5608 break;
5609 default:
5610 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5611 __func__, type);
5612 return -EIO;
5613 }
5614
5615 return 0;
5616}
5617
5618/*
5619 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5620 * This function is used to read the txpower
5621 */
5622static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5623{
5624
5625 hdd_adapter_t *pAdapter;
5626 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5627
Jeff Johnsone7245742012-09-05 17:12:55 -07005628 ENTER();
5629
Jeff Johnson295189b2012-06-20 16:38:30 -07005630 if (NULL == pHddCtx)
5631 {
5632 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5633 *dbm = 0;
5634 return -ENOENT;
5635 }
5636
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005637 if ( pHddCtx->isLogpInProgress )
5638 {
5639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5640 "%s:LOGP in Progress. Ignore!!!", __func__);
5641 return -EAGAIN;
5642 }
5643
Jeff Johnson295189b2012-06-20 16:38:30 -07005644 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5645 if (NULL == pAdapter)
5646 {
5647 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5648 return -ENOENT;
5649 }
5650
5651 wlan_hdd_get_classAstats(pAdapter);
5652 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5653
Jeff Johnsone7245742012-09-05 17:12:55 -07005654 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 return 0;
5656}
5657
5658static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5659 u8* mac, struct station_info *sinfo)
5660{
5661 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5662 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5663 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5664 tANI_U8 rate_flags;
5665
5666 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5667 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5668 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5669
5670 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5671 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5672 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5673 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5674 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5675 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5676 tANI_U16 maxRate = 0;
5677 tANI_U16 myRate;
5678 tANI_U16 currentRate = 0;
5679 tANI_U8 maxSpeedMCS = 0;
5680 tANI_U8 maxMCSIdx = 0;
5681 tANI_U8 rateFlag = 1;
5682 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005683 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005684
Jeff Johnsone7245742012-09-05 17:12:55 -07005685 ENTER();
5686
Jeff Johnson295189b2012-06-20 16:38:30 -07005687 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5688 (0 == ssidlen))
5689 {
5690 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5691 " Invalid ssidlen, %d", __func__, ssidlen);
5692 /*To keep GUI happy*/
5693 return 0;
5694 }
5695
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005696 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5697 {
5698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5699 "%s:LOGP in Progress. Ignore!!!", __func__);
5700 return -EAGAIN;
5701 }
5702
Jeff Johnson295189b2012-06-20 16:38:30 -07005703 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5704 sinfo->filled |= STATION_INFO_SIGNAL;
5705
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005706 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005707 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5708
5709 //convert to the UI units of 100kbps
5710 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5711
5712#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005713 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 -07005714 sinfo->signal,
5715 pCfg->reportMaxLinkSpeed,
5716 myRate,
5717 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005718 (int) pCfg->linkSpeedRssiMid,
5719 (int) pCfg->linkSpeedRssiLow,
5720 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005721#endif //LINKSPEED_DEBUG_ENABLED
5722
5723 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5724 {
5725 // we do not want to necessarily report the current speed
5726 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5727 {
5728 // report the max possible speed
5729 rssidx = 0;
5730 }
5731 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5732 {
5733 // report the max possible speed with RSSI scaling
5734 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5735 {
5736 // report the max possible speed
5737 rssidx = 0;
5738 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005739 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005740 {
5741 // report middle speed
5742 rssidx = 1;
5743 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005744 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5745 {
5746 // report middle speed
5747 rssidx = 2;
5748 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005749 else
5750 {
5751 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005752 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 }
5754 }
5755 else
5756 {
5757 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5758 hddLog(VOS_TRACE_LEVEL_ERROR,
5759 "%s: Invalid value for reportMaxLinkSpeed: %u",
5760 __func__, pCfg->reportMaxLinkSpeed);
5761 rssidx = 0;
5762 }
5763
5764 maxRate = 0;
5765
5766 /* Get Basic Rate Set */
5767 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5768 for (i = 0; i < ORLeng; i++)
5769 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005770 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005771 {
5772 /* Validate Rate Set */
5773 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5774 {
5775 currentRate = supported_data_rate[j].supported_rate[rssidx];
5776 break;
5777 }
5778 }
5779 /* Update MAX rate */
5780 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5781 }
5782
5783 /* Get Extended Rate Set */
5784 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5785 for (i = 0; i < ERLeng; i++)
5786 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005787 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005788 {
5789 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5790 {
5791 currentRate = supported_data_rate[j].supported_rate[rssidx];
5792 break;
5793 }
5794 }
5795 /* Update MAX rate */
5796 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5797 }
5798
5799 /* Get MCS Rate Set -- but only if we are connected at MCS
5800 rates or if we are always reporting max speed or if we have
5801 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005802 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005803 {
5804 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5805 rateFlag = 0;
5806 if (rate_flags & eHAL_TX_RATE_HT40)
5807 {
5808 rateFlag |= 1;
5809 }
5810 if (rate_flags & eHAL_TX_RATE_SGI)
5811 {
5812 rateFlag |= 2;
5813 }
5814
5815 for (i = 0; i < MCSLeng; i++)
5816 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005817 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5818 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005819 {
5820 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5821 {
5822 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5823 break;
5824 }
5825 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005826 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 {
5828 maxRate = currentRate;
5829 maxSpeedMCS = 1;
5830 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5831 }
5832 }
5833 }
5834
5835 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005836 if (((maxRate < myRate) && (0 == rssidx)) ||
5837 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 {
5839 maxRate = myRate;
5840 if (rate_flags & eHAL_TX_RATE_LEGACY)
5841 {
5842 maxSpeedMCS = 0;
5843 }
5844 else
5845 {
5846 maxSpeedMCS = 1;
5847 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5848 }
5849 }
5850
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005851 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005852 {
5853 sinfo->txrate.legacy = maxRate;
5854#ifdef LINKSPEED_DEBUG_ENABLED
5855 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5856#endif //LINKSPEED_DEBUG_ENABLED
5857 }
5858 else
5859 {
5860 sinfo->txrate.mcs = maxMCSIdx;
5861 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5862 if (rate_flags & eHAL_TX_RATE_SGI)
5863 {
5864 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5865 }
5866 if (rate_flags & eHAL_TX_RATE_HT40)
5867 {
5868 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5869 }
5870#ifdef LINKSPEED_DEBUG_ENABLED
5871 pr_info("Reporting MCS rate %d flags %x\n",
5872 sinfo->txrate.mcs,
5873 sinfo->txrate.flags );
5874#endif //LINKSPEED_DEBUG_ENABLED
5875 }
5876 }
5877 else
5878 {
5879 // report current rate instead of max rate
5880
5881 if (rate_flags & eHAL_TX_RATE_LEGACY)
5882 {
5883 //provide to the UI in units of 100kbps
5884 sinfo->txrate.legacy = myRate;
5885#ifdef LINKSPEED_DEBUG_ENABLED
5886 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5887#endif //LINKSPEED_DEBUG_ENABLED
5888 }
5889 else
5890 {
5891 //must be MCS
5892 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5893 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5894 if (rate_flags & eHAL_TX_RATE_SGI)
5895 {
5896 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5897 }
5898 if (rate_flags & eHAL_TX_RATE_HT40)
5899 {
5900 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5901 }
5902#ifdef LINKSPEED_DEBUG_ENABLED
5903 pr_info("Reporting actual MCS rate %d flags %x\n",
5904 sinfo->txrate.mcs,
5905 sinfo->txrate.flags );
5906#endif //LINKSPEED_DEBUG_ENABLED
5907 }
5908 }
5909 sinfo->filled |= STATION_INFO_TX_BITRATE;
5910
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005911 sinfo->tx_packets =
5912 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5913 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5914 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5915 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5916
5917 sinfo->tx_retries =
5918 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
5919 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
5920 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
5921 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
5922
5923 sinfo->tx_failed =
5924 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
5925 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
5926 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
5927 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
5928
5929 sinfo->filled |=
5930 STATION_INFO_TX_PACKETS |
5931 STATION_INFO_TX_RETRIES |
5932 STATION_INFO_TX_FAILED;
5933
5934 EXIT();
5935 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005936}
5937
5938static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
5939 struct net_device *dev, bool mode, v_SINT_t timeout)
5940{
5941 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5942 VOS_STATUS vos_status;
5943
Jeff Johnsone7245742012-09-05 17:12:55 -07005944 ENTER();
5945
Jeff Johnson295189b2012-06-20 16:38:30 -07005946 if (NULL == pAdapter)
5947 {
5948 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5949 return -ENODEV;
5950 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005951 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5952 {
5953 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5954 "%s:LOGP in Progress. Ignore!!!", __func__);
5955 return -EAGAIN;
5956 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005957
5958 /**The get power cmd from the supplicant gets updated by the nl only
5959 *on successful execution of the function call
5960 *we are oppositely mapped w.r.t mode in the driver
5961 **/
5962 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
5963
Jeff Johnsone7245742012-09-05 17:12:55 -07005964 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005965 if (VOS_STATUS_E_FAILURE == vos_status)
5966 {
5967 return -EINVAL;
5968 }
5969 return 0;
5970}
5971
5972
5973#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5974static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
5975 struct net_device *netdev,
5976 u8 key_index)
5977{
Jeff Johnsone7245742012-09-05 17:12:55 -07005978 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005979 return 0;
5980}
5981#endif //LINUX_VERSION_CODE
5982
5983#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5984static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5985 struct net_device *dev,
5986 struct ieee80211_txq_params *params)
5987{
Jeff Johnsone7245742012-09-05 17:12:55 -07005988 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005989 return 0;
5990}
5991#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5992static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5993 struct ieee80211_txq_params *params)
5994{
Jeff Johnsone7245742012-09-05 17:12:55 -07005995 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005996 return 0;
5997}
5998#endif //LINUX_VERSION_CODE
5999
6000static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6001 struct net_device *dev, u8 *mac)
6002{
6003 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6004
Jeff Johnsone7245742012-09-05 17:12:55 -07006005 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006006 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6007 {
6008 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6009 return -EINVAL;
6010 }
6011
6012 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6013 {
6014 hddLog( LOGE,
6015 "%s: Wlan Load/Unload is in progress", __func__);
6016 return -EBUSY;
6017 }
6018
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006019 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6020 {
6021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6022 "%s:LOGP in Progress. Ignore!!!", __func__);
6023 return -EAGAIN;
6024 }
6025
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6027#ifdef WLAN_FEATURE_P2P
6028 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6029#endif
6030 )
6031 {
6032 if( NULL == mac )
6033 {
6034 v_U16_t i;
6035 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6036 {
6037 if(pAdapter->aStaInfo[i].isUsed)
6038 {
6039 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6040 hddLog(VOS_TRACE_LEVEL_INFO,
6041 "%s: Delete STA with MAC::"
6042 "%02x:%02x:%02x:%02x:%02x:%02x",
6043 __func__,
6044 macAddr[0], macAddr[1], macAddr[2],
6045 macAddr[3], macAddr[4], macAddr[5]);
6046 hdd_softap_sta_deauth(pAdapter, macAddr);
6047 }
6048 }
6049 }
6050 else
6051 {
6052 hddLog(VOS_TRACE_LEVEL_INFO,
6053 "%s: Delete STA with MAC::"
6054 "%02x:%02x:%02x:%02x:%02x:%02x",
6055 __func__,
6056 mac[0], mac[1], mac[2],
6057 mac[3], mac[4], mac[5]);
6058 hdd_softap_sta_deauth(pAdapter, mac);
6059 }
6060 }
6061
6062 EXIT();
6063
6064 return 0;
6065}
6066
6067static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6068 struct net_device *dev, u8 *mac, struct station_parameters *params)
6069{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006070#ifdef FEATURE_WLAN_TDLS
6071 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6072 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6073 u32 mask, set;
6074 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006075 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006076
6077 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6078 {
6079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6080 "Invalid arguments");
6081 return -EINVAL;
6082 }
6083
6084 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6085 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6086 {
6087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6088 "TDLS Disabled in INI OR not enabled in FW.\
6089 Cannot process TDLS commands \n");
6090 return -ENOTSUPP;
6091 }
6092
6093 mask = params->sta_flags_mask;
6094
6095 set = params->sta_flags_set;
6096
6097
6098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6099 "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
6100
6101 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6102 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6104 "Add TDLS peer");
6105
6106
6107 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6108 pAdapter->sessionId, mac);
6109
6110 if (VOS_STATUS_SUCCESS != status) {
6111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6112 "%s: sme_AddTdlsPeerSta failed!", __func__);
6113 }
6114 }
6115 }
6116#endif
6117
Jeff Johnson295189b2012-06-20 16:38:30 -07006118 return 0;
6119}
6120
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006121
6122#ifdef FEATURE_WLAN_LFR
6123static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006124 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006125{
6126#define MAX_PMKSAIDS_IN_CACHE 8
6127 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006128 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006129 tANI_U32 j=0;
6130 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6131 tHalHandle halHandle;
6132 eHalStatus result;
6133 tANI_U8 BSSIDMatched = 0;
6134
Jeff Johnsone7245742012-09-05 17:12:55 -07006135 ENTER();
6136
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006137 // Validate pAdapter
6138 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6139 {
6140 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6141 return -EINVAL;
6142 }
6143
6144 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6145 {
6146 hddLog( LOGE,
6147 "%s: Wlan Load/Unload is in progress", __func__);
6148 return -EBUSY;
6149 }
6150
6151 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6152 {
6153 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6154 "%s:LOGP in Progress. Ignore!!!", __func__);
6155 return -EAGAIN;
6156 }
6157
6158 // Retrieve halHandle
6159 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6160
6161 for (j = 0; j < i; j++)
6162 {
6163 if(vos_mem_compare(PMKIDCache[j].BSSID,
6164 pmksa->bssid, WNI_CFG_BSSID_LEN))
6165 {
6166 /* BSSID matched previous entry. Overwrite it. */
6167 BSSIDMatched = 1;
6168 vos_mem_copy(PMKIDCache[j].BSSID,
6169 pmksa->bssid, WNI_CFG_BSSID_LEN);
6170 vos_mem_copy(PMKIDCache[j].PMKID,
6171 pmksa->pmkid,
6172 CSR_RSN_PMKID_SIZE);
6173 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006174 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006175 dump_bssid(pmksa->bssid);
6176 dump_pmkid(halHandle, pmksa->pmkid);
6177 break;
6178 }
6179 }
6180
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006181 /* Check we compared all entries,if then take the first slot now */
6182 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6183
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006184 if (!BSSIDMatched)
6185 {
6186 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6187 vos_mem_copy(PMKIDCache[i].BSSID,
6188 pmksa->bssid, ETHER_ADDR_LEN);
6189 vos_mem_copy(PMKIDCache[i].PMKID,
6190 pmksa->pmkid,
6191 CSR_RSN_PMKID_SIZE);
6192 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006193 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006194 dump_bssid(pmksa->bssid);
6195 dump_pmkid(halHandle, pmksa->pmkid);
6196 // Increment the HDD Local Cache index
6197 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6198 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6199 }
6200
6201
6202 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6203 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006204 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006205 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006206 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006207 // Finally set the PMKSA ID Cache in CSR
6208 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6209 PMKIDCache,
6210 i );
6211 return 0;
6212}
6213
6214
6215static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006216 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006217{
Jeff Johnsone7245742012-09-05 17:12:55 -07006218 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006219 // TODO: Implement this later.
6220 return 0;
6221}
6222
6223static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6224{
Jeff Johnsone7245742012-09-05 17:12:55 -07006225 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006226 // TODO: Implement this later.
6227 return 0;
6228}
6229#endif
6230
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006231#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6232static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6233 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6234{
6235 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6236 hdd_station_ctx_t *pHddStaCtx;
6237
6238 if (NULL == pAdapter)
6239 {
6240 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6241 return -ENODEV;
6242 }
6243
6244 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6245
6246 // Added for debug on reception of Re-assoc Req.
6247 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6248 {
6249 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6250 ftie->ie_len);
6251 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6252 }
6253
6254#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6255 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6256 ftie->ie_len);
6257#endif
6258
6259 // Pass the received FT IEs to SME
6260 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6261 ftie->ie_len);
6262 return 0;
6263}
6264#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006265
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006266#ifdef FEATURE_WLAN_TDLS
6267static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6268 u8 *peer, u8 action_code, u8 dialog_token,
6269 u16 status_code, const u8 *buf, size_t len)
6270{
6271
6272 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6273 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6274 u8 *buf_1;
6275 size_t len_1 = len;
6276 u8 peerMac[6];
6277 VOS_STATUS status;
6278
6279 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6280 {
6281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6282 "Invalid arguments");
6283 return -EINVAL;
6284 }
6285
6286 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6287 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6288 {
6289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6290 "TDLS Disabled in INI OR not enabled in FW.\
6291 Cannot process TDLS commands \n");
6292 return -ENOTSUPP;
6293 }
6294 vos_mem_copy( peerMac, peer, 6);
6295
6296 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6297 "Request to send TDLS management: action = %d, status = %d, \
Ng Chilamfc416462012-12-27 17:26:52 -08006298 len = %d", action_code, status_code, len);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006299
6300 buf_1 = vos_mem_malloc(len);
6301 if(buf_1 == NULL) {
6302 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6303 "%s: malloc failed!", __func__);
6304 return -ENOMEM;
6305 }
6306 vos_mem_copy(buf_1, buf, len);
6307
6308 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6309 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6310
6311 if (VOS_STATUS_SUCCESS != status) {
6312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6313 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6314 }
6315
6316 vos_mem_free(buf_1);
6317
6318 return 0;
6319}
6320
6321static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6322 u8 *peer, enum nl80211_tdls_operation oper)
6323{
6324 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6325 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6326
6327 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6328 {
6329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6330 "Invalid arguments");
6331 return -EINVAL;
6332 }
6333
6334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6335 "Request for TDLS oper: %d", (int)oper);
6336
6337 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6338 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6339 {
6340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6341 "TDLS Disabled in INI OR not enabled in FW.\
6342 Cannot process TDLS commands \n");
6343 return -ENOTSUPP;
6344 }
6345
6346 switch (oper) {
6347 case NL80211_TDLS_ENABLE_LINK:
6348 {
6349 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6350 v_U8_t my_peer[6];
6351 v_U8_t ucSTAId;
6352 VOS_STATUS status;
6353
6354 if (peer) {
6355 vos_mem_copy(my_peer, peer, 6);
6356 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6357
6358 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6359 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6360 __func__, peer[0], peer[1],
6361 peer[2], peer[3],
6362 peer[4], peer[5] );
6363
6364 if (-1 == ucSTAId ) {
6365 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
6366 return 0;
6367 }
6368
6369 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6370 WLANTL_STA_AUTHENTICATED );
6371
6372 if (0 != status) {
6373 hddLog(VOS_TRACE_LEVEL_ERROR,
6374 "%s: WLANTL_ChangeSTAState failed, returned %d",
6375 __func__, status);
6376 return status;
6377 }
6378 } else {
6379 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6380 }
6381 }
6382 break;
6383 case NL80211_TDLS_DISABLE_LINK:
6384 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6385 pAdapter->sessionId, peer );
6386 return 0;
6387 case NL80211_TDLS_TEARDOWN:
6388 case NL80211_TDLS_SETUP:
6389 case NL80211_TDLS_DISCOVERY_REQ:
6390 /* We don't support in-driver setup/teardown/discovery */
6391 return -ENOTSUPP;
6392 default:
6393 return -ENOTSUPP;
6394 }
6395 return 0;
6396}
6397#endif
6398
Jeff Johnson295189b2012-06-20 16:38:30 -07006399/* cfg80211_ops */
6400static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6401{
6402 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6403 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6404 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6405 .change_station = wlan_hdd_change_station,
6406#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6407 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6408 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6409 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006410#else
6411 .start_ap = wlan_hdd_cfg80211_start_ap,
6412 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6413 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006414#endif
6415 .change_bss = wlan_hdd_cfg80211_change_bss,
6416 .add_key = wlan_hdd_cfg80211_add_key,
6417 .get_key = wlan_hdd_cfg80211_get_key,
6418 .del_key = wlan_hdd_cfg80211_del_key,
6419 .set_default_key = wlan_hdd_cfg80211_set_default_key,
6420 .set_channel = wlan_hdd_cfg80211_set_channel,
6421 .scan = wlan_hdd_cfg80211_scan,
6422 .connect = wlan_hdd_cfg80211_connect,
6423 .disconnect = wlan_hdd_cfg80211_disconnect,
6424 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6425 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6426 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6427 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6428 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6429#ifdef WLAN_FEATURE_P2P
6430 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6431 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6432 .mgmt_tx = wlan_hdd_action,
6433#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6434 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6435 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6436 .set_txq_params = wlan_hdd_set_txq_params,
6437#endif
6438#endif
6439 .get_station = wlan_hdd_cfg80211_get_station,
6440 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6441 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006442 .add_station = wlan_hdd_cfg80211_add_station,
6443#ifdef FEATURE_WLAN_LFR
6444 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6445 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6446 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6447#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006448#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6449 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6450#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006451#ifdef FEATURE_WLAN_TDLS
6452 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6453 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6454#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006455};
6456
6457#endif // CONFIG_CFG80211