blob: 28b9b1758ae187404d25a4e1af35c58c01911659 [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
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
355#ifdef WLAN_FEATURE_P2P
356static const struct ieee80211_iface_limit
357wlan_hdd_iface_limit[] = {
358 {
359 /* max=2 is to support JellyBean architecture which has wlan0
360 * and p2p0 interfaces during init. p2p0 is considered station
361 * interface until a group is formed */
362 .max = 2,
363 .types = BIT(NL80211_IFTYPE_STATION),
364 },
365 {
366 .max = 1,
367 .types = BIT(NL80211_IFTYPE_AP),
368 },
369 {
370 .max = 1,
371 .types = BIT(NL80211_IFTYPE_P2P_GO) |
372 BIT(NL80211_IFTYPE_P2P_CLIENT),
373 },
374};
375
376/* By default, only single channel concurrency is allowed */
377static struct ieee80211_iface_combination
378wlan_hdd_iface_combination = {
379 .limits = wlan_hdd_iface_limit,
380 .num_different_channels = 1,
381 .max_interfaces = 2,
382 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
383 .beacon_int_infra_match = false,
384};
385#endif
386#endif
387
Jeff Johnson295189b2012-06-20 16:38:30 -0700388static struct cfg80211_ops wlan_hdd_cfg80211_ops;
389
390/* Data rate 100KBPS based on IE Index */
391struct index_data_rate_type
392{
393 v_U8_t beacon_rate_index;
394 v_U16_t supported_rate[4];
395};
396
397/* 11B, 11G Rate table include Basic rate and Extended rate
398 The IDX field is the rate index
399 The HI field is the rate when RSSI is strong or being ignored
400 (in this case we report actual rate)
401 The MID field is the rate when RSSI is moderate
402 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
403 The LO field is the rate when RSSI is low
404 (in this case we don't report rates, actual current rate used)
405 */
406static const struct
407{
408 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700409 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700410} supported_data_rate[] =
411{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700412/* IDX HI HM LM LO (RSSI-based index */
413 {2, { 10, 10, 10, 0}},
414 {4, { 20, 20, 10, 0}},
415 {11, { 55, 20, 10, 0}},
416 {12, { 60, 55, 20, 0}},
417 {18, { 90, 55, 20, 0}},
418 {22, {110, 55, 20, 0}},
419 {24, {120, 90, 60, 0}},
420 {36, {180, 120, 60, 0}},
421 {44, {220, 180, 60, 0}},
422 {48, {240, 180, 90, 0}},
423 {66, {330, 180, 90, 0}},
424 {72, {360, 240, 90, 0}},
425 {96, {480, 240, 120, 0}},
426 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700427};
428
429/* MCS Based rate table */
430static struct index_data_rate_type supported_mcs_rate[] =
431{
432/* MCS L20 L40 S20 S40 */
433 {0, {65, 135, 72, 150}},
434 {1, {130, 270, 144, 300}},
435 {2, {195, 405, 217, 450}},
436 {3, {260, 540, 289, 600}},
437 {4, {390, 810, 433, 900}},
438 {5, {520, 1080, 578, 1200}},
439 {6, {585, 1215, 650, 1350}},
440 {7, {650, 1350, 722, 1500}}
441};
442
443extern struct net_device_ops net_ops_struct;
444
445/*
446 * FUNCTION: wlan_hdd_cfg80211_init
447 * This function is called by hdd_wlan_startup()
448 * during initialization.
449 * This function is used to initialize and register wiphy structure.
450 */
451struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
452{
453 struct wiphy *wiphy;
454 ENTER();
455
456 /*
457 * Create wiphy device
458 */
459 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
460
461 if (!wiphy)
462 {
463 /* Print error and jump into err label and free the memory */
464 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
465 return NULL;
466 }
467
468 return wiphy;
469}
470
471/*
472 * FUNCTION: wlan_hdd_cfg80211_update_band
473 * This function is called from the supplicant through a
474 * private ioctl to change the band value
475 */
476int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
477{
Jeff Johnsone7245742012-09-05 17:12:55 -0700478 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700479 switch(eBand)
480 {
481 case eCSR_BAND_24:
482 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
483 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
484 break;
485 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700486#ifdef WLAN_FEATURE_P2P
487 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
488#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700489 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700490#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700491 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
492 break;
493 case eCSR_BAND_ALL:
494 default:
495 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
496 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
497 }
498 return 0;
499}
500/*
501 * FUNCTION: wlan_hdd_cfg80211_init
502 * This function is called by hdd_wlan_startup()
503 * during initialization.
504 * This function is used to initialize and register wiphy structure.
505 */
506int wlan_hdd_cfg80211_register(struct device *dev,
507 struct wiphy *wiphy,
508 hdd_config_t *pCfg
509 )
510{
Jeff Johnsone7245742012-09-05 17:12:55 -0700511 ENTER();
512
Jeff Johnson295189b2012-06-20 16:38:30 -0700513 /* Now bind the underlying wlan device with wiphy */
514 set_wiphy_dev(wiphy, dev);
515
516 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
517
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700518 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700519
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700520#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700521 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
522 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
523 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700524 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700525#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800526#ifdef FEATURE_WLAN_TDLS
527 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
528 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
529#endif
530
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700531 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
532 driver can still register regulatory callback and
533 it will get CRDA setting in wiphy->band[], but
534 driver need to determine what to do with both
535 regulatory settings */
536 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700537
Jeff Johnson295189b2012-06-20 16:38:30 -0700538 wiphy->max_scan_ssids = MAX_SCAN_SSID;
539
540 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
541
542 /* Supports STATION & AD-HOC modes right now */
543 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
544 | BIT(NL80211_IFTYPE_ADHOC)
545#ifdef WLAN_FEATURE_P2P
546 | BIT(NL80211_IFTYPE_P2P_CLIENT)
547 | BIT(NL80211_IFTYPE_P2P_GO)
548#endif
549 | BIT(NL80211_IFTYPE_AP);
550
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800551#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
552#ifdef WLAN_FEATURE_P2P
553 if( pCfg->enableMCC )
554 {
555 /* Currently, supports up to two channels */
556 wlan_hdd_iface_combination.num_different_channels = 2;
557
558 if( !pCfg->allowMCCGODiffBI )
559 wlan_hdd_iface_combination.beacon_int_infra_match = true;
560
561 }
562 wiphy->iface_combinations = &wlan_hdd_iface_combination;
563 wiphy->n_iface_combinations = 1;
564#endif
565#endif
566
Jeff Johnson295189b2012-06-20 16:38:30 -0700567 /* Before registering we need to update the ht capabilitied based
568 * on ini values*/
569 if( !pCfg->ShortGI20MhzEnable )
570 {
571 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
572 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
573 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
574 }
575
576 if( !pCfg->ShortGI40MhzEnable )
577 {
578 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
579 }
580
581 if( !pCfg->nChannelBondingMode5GHz )
582 {
583 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
584 }
585
586 /*Initialize band capability*/
587 switch(pCfg->nBandCapability)
588 {
589 case eCSR_BAND_24:
590 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
591 break;
592 case eCSR_BAND_5G:
593#ifdef WLAN_FEATURE_P2P
594 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
595#endif
596 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
597 break;
598 case eCSR_BAND_ALL:
599 default:
600 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
601 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
602 }
603 /*Initialise the supported cipher suite details*/
604 wiphy->cipher_suites = hdd_cipher_suites;
605 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
606
607 /*signal strength in mBm (100*dBm) */
608 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
609
610#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
611#ifdef WLAN_FEATURE_P2P
612 wiphy->max_remain_on_channel_duration = 1000;
613#endif
614#endif
615
616 /* Register our wiphy dev with cfg80211 */
617 if (0 > wiphy_register(wiphy))
618 {
619 /* print eror */
620 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
621 return -EIO;
622 }
623
624 EXIT();
625 return 0;
626}
627
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700628/* In this function we will try to get default country code from crda.
629 If the gCrdaDefaultCountryCode is configured in ini file,
630 we will try to call user space crda to get the regulatory settings for
631 that country. We will timeout if we can't get it from crda.
632 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
633*/
634int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
635{
636 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
637 if (memcmp(pCfg->crdaDefaultCountryCode,
638 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
639 {
640 init_completion(&pHddCtx->driver_crda_req);
641 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
642 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
643 CRDA_WAIT_TIME);
644 }
645 return 0;
646}
647
Jeff Johnson295189b2012-06-20 16:38:30 -0700648/* In this function we will do all post VOS start initialization.
649 In this function we will register for all frame in which supplicant
650 is interested.
651*/
652void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
653{
654#ifdef WLAN_FEATURE_P2P
655 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
656 /* Register for all P2P action, public action etc frames */
657 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
658
Jeff Johnsone7245742012-09-05 17:12:55 -0700659 ENTER();
660
Jeff Johnson295189b2012-06-20 16:38:30 -0700661 /* Right now we are registering these frame when driver is getting
662 initialized. Once we will move to 2.6.37 kernel, in which we have
663 frame register ops, we will move this code as a part of that */
664 /* GAS Initial Request */
665 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
666 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
667
668 /* GAS Initial Response */
669 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
670 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
671
672 /* GAS Comeback Request */
673 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
674 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
675
676 /* GAS Comeback Response */
677 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
678 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
679
680 /* P2P Public Action */
681 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
682 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
683 P2P_PUBLIC_ACTION_FRAME_SIZE );
684
685 /* P2P Action */
686 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
687 (v_U8_t*)P2P_ACTION_FRAME,
688 P2P_ACTION_FRAME_SIZE );
689#endif /* WLAN_FEATURE_P2P */
690}
691
692void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
693{
694#ifdef WLAN_FEATURE_P2P
695 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
696 /* Register for all P2P action, public action etc frames */
697 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
698
Jeff Johnsone7245742012-09-05 17:12:55 -0700699 ENTER();
700
Jeff Johnson295189b2012-06-20 16:38:30 -0700701 /* Right now we are registering these frame when driver is getting
702 initialized. Once we will move to 2.6.37 kernel, in which we have
703 frame register ops, we will move this code as a part of that */
704 /* GAS Initial Request */
705
706 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
707 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
708
709 /* GAS Initial Response */
710 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
711 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
712
713 /* GAS Comeback Request */
714 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
715 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
716
717 /* GAS Comeback Response */
718 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
719 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
720
721 /* P2P Public Action */
722 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
723 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
724 P2P_PUBLIC_ACTION_FRAME_SIZE );
725
726 /* P2P Action */
727 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
728 (v_U8_t*)P2P_ACTION_FRAME,
729 P2P_ACTION_FRAME_SIZE );
730#endif /* WLAN_FEATURE_P2P */
731}
732
733#ifdef FEATURE_WLAN_WAPI
734void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
735 const u8 *mac_addr, u8 *key , int key_Len)
736{
737 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
738 tCsrRoamSetKey setKey;
739 v_BOOL_t isConnected = TRUE;
740 int status = 0;
741 v_U32_t roamId= 0xFF;
742 tANI_U8 *pKeyPtr = NULL;
743 int n = 0;
744
745 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
746 __func__,pAdapter->device_mode);
747
748 setKey.keyId = key_index; // Store Key ID
749 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
750 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
751 setKey.paeRole = 0 ; // the PAE role
752 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
753 {
754 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
755 }
756 else
757 {
758 isConnected = hdd_connIsConnected(pHddStaCtx);
759 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
760 }
761 setKey.keyLength = key_Len;
762 pKeyPtr = setKey.Key;
763 memcpy( pKeyPtr, key, key_Len);
764
765 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
766 __func__, key_Len);
767 for (n = 0 ; n < key_Len; n++)
768 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
769 __func__,n,setKey.Key[n]);
770
771 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
772 if ( isConnected )
773 {
774 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
775 pAdapter->sessionId, &setKey, &roamId );
776 }
777 if ( status != 0 )
778 {
779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
780 "[%4d] sme_RoamSetKey returned ERROR status= %d",
781 __LINE__, status );
782 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
783 }
784}
785#endif /* FEATURE_WLAN_WAPI*/
786
787#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
788int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
789 beacon_data_t **ppBeacon,
790 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700791#else
792int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
793 beacon_data_t **ppBeacon,
794 struct cfg80211_beacon_data *params,
795 int dtim_period)
796#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700797{
798 int size;
799 beacon_data_t *beacon = NULL;
800 beacon_data_t *old = NULL;
801 int head_len,tail_len;
802
Jeff Johnsone7245742012-09-05 17:12:55 -0700803 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700804 if (params->head && !params->head_len)
805 return -EINVAL;
806
807 old = pAdapter->sessionCtx.ap.beacon;
808
809 if (!params->head && !old)
810 return -EINVAL;
811
812 if (params->tail && !params->tail_len)
813 return -EINVAL;
814
815#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
816 /* Kernel 3.0 is not updating dtim_period for set beacon */
817 if (!params->dtim_period)
818 return -EINVAL;
819#endif
820
821 if(params->head)
822 head_len = params->head_len;
823 else
824 head_len = old->head_len;
825
826 if(params->tail || !old)
827 tail_len = params->tail_len;
828 else
829 tail_len = old->tail_len;
830
831 size = sizeof(beacon_data_t) + head_len + tail_len;
832
833 beacon = kzalloc(size, GFP_KERNEL);
834
835 if( beacon == NULL )
836 return -ENOMEM;
837
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700838#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700839 if(params->dtim_period || !old )
840 beacon->dtim_period = params->dtim_period;
841 else
842 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700843#else
844 if(dtim_period || !old )
845 beacon->dtim_period = dtim_period;
846 else
847 beacon->dtim_period = old->dtim_period;
848#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700849
850 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
851 beacon->tail = beacon->head + head_len;
852 beacon->head_len = head_len;
853 beacon->tail_len = tail_len;
854
855 if(params->head) {
856 memcpy (beacon->head,params->head,beacon->head_len);
857 }
858 else {
859 if(old)
860 memcpy (beacon->head,old->head,beacon->head_len);
861 }
862
863 if(params->tail) {
864 memcpy (beacon->tail,params->tail,beacon->tail_len);
865 }
866 else {
867 if(old)
868 memcpy (beacon->tail,old->tail,beacon->tail_len);
869 }
870
871 *ppBeacon = beacon;
872
873 kfree(old);
874
875 return 0;
876
877}
Jeff Johnson295189b2012-06-20 16:38:30 -0700878
879v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
880{
881 int left = length;
882 v_U8_t *ptr = pIes;
883 v_U8_t elem_id,elem_len;
884
885 while(left >= 2)
886 {
887 elem_id = ptr[0];
888 elem_len = ptr[1];
889 left -= 2;
890 if(elem_len > left)
891 {
892 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700893 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700894 eid,elem_len,left);
895 return NULL;
896 }
897 if (elem_id == eid)
898 {
899 return ptr;
900 }
901
902 left -= elem_len;
903 ptr += (elem_len + 2);
904 }
905 return NULL;
906}
907
Jeff Johnson295189b2012-06-20 16:38:30 -0700908/* Check if rate is 11g rate or not */
909static int wlan_hdd_rate_is_11g(u8 rate)
910{
911 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
912 u8 i;
913 for (i = 0; i < 8; i++)
914 {
915 if(rate == gRateArray[i])
916 return TRUE;
917 }
918 return FALSE;
919}
920
921/* Check for 11g rate and set proper 11g only mode */
922static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
923 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
924{
925 u8 i, num_rates = pIe[0];
926
927 pIe += 1;
928 for ( i = 0; i < num_rates; i++)
929 {
930 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
931 {
932 /* If rate set have 11g rate than change the mode to 11G */
933 *pSapHw_mode = eSAP_DOT11_MODE_11g;
934 if (pIe[i] & BASIC_RATE_MASK)
935 {
936 /* If we have 11g rate as basic rate, it means mode
937 is 11g only mode.
938 */
939 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
940 *pCheckRatesfor11g = FALSE;
941 }
942 }
943 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
944 {
945 *require_ht = TRUE;
946 }
947 }
948 return;
949}
950
951static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
952{
953 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
954 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
955 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
956 u8 checkRatesfor11g = TRUE;
957 u8 require_ht = FALSE;
958 u8 *pIe=NULL;
959
960 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
961
962 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
963 pBeacon->head_len, WLAN_EID_SUPP_RATES);
964 if (pIe != NULL)
965 {
966 pIe += 1;
967 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
968 &pConfig->SapHw_mode);
969 }
970
971 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
972 WLAN_EID_EXT_SUPP_RATES);
973 if (pIe != NULL)
974 {
975
976 pIe += 1;
977 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
978 &pConfig->SapHw_mode);
979 }
980
981 if( pConfig->channel > 14 )
982 {
983 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
984 }
985
986 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
987 WLAN_EID_HT_CAPABILITY);
988
989 if(pIe)
990 {
991 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
992 if(require_ht)
993 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
994 }
995}
996
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700997#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700998static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
999 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001000#else
1001static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1002 struct cfg80211_beacon_data *params)
1003#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001004{
1005 v_U8_t *genie;
1006 v_U8_t total_ielen = 0, ielen = 0;
1007 v_U8_t *pIe = NULL;
1008 v_U8_t addIE[1] = {0};
1009 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -07001010 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001011
1012 genie = vos_mem_malloc(MAX_GENIE_LEN);
1013
1014 if(genie == NULL) {
1015
1016 return -ENOMEM;
1017 }
1018
1019 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1020
1021 if(pIe)
1022 {
1023 /*Copy the wps IE*/
1024 ielen = pIe[1] + 2;
1025 if( ielen <=MAX_GENIE_LEN)
1026 {
1027 vos_mem_copy(genie, pIe, ielen);
1028 }
1029 else
1030 {
1031 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001032 ret = -EINVAL;
1033 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001034 }
1035 total_ielen = ielen;
1036 }
1037
1038#ifdef WLAN_FEATURE_WFD
1039 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1040
1041 if(pIe)
1042 {
1043 ielen = pIe[1] + 2;
1044 if(total_ielen + ielen <= MAX_GENIE_LEN) {
1045 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
1046 }
1047 else {
1048 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001049 ret = -EINVAL;
1050 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001051 }
1052 total_ielen += ielen;
1053 }
1054#endif
1055
1056#ifdef WLAN_FEATURE_P2P
1057 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1058
1059 if(pIe)
1060 {
1061 ielen = pIe[1] + 2;
1062 if(total_ielen + ielen <= MAX_GENIE_LEN)
1063 {
1064 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1065 }
1066 else
1067 {
1068 hddLog( VOS_TRACE_LEVEL_ERROR,
1069 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001070 ret = -EINVAL;
1071 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001072 }
1073 total_ielen += ielen;
1074 }
1075#endif
1076
1077 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1078 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1079 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1080 {
1081 hddLog(LOGE,
1082 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001083 ret = -EINVAL;
1084 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001085 }
1086
1087 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1088 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1089 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1090 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1091 ==eHAL_STATUS_FAILURE)
1092 {
1093 hddLog(LOGE,
1094 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001095 ret = -EINVAL;
1096 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001097 }
1098
1099 // Added for ProResp IE
1100 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1101 {
1102 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1103 u8 probe_rsp_ie_len[3] = {0};
1104 u8 counter = 0;
1105 /* Check Probe Resp Length if it is greater then 255 then Store
1106 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1107 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1108 Store More then 255 bytes into One Variable.
1109 */
1110 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1111 {
1112 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1113 {
1114 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1115 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1116 }
1117 else
1118 {
1119 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1120 rem_probe_resp_ie_len = 0;
1121 }
1122 }
1123
1124 rem_probe_resp_ie_len = 0;
1125
1126 if (probe_rsp_ie_len[0] > 0)
1127 {
1128 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1129 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1130 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1131 probe_rsp_ie_len[0], NULL,
1132 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1133 {
1134 hddLog(LOGE,
1135 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001136 ret = -EINVAL;
1137 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001138 }
1139 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1140 }
1141
1142 if (probe_rsp_ie_len[1] > 0)
1143 {
1144 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1145 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1146 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1147 probe_rsp_ie_len[1], NULL,
1148 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1149 {
1150 hddLog(LOGE,
1151 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001152 ret = -EINVAL;
1153 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 }
1155 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1156 }
1157
1158 if (probe_rsp_ie_len[2] > 0)
1159 {
1160 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1161 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1162 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1163 probe_rsp_ie_len[2], NULL,
1164 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1165 {
1166 hddLog(LOGE,
1167 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001168 ret = -EINVAL;
1169 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001170 }
1171 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1172 }
1173
1174 if (probe_rsp_ie_len[1] == 0 )
1175 {
1176 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1177 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1178 eANI_BOOLEAN_FALSE) )
1179 {
1180 hddLog(LOGE,
1181 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1182 }
1183 }
1184
1185 if (probe_rsp_ie_len[2] == 0 )
1186 {
1187 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1188 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1189 eANI_BOOLEAN_FALSE) )
1190 {
1191 hddLog(LOGE,
1192 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1193 }
1194 }
1195
1196 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1197 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1198 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1199 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1200 == eHAL_STATUS_FAILURE)
1201 {
1202 hddLog(LOGE,
1203 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001204 ret = -EINVAL;
1205 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001206 }
1207 }
1208 else
1209 {
1210 // Reset WNI_CFG_PROBE_RSP Flags
1211 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1212
1213 hddLog(VOS_TRACE_LEVEL_INFO,
1214 "%s: No Probe Response IE received in set beacon",
1215 __func__);
1216 }
1217
1218 // Added for AssocResp IE
1219 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1220 {
1221 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1222 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1223 params->assocresp_ies_len, NULL,
1224 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1225 {
1226 hddLog(LOGE,
1227 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001228 ret = -EINVAL;
1229 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001230 }
1231
1232 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1233 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1234 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1235 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1236 == eHAL_STATUS_FAILURE)
1237 {
1238 hddLog(LOGE,
1239 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001240 ret = -EINVAL;
1241 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001242 }
1243 }
1244 else
1245 {
1246 hddLog(VOS_TRACE_LEVEL_INFO,
1247 "%s: No Assoc Response IE received in set beacon",
1248 __func__);
1249
1250 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1251 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1252 eANI_BOOLEAN_FALSE) )
1253 {
1254 hddLog(LOGE,
1255 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1256 }
1257 }
1258
Jeff Johnsone7245742012-09-05 17:12:55 -07001259done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001260 vos_mem_free(genie);
1261 return 0;
1262}
Jeff Johnson295189b2012-06-20 16:38:30 -07001263
1264/*
1265 * FUNCTION: wlan_hdd_validate_operation_channel
1266 * called by wlan_hdd_cfg80211_start_bss() and
1267 * wlan_hdd_cfg80211_set_channel()
1268 * This function validates whether given channel is part of valid
1269 * channel list.
1270 */
1271static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1272{
1273
1274 v_U32_t num_ch = 0;
1275 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1276 u32 indx = 0;
1277 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1278
1279 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1280
1281 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1282 valid_ch, &num_ch))
1283 {
1284 hddLog(VOS_TRACE_LEVEL_ERROR,
1285 "%s: failed to get valid channel list\n", __func__);
1286 return VOS_STATUS_E_FAILURE;
1287 }
1288
1289 for (indx = 0; indx < num_ch; indx++)
1290 {
1291 if (channel == valid_ch[indx])
1292 {
1293 break;
1294 }
1295 }
1296
1297 if (indx >= num_ch)
1298 {
1299 hddLog(VOS_TRACE_LEVEL_ERROR,
1300 "%s: Invalid Channel [%d] \n", __func__, channel);
1301 return VOS_STATUS_E_FAILURE;
1302 }
1303 return VOS_STATUS_SUCCESS;
1304
1305}
1306
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301307/*
1308 * FUNCTION: wlan_hdd_select_cbmode
1309 * called by wlan_hdd_cfg80211_start_bss() and
1310 * This function selects the cbmode based on primary channel
1311 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001312VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301313{
1314 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001315 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1316 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1317
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301318 if(
1319#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001320 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1321 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301322#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001323 SapHw_mode != eSAP_DOT11_MODE_11n &&
1324 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301325 )
1326 {
1327 return VOS_STATUS_SUCCESS;
1328 }
1329
1330 if (!pConfigIni->nChannelBondingMode5GHz) {
1331 return VOS_STATUS_SUCCESS;
1332 }
1333
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001334 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301335 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1336
1337 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1338
1339#ifdef WLAN_FEATURE_11AC
1340
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001341 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1342 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301343 {
1344 if ( channel== 36 || channel == 52 || channel == 100 ||
1345 channel == 116 || channel == 149 )
1346 {
1347 smeConfig.csrConfig.channelBondingMode5GHz =
1348 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1349 }
1350 else if ( channel == 40 || channel == 56 || channel == 104 ||
1351 channel == 120 || channel == 153 )
1352 {
1353 smeConfig.csrConfig.channelBondingMode5GHz =
1354 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1355 }
1356 else if ( channel == 44 || channel == 60 || channel == 108 ||
1357 channel == 124 || channel == 157 )
1358 {
1359 smeConfig.csrConfig.channelBondingMode5GHz =
1360 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1361 }
1362 else if ( channel == 48 || channel == 64 || channel == 112 ||
1363 channel == 128 || channel == 161 )
1364 {
1365 smeConfig.csrConfig.channelBondingMode5GHz =
1366 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1367 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301368 }
1369#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001370 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1371 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301372 {
1373 if ( channel== 40 || channel == 48 || channel == 56 ||
1374 channel == 64 || channel == 104 || channel == 112 ||
1375 channel == 120 || channel == 128 || channel == 136 ||
1376 channel == 144 || channel == 153 || channel == 161 )
1377 {
1378 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1379 }
1380 else if ( channel== 36 || channel == 44 || channel == 52 ||
1381 channel == 60 || channel == 100 || channel == 108 ||
1382 channel == 116 || channel == 124 || channel == 132 ||
1383 channel == 140 || channel == 149 || channel == 157 )
1384 {
1385 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1386 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301387 }
1388 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1389
1390 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1391 return VOS_STATUS_SUCCESS;
1392}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001393
Jeff Johnson295189b2012-06-20 16:38:30 -07001394#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1395static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1396 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001397#else
1398static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1399 struct cfg80211_beacon_data *params,
1400 const u8 *ssid, size_t ssid_len,
1401 enum nl80211_hidden_ssid hidden_ssid)
1402#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001403{
1404 tsap_Config_t *pConfig;
1405 beacon_data_t *pBeacon = NULL;
1406 struct ieee80211_mgmt *pMgmt_frame;
1407 v_U8_t *pIe=NULL;
1408 v_U16_t capab_info;
1409 eCsrAuthType RSNAuthType;
1410 eCsrEncryptionType RSNEncryptType;
1411 eCsrEncryptionType mcRSNEncryptType;
1412 int status = VOS_STATUS_SUCCESS;
1413 tpWLAN_SAPEventCB pSapEventCallback;
1414 hdd_hostapd_state_t *pHostapdState;
1415 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1416 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1417 struct qc_mac_acl_entry *acl_entry = NULL;
1418 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001419 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001420
1421 ENTER();
1422
1423 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1424
1425 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1426
1427 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1428
1429 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1430
1431 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1432
1433 //channel is already set in the set_channel Call back
1434 //pConfig->channel = pCommitConfig->channel;
1435
1436 /*Protection parameter to enable or disable*/
1437 pConfig->protEnabled =
1438 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1439
1440 pConfig->dtim_period = pBeacon->dtim_period;
1441
1442 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1443 pConfig->dtim_period);
1444
1445
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001446 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001447 {
1448 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001449 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001450 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001451 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001452 tANI_BOOLEAN restartNeeded;
1453 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1454 pConfig->ieee80211d = 1;
1455 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1456 sme_setRegInfo(hHal, pConfig->countryCode);
1457 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1458 /*
1459 * If auto channel is configured i.e. channel is 0,
1460 * so skip channel validation.
1461 */
1462 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001463 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001464 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1465 {
1466 hddLog(VOS_TRACE_LEVEL_ERROR,
1467 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1468 return -EINVAL;
1469 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001470 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001471 /*
1472 * Validate the given channel range for the given country code
1473 */
1474 else
1475 {
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001476 if(1 != pHddCtx->is_dynamic_channel_range_set)
Ng Chilamfc416462012-12-27 17:26:52 -08001477 {
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001478 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001479 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
Ng Chilamfc416462012-12-27 17:26:52 -08001480 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001481 }
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001482
Ng Chilamfc416462012-12-27 17:26:52 -08001483 pHddCtx->is_dynamic_channel_range_set = 0;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001484 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001485 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001486 else
1487 {
1488 pConfig->ieee80211d = 0;
1489 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001490 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001491 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001492 {
1493 pConfig->ieee80211d = 0;
1494 }
1495 pConfig->authType = eSAP_AUTO_SWITCH;
1496
1497 capab_info = pMgmt_frame->u.beacon.capab_info;
1498
1499 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1500 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1501
1502 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1503
1504 /*Set wps station to configured*/
1505 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1506
1507 if(pIe)
1508 {
1509 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1510 {
1511 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1512 return -EINVAL;
1513 }
1514 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1515 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001516 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001517 /* Check 15 bit of WPS IE as it contain information for wps state
1518 * WPS state
1519 */
1520 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1521 {
1522 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1523 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1524 {
1525 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1526 }
1527 }
1528 }
1529 else
1530 {
1531 pConfig->wps_state = SAP_WPS_DISABLED;
1532 }
1533 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1534
1535 pConfig->RSNWPAReqIELength = 0;
1536 pConfig->pRSNWPAReqIE = NULL;
1537 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1538 WLAN_EID_RSN);
1539 if(pIe && pIe[1])
1540 {
1541 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1542 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1543 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1544 /* The actual processing may eventually be more extensive than
1545 * this. Right now, just consume any PMKIDs that are sent in
1546 * by the app.
1547 * */
1548 status = hdd_softap_unpackIE(
1549 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1550 &RSNEncryptType,
1551 &mcRSNEncryptType,
1552 &RSNAuthType,
1553 pConfig->pRSNWPAReqIE[1]+2,
1554 pConfig->pRSNWPAReqIE );
1555
1556 if( VOS_STATUS_SUCCESS == status )
1557 {
1558 /* Now copy over all the security attributes you have
1559 * parsed out
1560 * */
1561 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1562 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1563 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1564 = RSNEncryptType;
1565 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1566 "EncryptionType = %d mcEncryptionType = %d\n"),
1567 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1568 }
1569 }
1570
1571 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1572 pBeacon->tail, pBeacon->tail_len);
1573
1574 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1575 {
1576 if (pConfig->pRSNWPAReqIE)
1577 {
1578 /*Mixed mode WPA/WPA2*/
1579 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1580 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1581 }
1582 else
1583 {
1584 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1585 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1586 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1587 status = hdd_softap_unpackIE(
1588 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1589 &RSNEncryptType,
1590 &mcRSNEncryptType,
1591 &RSNAuthType,
1592 pConfig->pRSNWPAReqIE[1]+2,
1593 pConfig->pRSNWPAReqIE );
1594
1595 if( VOS_STATUS_SUCCESS == status )
1596 {
1597 /* Now copy over all the security attributes you have
1598 * parsed out
1599 * */
1600 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1601 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1602 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1603 = RSNEncryptType;
1604 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1605 "EncryptionType = %d mcEncryptionType = %d\n"),
1606 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1607 }
1608 }
1609 }
1610
1611 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1612
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001613#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001614 if (params->ssid != NULL)
1615 {
1616 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1617 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1618 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1619 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1620 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001621#else
1622 if (ssid != NULL)
1623 {
1624 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1625 pConfig->SSIDinfo.ssid.length = ssid_len;
1626 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1627 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1628 }
1629#endif
1630
Jeff Johnson295189b2012-06-20 16:38:30 -07001631 vos_mem_copy(pConfig->self_macaddr.bytes,
1632 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1633
1634 /* default value */
1635 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1636 pConfig->num_accept_mac = 0;
1637 pConfig->num_deny_mac = 0;
1638
1639 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1640 pBeacon->tail, pBeacon->tail_len);
1641
1642 /* pIe for black list is following form:
1643 type : 1 byte
1644 length : 1 byte
1645 OUI : 4 bytes
1646 acl type : 1 byte
1647 no of mac addr in black list: 1 byte
1648 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1649 */
1650 if ((pIe != NULL) && (pIe[1] != 0))
1651 {
1652 pConfig->SapMacaddr_acl = pIe[6];
1653 pConfig->num_deny_mac = pIe[7];
1654 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1655 pIe[6], pIe[7]);
1656 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1657 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1658 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1659 for (i = 0; i < pConfig->num_deny_mac; i++)
1660 {
1661 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1662 acl_entry++;
1663 }
1664 }
1665 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1666 pBeacon->tail, pBeacon->tail_len);
1667
1668 /* pIe for white list is following form:
1669 type : 1 byte
1670 length : 1 byte
1671 OUI : 4 bytes
1672 acl type : 1 byte
1673 no of mac addr in white list: 1 byte
1674 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1675 */
1676 if ((pIe != NULL) && (pIe[1] != 0))
1677 {
1678 pConfig->SapMacaddr_acl = pIe[6];
1679 pConfig->num_accept_mac = pIe[7];
1680 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1681 pIe[6], pIe[7]);
1682 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1683 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1684 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1685 for (i = 0; i < pConfig->num_accept_mac; i++)
1686 {
1687 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1688 acl_entry++;
1689 }
1690 }
1691 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1692
Jeff Johnsone7245742012-09-05 17:12:55 -07001693#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001694 /* Overwrite the hostapd setting for HW mode only for 11ac.
1695 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1696 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1697 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1698 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1699 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1700 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1701 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001702 {
1703 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1704 }
1705#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301706
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001707 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1708 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001709 // ht_capab is not what the name conveys,this is used for protection bitmap
1710 pConfig->ht_capab =
1711 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1712
1713 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1714 {
1715 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1716 return -EINVAL;
1717 }
1718
1719 //Uapsd Enabled Bit
1720 pConfig->UapsdEnable =
1721 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1722 //Enable OBSS protection
1723 pConfig->obssProtEnabled =
1724 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1725
1726 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1727 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1728 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1729 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1730 (int)pConfig->channel);
1731 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1732 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1733 pConfig->authType);
1734 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1735 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1736 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1737 pConfig->protEnabled, pConfig->obssProtEnabled);
1738
1739 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1740 {
1741 //Bss already started. just return.
1742 //TODO Probably it should update some beacon params.
1743 hddLog( LOGE, "Bss Already started...Ignore the request");
1744 EXIT();
1745 return 0;
1746 }
1747
1748 pConfig->persona = pHostapdAdapter->device_mode;
1749
1750 pSapEventCallback = hdd_hostapd_SAPEventCB;
1751 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1752 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1753 {
1754 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1755 return -EINVAL;
1756 }
1757
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001758 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001759 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1760
1761 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1762
1763 if (!VOS_IS_STATUS_SUCCESS(status))
1764 {
1765 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1766 ("ERROR: HDD vos wait for single_event failed!!\n"));
1767 VOS_ASSERT(0);
1768 }
1769
1770 //Succesfully started Bss update the state bit.
1771 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1772
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001773#ifdef WLAN_FEATURE_P2P_DEBUG
1774 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1775 {
1776 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1777 {
1778 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1779 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001780 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001781 }
1782 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1783 {
1784 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1785 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001786 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001787 }
1788 }
1789#endif
1790
Jeff Johnson295189b2012-06-20 16:38:30 -07001791 pHostapdState->bCommit = TRUE;
1792 EXIT();
1793
1794 return 0;
1795}
1796
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001797#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001798static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1799 struct net_device *dev,
1800 struct beacon_parameters *params)
1801{
1802 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1803 int status=VOS_STATUS_SUCCESS;
1804
1805 ENTER();
1806
1807 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1808
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001809 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1810 {
1811 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1812 "%s:LOGP in Progress. Ignore!!!", __func__);
1813 return -EAGAIN;
1814 }
1815
Jeff Johnson295189b2012-06-20 16:38:30 -07001816 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1817#ifdef WLAN_FEATURE_P2P
1818 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1819#endif
1820 )
1821 {
1822 beacon_data_t *old,*new;
1823
1824 old = pAdapter->sessionCtx.ap.beacon;
1825
1826 if (old)
1827 return -EALREADY;
1828
1829 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1830
1831 if(status != VOS_STATUS_SUCCESS)
1832 {
1833 hddLog(VOS_TRACE_LEVEL_FATAL,
1834 "%s:Error!!! Allocating the new beacon\n",__func__);
1835 return -EINVAL;
1836 }
1837
1838 pAdapter->sessionCtx.ap.beacon = new;
1839
1840 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1841 }
1842
1843 EXIT();
1844 return status;
1845}
1846
1847static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1848 struct net_device *dev,
1849 struct beacon_parameters *params)
1850{
1851 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1852 int status=VOS_STATUS_SUCCESS;
1853
1854 ENTER();
1855
1856 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1857 __func__,pAdapter->device_mode);
1858
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001859 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1860 {
1861 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1862 "%s:LOGP in Progress. Ignore!!!", __func__);
1863 return -EAGAIN;
1864 }
1865
Jeff Johnson295189b2012-06-20 16:38:30 -07001866 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1867#ifdef WLAN_FEATURE_P2P
1868 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1869#endif
1870 )
1871 {
1872 beacon_data_t *old,*new;
1873
1874 old = pAdapter->sessionCtx.ap.beacon;
1875
1876 if (!old)
1877 return -ENOENT;
1878
1879 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1880
1881 if(status != VOS_STATUS_SUCCESS) {
1882 hddLog(VOS_TRACE_LEVEL_FATAL,
1883 "%s: Error!!! Allocating the new beacon\n",__func__);
1884 return -EINVAL;
1885 }
1886
1887 pAdapter->sessionCtx.ap.beacon = new;
1888
1889 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1890 }
1891
1892 EXIT();
1893 return status;
1894}
1895
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001896#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1897
1898#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001899static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1900 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001901#else
1902static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1903 struct net_device *dev)
1904#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001905{
1906 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001907 hdd_context_t *pHddCtx = NULL;
1908 hdd_scaninfo_t *pScanInfo = NULL;
1909 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001910 VOS_STATUS status = 0;
1911
1912 ENTER();
1913
1914 if (NULL == pAdapter)
1915 {
1916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001917 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001918 return -ENODEV;
1919 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001920 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1921 {
1922 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1923 "%s:LOGP in Progress. Ignore!!!", __func__);
1924 return -EAGAIN;
1925 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001926
1927 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1928 if (NULL == pHddCtx)
1929 {
1930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001931 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001932 return -ENODEV;
1933 }
1934
1935 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1936 if (NULL == staAdapter)
1937 {
1938 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1939 if (NULL == staAdapter)
1940 {
1941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001942 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001943 return -ENODEV;
1944 }
1945 }
1946
1947 pScanInfo = &pHddCtx->scan_info;
1948
Jeff Johnson295189b2012-06-20 16:38:30 -07001949 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1950 {
1951 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1952 return -EAGAIN;
1953 }
1954
1955 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1956
1957 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1958 __func__,pAdapter->device_mode);
1959
Jeff Johnsone7245742012-09-05 17:12:55 -07001960 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1961 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001962 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001963 hdd_abort_mac_scan(staAdapter->pHddCtx);
1964 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001965 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07001966 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1967 if (!status)
1968 {
1969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08001970 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001971 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001972 VOS_ASSERT(pScanInfo->mScanPending);
1973 return 0;
1974 }
1975 }
1976
Jeff Johnson295189b2012-06-20 16:38:30 -07001977 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1978#ifdef WLAN_FEATURE_P2P
1979 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1980#endif
1981 )
1982 {
1983 beacon_data_t *old;
1984
1985 old = pAdapter->sessionCtx.ap.beacon;
1986
1987 if (!old)
1988 return -ENOENT;
1989
1990#ifdef CONFIG_CFG80211
1991 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1992#endif
1993
1994 mutex_lock(&pHddCtx->sap_lock);
1995 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1996 {
1997 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
1998 {
1999 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2000
2001 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2002
2003 if (!VOS_IS_STATUS_SUCCESS(status))
2004 {
2005 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2006 ("ERROR: HDD vos wait for single_event failed!!\n"));
2007 VOS_ASSERT(0);
2008 }
2009 }
2010 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2011 }
2012 mutex_unlock(&pHddCtx->sap_lock);
2013
2014 if(status != VOS_STATUS_SUCCESS)
2015 {
2016 hddLog(VOS_TRACE_LEVEL_FATAL,
2017 "%s:Error!!! Stopping the BSS\n",__func__);
2018 return -EINVAL;
2019 }
2020
2021 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2022 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2023 ==eHAL_STATUS_FAILURE)
2024 {
2025 hddLog(LOGE,
2026 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2027 }
2028
2029 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2030 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2031 eANI_BOOLEAN_FALSE) )
2032 {
2033 hddLog(LOGE,
2034 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2035 }
2036
2037 // Reset WNI_CFG_PROBE_RSP Flags
2038 wlan_hdd_reset_prob_rspies(pAdapter);
2039
2040 pAdapter->sessionCtx.ap.beacon = NULL;
2041 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002042#ifdef WLAN_FEATURE_P2P_DEBUG
2043 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2044 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2045 {
2046 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2047 "GO got removed");
2048 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2049 }
2050#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002051 }
2052 EXIT();
2053 return status;
2054}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002055
2056#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2057
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302058static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2059 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002060 struct cfg80211_ap_settings *params)
2061{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302062 hdd_adapter_t *pAdapter;
2063 hdd_context_t *pHddCtx;
2064 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002065
2066 ENTER();
2067
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302068 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002069 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302070 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2071 "%s: Device is Null", __func__);
2072 return -ENODEV;
2073 }
2074
2075 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2076 if (NULL == pAdapter)
2077 {
2078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2079 "%s: HDD adapter is Null", __func__);
2080 return -ENODEV;
2081 }
2082
2083 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2084 {
2085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2086 "%s: HDD adapter magic is invalid", __func__);
2087 return -ENODEV;
2088 }
2089
2090 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2091 if (NULL == pHddCtx)
2092 {
2093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2094 "%s: HDD context is Null", __func__);
2095 return -ENODEV;
2096 }
2097
2098 if (pHddCtx->isLogpInProgress)
2099 {
2100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2101 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002102 return -EAGAIN;
2103 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302104
2105 if (pHddCtx->isLoadUnloadInProgress)
2106 {
2107 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2108 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2109 return -EAGAIN;
2110 }
2111
2112 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2113 __func__, pAdapter->device_mode);
2114
2115 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002116#ifdef WLAN_FEATURE_P2P
2117 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2118#endif
2119 )
2120 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302121 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002122
2123 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302124
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002125 if (old)
2126 return -EALREADY;
2127
2128 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2129
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302130 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002131 {
2132 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302133 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002134 return -EINVAL;
2135 }
2136 pAdapter->sessionCtx.ap.beacon = new;
2137 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2138 params->ssid_len, params->hidden_ssid);
2139 }
2140
2141 EXIT();
2142 return status;
2143}
2144
2145
2146static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2147 struct net_device *dev,
2148 struct cfg80211_beacon_data *params)
2149{
2150 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2151 int status=VOS_STATUS_SUCCESS;
2152
2153 ENTER();
2154
2155 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2156 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002157 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2158 {
2159 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2160 return -EAGAIN;
2161 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002162
2163 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2164#ifdef WLAN_FEATURE_P2P
2165 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2166#endif
2167 )
2168 {
2169 beacon_data_t *old,*new;
2170
2171 old = pAdapter->sessionCtx.ap.beacon;
2172
2173 if (!old)
2174 return -ENOENT;
2175
2176 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2177
2178 if(status != VOS_STATUS_SUCCESS) {
2179 hddLog(VOS_TRACE_LEVEL_FATAL,
2180 "%s: Error!!! Allocating the new beacon\n",__func__);
2181 return -EINVAL;
2182 }
2183
2184 pAdapter->sessionCtx.ap.beacon = new;
2185
2186 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2187 }
2188
2189 EXIT();
2190 return status;
2191}
2192
2193#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2194
Jeff Johnson295189b2012-06-20 16:38:30 -07002195
2196static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2197 struct net_device *dev,
2198 struct bss_parameters *params)
2199{
2200 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2201
2202 ENTER();
2203
2204 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2205 __func__,pAdapter->device_mode);
2206
2207 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2208#ifdef WLAN_FEATURE_P2P
2209 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2210#endif
2211 )
2212 {
2213 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2214 * want to update this parameter */
2215 if (-1 != params->ap_isolate)
2216 {
2217 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2218 }
2219 }
2220
2221 EXIT();
2222 return 0;
2223}
2224
2225/*
2226 * FUNCTION: wlan_hdd_cfg80211_change_iface
2227 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2228 */
2229int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2230 struct net_device *ndev,
2231 enum nl80211_iftype type,
2232 u32 *flags,
2233 struct vif_params *params
2234 )
2235{
2236 struct wireless_dev *wdev;
2237 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2238 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002239 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002240 tCsrRoamProfile *pRoamProfile = NULL;
2241 eCsrRoamBssType LastBSSType;
2242 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2243 eMib_dot11DesiredBssType connectedBssType;
2244 VOS_STATUS status;
2245
2246 ENTER();
2247
2248 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2249 {
2250 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2251 return -EAGAIN;
2252 }
2253
2254 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2255 __func__, pAdapter->device_mode);
2256
2257 wdev = ndev->ieee80211_ptr;
2258
2259#ifdef WLAN_BTAMP_FEATURE
2260 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2261 (NL80211_IFTYPE_ADHOC == type)||
2262 (NL80211_IFTYPE_AP == type)||
2263 (NL80211_IFTYPE_P2P_GO == type))
2264 {
2265 pHddCtx->isAmpAllowed = VOS_FALSE;
2266 // stop AMP traffic
2267 status = WLANBAP_StopAmp();
2268 if(VOS_STATUS_SUCCESS != status )
2269 {
2270 pHddCtx->isAmpAllowed = VOS_TRUE;
2271 hddLog(VOS_TRACE_LEVEL_FATAL,
2272 "%s: Failed to stop AMP", __func__);
2273 return -EINVAL;
2274 }
2275 }
2276#endif //WLAN_BTAMP_FEATURE
2277 /* Reset the current device mode bit mask*/
2278 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2279
2280 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2281#ifdef WLAN_FEATURE_P2P
2282 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002283 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002284#endif
2285 )
2286 {
2287 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2288 pRoamProfile = &pWextState->roamProfile;
2289 LastBSSType = pRoamProfile->BSSType;
2290
2291 switch (type)
2292 {
2293 case NL80211_IFTYPE_STATION:
2294#ifdef WLAN_FEATURE_P2P
2295 case NL80211_IFTYPE_P2P_CLIENT:
2296#endif
2297 hddLog(VOS_TRACE_LEVEL_INFO,
2298 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2299 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002300#ifdef WLAN_FEATURE_11AC
2301 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2302 {
2303 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2304 }
2305#endif
2306 pRoamProfile->phyMode =
2307 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002308 wdev->iftype = type;
2309#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002310 //Check for sub-string p2p to confirm its a p2p interface
2311 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002312 {
2313 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2314 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2315 }
2316 else
2317 {
2318 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002319 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002320 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002321#endif
2322 break;
2323 case NL80211_IFTYPE_ADHOC:
2324 hddLog(VOS_TRACE_LEVEL_INFO,
2325 "%s: setting interface Type to ADHOC", __func__);
2326 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2327 pRoamProfile->phyMode =
2328 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2329 wdev->iftype = type;
2330 break;
2331
2332 case NL80211_IFTYPE_AP:
2333#ifdef WLAN_FEATURE_P2P
2334 case NL80211_IFTYPE_P2P_GO:
2335#endif
2336 {
2337 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2338 "%s: setting interface Type to %s", __func__,
2339 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2340
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002341 //Cancel any remain on channel for GO mode
2342 if (NL80211_IFTYPE_P2P_GO == type)
2343 {
2344 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2345 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002346 if (NL80211_IFTYPE_AP == type)
2347 {
2348 /* As Loading WLAN Driver one interface being created for p2p device
2349 * address. This will take one HW STA and the max number of clients
2350 * that can connect to softAP will be reduced by one. so while changing
2351 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2352 * interface as it is not required in SoftAP mode.
2353 */
2354
2355 // Get P2P Adapter
2356 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2357
2358 if (pP2pAdapter)
2359 {
2360 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2361 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2362 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2363 }
2364 }
2365
Jeff Johnson295189b2012-06-20 16:38:30 -07002366 //De-init the adapter.
2367 hdd_stop_adapter( pHddCtx, pAdapter );
2368 hdd_deinit_adapter( pHddCtx, pAdapter );
2369 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2370#ifdef WLAN_SOFTAP_FEATURE
2371#ifdef WLAN_FEATURE_P2P
2372 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2373 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2374#else
2375 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2376#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002377
2378 //Disable BMPS and IMPS if enabled
2379 //before starting Go
2380 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2381 {
2382 if(VOS_STATUS_E_FAILURE ==
2383 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2384 {
2385 //Fail to Exit BMPS
2386 VOS_ASSERT(0);
2387 }
2388 }
2389
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002390 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2391 (pConfig->apRandomBssidEnabled))
2392 {
2393 /* To meet Android requirements create a randomized
2394 MAC address of the form 02:1A:11:Fx:xx:xx */
2395 get_random_bytes(&ndev->dev_addr[3], 3);
2396 ndev->dev_addr[0] = 0x02;
2397 ndev->dev_addr[1] = 0x1A;
2398 ndev->dev_addr[2] = 0x11;
2399 ndev->dev_addr[3] |= 0xF0;
2400 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2401 VOS_MAC_ADDR_SIZE);
2402 pr_info("wlan: Generated HotSpot BSSID "
2403 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2404 ndev->dev_addr[0],
2405 ndev->dev_addr[1],
2406 ndev->dev_addr[2],
2407 ndev->dev_addr[3],
2408 ndev->dev_addr[4],
2409 ndev->dev_addr[5]);
2410 }
2411
Jeff Johnson295189b2012-06-20 16:38:30 -07002412 hdd_set_ap_ops( pAdapter->dev );
2413
2414 status = hdd_init_ap_mode(pAdapter);
2415 if(status != VOS_STATUS_SUCCESS)
2416 {
2417 hddLog(VOS_TRACE_LEVEL_FATAL,
2418 "%s: Error initializing the ap mode", __func__);
2419 return -EINVAL;
2420 }
2421 hdd_set_conparam(1);
2422
2423#endif
2424 /*interface type changed update in wiphy structure*/
2425 if(wdev)
2426 {
2427 wdev->iftype = type;
2428 pHddCtx->change_iface = type;
2429 }
2430 else
2431 {
2432 hddLog(VOS_TRACE_LEVEL_ERROR,
2433 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2434 return -EINVAL;
2435 }
2436 goto done;
2437 }
2438
2439 default:
2440 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2441 __func__);
2442 return -EOPNOTSUPP;
2443 }
2444 }
2445 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2446#ifdef WLAN_FEATURE_P2P
2447 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2448#endif
2449 )
2450 {
2451 switch(type)
2452 {
2453 case NL80211_IFTYPE_STATION:
2454#ifdef WLAN_FEATURE_P2P
2455 case NL80211_IFTYPE_P2P_CLIENT:
2456#endif
2457 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002458 hdd_stop_adapter( pHddCtx, pAdapter );
2459 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002460 wdev->iftype = type;
2461#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002462 //Check for sub-string p2p to confirm its a p2p interface
2463 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002464 {
2465 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2466 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2467 }
2468 else
2469 {
2470 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002471 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002472 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002473#endif
2474 hdd_set_conparam(0);
2475 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002476 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2477 hdd_set_station_ops( pAdapter->dev );
2478 status = hdd_init_station_mode( pAdapter );
2479 if( VOS_STATUS_SUCCESS != status )
2480 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002481 /* In case of JB, for P2P-GO, only change interface will be called,
2482 * This is the right place to enable back bmps_imps()
2483 */
2484 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 goto done;
2486 case NL80211_IFTYPE_AP:
2487#ifdef WLAN_FEATURE_P2P
2488 case NL80211_IFTYPE_P2P_GO:
2489#endif
2490 wdev->iftype = type;
2491#ifdef WLAN_FEATURE_P2P
2492 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2493 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2494#endif
2495 goto done;
2496 default:
2497 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2498 __func__);
2499 return -EOPNOTSUPP;
2500
2501 }
2502
2503 }
2504 else
2505 {
2506 return -EOPNOTSUPP;
2507 }
2508
2509
2510 if(pRoamProfile)
2511 {
2512 if ( LastBSSType != pRoamProfile->BSSType )
2513 {
2514 /*interface type changed update in wiphy structure*/
2515 wdev->iftype = type;
2516
2517 /*the BSS mode changed, We need to issue disconnect
2518 if connected or in IBSS disconnect state*/
2519 if ( hdd_connGetConnectedBssType(
2520 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2521 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2522 {
2523 /*need to issue a disconnect to CSR.*/
2524 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2525 if( eHAL_STATUS_SUCCESS ==
2526 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2527 pAdapter->sessionId,
2528 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2529 {
2530 wait_for_completion_interruptible_timeout(
2531 &pAdapter->disconnect_comp_var,
2532 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2533 }
2534 }
2535 }
2536 }
2537
2538done:
2539 /*set bitmask based on updated value*/
2540 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2541#ifdef WLAN_BTAMP_FEATURE
2542 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2543 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2544 {
2545 //we are ok to do AMP
2546 pHddCtx->isAmpAllowed = VOS_TRUE;
2547 }
2548#endif //WLAN_BTAMP_FEATURE
2549 EXIT();
2550 return 0;
2551}
2552
2553static int wlan_hdd_change_station(struct wiphy *wiphy,
2554 struct net_device *dev,
2555 u8 *mac,
2556 struct station_parameters *params)
2557{
2558 VOS_STATUS status = VOS_STATUS_SUCCESS;
2559 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2560 v_MACADDR_t STAMacAddress;
2561
Jeff Johnsone7245742012-09-05 17:12:55 -07002562 ENTER();
2563
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002564 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2565 {
2566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2567 "%s:LOGP in Progress. Ignore!!!", __func__);
2568 return -EAGAIN;
2569 }
2570
Jeff Johnson295189b2012-06-20 16:38:30 -07002571 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2572
2573 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2574#ifdef WLAN_FEATURE_P2P
2575 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2576#endif
2577 )
2578 {
2579 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2580 {
2581 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2582 WLANTL_STA_AUTHENTICATED);
2583
2584 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002585 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002586 return -EINVAL;
2587 }
2588 }
2589
Jeff Johnsone7245742012-09-05 17:12:55 -07002590 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002591 return status;
2592}
2593
2594/*
2595 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2596 * This function is used to get peer station index in IBSS mode
2597 */
2598static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2599{
2600 u8 idx = 0;
2601 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2602 ENTER();
2603 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2604 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2605 {
2606 if ( (0 !=
2607 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2608 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2609 temp, VOS_MAC_ADDR_SIZE)
2610 )
2611 {
2612 return idx;
2613 }
2614 }
2615 return idx;
2616}
2617
2618
2619/*
2620 * FUNCTION: wlan_hdd_cfg80211_add_key
2621 * This function is used to initialize the key information
2622 */
2623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2624static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2625 struct net_device *ndev,
2626 u8 key_index, bool pairwise,
2627 const u8 *mac_addr,
2628 struct key_params *params
2629 )
2630#else
2631static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2632 struct net_device *ndev,
2633 u8 key_index, const u8 *mac_addr,
2634 struct key_params *params
2635 )
2636#endif
2637{
2638 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2639 tCsrRoamSetKey setKey;
2640 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2641 int status = 0;
2642 v_U32_t roamId= 0xFF;
2643 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2644 hdd_hostapd_state_t *pHostapdState;
2645 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002646 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002647
2648 ENTER();
2649
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002650 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2651 {
2652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2653 "%s:LOGP in Progress. Ignore!!!", __func__);
2654 return -EAGAIN;
2655 }
2656
Jeff Johnson295189b2012-06-20 16:38:30 -07002657 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2658 __func__,pAdapter->device_mode);
2659
2660 if (CSR_MAX_NUM_KEY <= key_index)
2661 {
2662 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2663 key_index);
2664
2665 return -EINVAL;
2666 }
2667
2668 hddLog(VOS_TRACE_LEVEL_INFO,
2669 "%s: called with key index = %d & key length %d",
2670 __func__, key_index, params->key_len);
2671
2672 /*extract key idx, key len and key*/
2673 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2674 setKey.keyId = key_index;
2675 setKey.keyLength = params->key_len;
2676 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2677
2678 switch (params->cipher)
2679 {
2680 case WLAN_CIPHER_SUITE_WEP40:
2681 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2682 break;
2683
2684 case WLAN_CIPHER_SUITE_WEP104:
2685 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2686 break;
2687
2688 case WLAN_CIPHER_SUITE_TKIP:
2689 {
2690 u8 *pKey = &setKey.Key[0];
2691 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2692
2693 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2694
2695 /*Supplicant sends the 32bytes key in this order
2696
2697 |--------------|----------|----------|
2698 | Tk1 |TX-MIC | RX Mic |
2699 |--------------|----------|----------|
2700 <---16bytes---><--8bytes--><--8bytes-->
2701
2702 */
2703 /*Sme expects the 32 bytes key to be in the below order
2704
2705 |--------------|----------|----------|
2706 | Tk1 |RX-MIC | TX Mic |
2707 |--------------|----------|----------|
2708 <---16bytes---><--8bytes--><--8bytes-->
2709 */
2710 /* Copy the Temporal Key 1 (TK1) */
2711 vos_mem_copy(pKey, params->key,16);
2712
2713 /*Copy the rx mic first*/
2714 vos_mem_copy(&pKey[16],&params->key[24],8);
2715
2716 /*Copy the tx mic */
2717 vos_mem_copy(&pKey[24],&params->key[16],8);
2718
2719
2720 break;
2721 }
2722
2723 case WLAN_CIPHER_SUITE_CCMP:
2724 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2725 break;
2726
2727#ifdef FEATURE_WLAN_WAPI
2728 case WLAN_CIPHER_SUITE_SMS4:
2729 {
2730 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2731 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2732 params->key, params->key_len);
2733 return 0;
2734 }
2735#endif
2736#ifdef FEATURE_WLAN_CCX
2737 case WLAN_CIPHER_SUITE_KRK:
2738 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2739 break;
2740#endif
2741 default:
2742 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2743 __func__, params->cipher);
2744 return -EOPNOTSUPP;
2745 }
2746
2747 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2748 __func__, setKey.encType);
2749
2750
2751
2752 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2753#ifdef WLAN_FEATURE_P2P
2754 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2755#endif
2756 )
2757 {
2758
2759
2760 if (
2761#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2762 (!pairwise)
2763#else
2764 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2765#endif
2766 )
2767 {
2768 /* set group key*/
2769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002770 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002771 __func__, __LINE__);
2772 setKey.keyDirection = eSIR_RX_ONLY;
2773 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2774 }
2775 else
2776 {
2777 /* set pairwise key*/
2778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2779 "%s- %d: setting pairwise key",
2780 __func__, __LINE__);
2781 setKey.keyDirection = eSIR_TX_RX;
2782 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2783 }
2784
2785 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2786 if( pHostapdState->bssState == BSS_START )
2787 {
2788 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2789
2790 if ( status != eHAL_STATUS_SUCCESS )
2791 {
2792 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2793 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2794 __LINE__, status );
2795 }
2796 }
2797
2798 /* Saving WEP keys */
2799 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2800 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2801 {
2802 //Save the wep key in ap context. Issue setkey after the BSS is started.
2803 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2804 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2805 }
2806 else
2807 {
2808 //Save the key in ap context. Issue setkey after the BSS is started.
2809 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2810 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2811 }
2812 }
2813 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2814#ifdef WLAN_FEATURE_P2P
2815 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2816#endif
2817 )
2818 {
2819 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2820 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2821
2822 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2823
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08002824 pWextState->roamProfile.Keys.defaultIndex = key_index;
2825
2826
Jeff Johnson295189b2012-06-20 16:38:30 -07002827 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2828 params->key, params->key_len);
2829
2830 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2831
2832 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2833 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2834 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2835 )
2836 &&
2837 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2838 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2839 )
2840 )
2841 {
2842 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2843 * interface, copy bssid for pairwise key and group macaddr for
2844 * group key initialization*/
2845
2846 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2847
2848 pWextState->roamProfile.negotiatedUCEncryptionType =
2849 pHddStaCtx->conn_info.ucEncryptionType =
2850 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2851 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2852 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2853
2854
2855 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2856 "%s: Negotiated encryption type %d", __func__,
2857 pWextState->roamProfile.negotiatedUCEncryptionType);
2858
2859 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2860 &pWextState->roamProfile, true);
2861 setKey.keyLength = 0;
2862 setKey.keyDirection = eSIR_TX_RX;
2863
2864#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2865 if (pairwise)
2866 {
2867#endif
2868 if (mac_addr)
2869 {
2870 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2871 }
2872 else
2873 {
2874 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2875 * and peerMacAddress in case of IBSS*/
2876 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2877 {
2878 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2879 if (HDD_MAX_NUM_IBSS_STA != staidx)
2880 {
2881 vos_mem_copy(setKey.peerMac,
2882 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2883 WNI_CFG_BSSID_LEN);
2884
2885 }
2886 else
2887 {
2888 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2889 __func__);
2890 return -EOPNOTSUPP;
2891 }
2892 }
2893 else
2894 {
2895 vos_mem_copy(setKey.peerMac,
2896 &pHddStaCtx->conn_info.bssId[0],
2897 WNI_CFG_BSSID_LEN);
2898 }
2899 }
2900#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2901 }
2902 else
2903 {
2904 /* set group key*/
2905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2906 "%s- %d: setting Group key",
2907 __func__, __LINE__);
2908 setKey.keyDirection = eSIR_RX_ONLY;
2909 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2910 }
2911#endif
2912 }
2913 else if (
2914#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2915 (!pairwise)
2916#else
2917 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2918#endif
2919 )
2920 {
2921 /* set group key*/
2922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2923 "%s- %d: setting Group key",
2924 __func__, __LINE__);
2925 setKey.keyDirection = eSIR_RX_ONLY;
2926 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2927 }
2928 else
2929 {
2930 /* set pairwise key*/
2931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2932 "%s- %d: setting pairwise key",
2933 __func__, __LINE__);
2934 setKey.keyDirection = eSIR_TX_RX;
2935 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2936 }
2937
2938 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2939 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2940 __func__, setKey.peerMac[0], setKey.peerMac[1],
2941 setKey.peerMac[2], setKey.peerMac[3],
2942 setKey.peerMac[4], setKey.peerMac[5],
2943 setKey.keyDirection);
2944
2945 vos_status = wlan_hdd_check_ula_done(pAdapter);
2946
2947 if ( vos_status != VOS_STATUS_SUCCESS )
2948 {
2949 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2950 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2951 __LINE__, vos_status );
2952
2953 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2954
2955 return -EINVAL;
2956
2957 }
2958
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002959#ifdef WLAN_FEATURE_VOWIFI_11R
2960 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2961 Save the key in the UMAC and include it in the ADD BSS request */
2962 /*TODO 11r - is this used?? */
2963 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2964 if( halStatus == eHAL_STATUS_SUCCESS )
2965 {
2966 return halStatus;
2967 }
2968#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002969
2970 /* issue set key request to SME*/
2971 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2972 pAdapter->sessionId, &setKey, &roamId );
2973
2974 if ( 0 != status )
2975 {
2976 hddLog(VOS_TRACE_LEVEL_ERROR,
2977 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2978 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2979 return -EINVAL;
2980 }
2981
2982
2983 /* in case of IBSS as there was no information available about WEP keys during
2984 * IBSS join, group key intialized with NULL key, so re-initialize group key
2985 * with correct value*/
2986 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2987 !( ( IW_AUTH_KEY_MGMT_802_1X
2988 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2989 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2990 )
2991 &&
2992 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2993 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2994 )
2995 )
2996 {
2997 setKey.keyDirection = eSIR_RX_ONLY;
2998 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2999
3000 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3001 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3002 __func__, setKey.peerMac[0], setKey.peerMac[1],
3003 setKey.peerMac[2], setKey.peerMac[3],
3004 setKey.peerMac[4], setKey.peerMac[5],
3005 setKey.keyDirection);
3006
3007 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3008 pAdapter->sessionId, &setKey, &roamId );
3009
3010 if ( 0 != status )
3011 {
3012 hddLog(VOS_TRACE_LEVEL_ERROR,
3013 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3014 __func__, status);
3015 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3016 return -EINVAL;
3017 }
3018 }
3019 }
3020
3021 return 0;
3022}
3023
3024/*
3025 * FUNCTION: wlan_hdd_cfg80211_get_key
3026 * This function is used to get the key information
3027 */
3028#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3029static int wlan_hdd_cfg80211_get_key(
3030 struct wiphy *wiphy,
3031 struct net_device *ndev,
3032 u8 key_index, bool pairwise,
3033 const u8 *mac_addr, void *cookie,
3034 void (*callback)(void *cookie, struct key_params*)
3035 )
3036#else
3037static int wlan_hdd_cfg80211_get_key(
3038 struct wiphy *wiphy,
3039 struct net_device *ndev,
3040 u8 key_index, const u8 *mac_addr, void *cookie,
3041 void (*callback)(void *cookie, struct key_params*)
3042 )
3043#endif
3044{
3045 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3046 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3047 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3048 struct key_params params;
3049
3050 ENTER();
3051
3052 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3053 __func__,pAdapter->device_mode);
3054
3055 memset(&params, 0, sizeof(params));
3056
3057 if (CSR_MAX_NUM_KEY <= key_index)
3058 {
3059 return -EINVAL;
3060 }
3061
3062 switch(pRoamProfile->EncryptionType.encryptionType[0])
3063 {
3064 case eCSR_ENCRYPT_TYPE_NONE:
3065 params.cipher = IW_AUTH_CIPHER_NONE;
3066 break;
3067
3068 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3069 case eCSR_ENCRYPT_TYPE_WEP40:
3070 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3071 break;
3072
3073 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3074 case eCSR_ENCRYPT_TYPE_WEP104:
3075 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3076 break;
3077
3078 case eCSR_ENCRYPT_TYPE_TKIP:
3079 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3080 break;
3081
3082 case eCSR_ENCRYPT_TYPE_AES:
3083 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3084 break;
3085
3086 default:
3087 params.cipher = IW_AUTH_CIPHER_NONE;
3088 break;
3089 }
3090
3091 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3092 params.seq_len = 0;
3093 params.seq = NULL;
3094 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3095 callback(cookie, &params);
3096 return 0;
3097}
3098
3099/*
3100 * FUNCTION: wlan_hdd_cfg80211_del_key
3101 * This function is used to delete the key information
3102 */
3103#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3104static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3105 struct net_device *ndev,
3106 u8 key_index,
3107 bool pairwise,
3108 const u8 *mac_addr
3109 )
3110#else
3111static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3112 struct net_device *ndev,
3113 u8 key_index,
3114 const u8 *mac_addr
3115 )
3116#endif
3117{
3118 int status = 0;
3119
3120 //This code needs to be revisited. There is sme_removeKey API, we should
3121 //plan to use that. After the change to use correct index in setkey,
3122 //it is observed that this is invalidating peer
3123 //key index whenever re-key is done. This is affecting data link.
3124 //It should be ok to ignore del_key.
3125#if 0
3126 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3127 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3128 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3129 tCsrRoamSetKey setKey;
3130 v_U32_t roamId= 0xFF;
3131
3132 ENTER();
3133
3134 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3135 __func__,pAdapter->device_mode);
3136
3137 if (CSR_MAX_NUM_KEY <= key_index)
3138 {
3139 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3140 key_index);
3141
3142 return -EINVAL;
3143 }
3144
3145 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3146 setKey.keyId = key_index;
3147
3148 if (mac_addr)
3149 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3150 else
3151 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3152
3153 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3154
3155 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3156#ifdef WLAN_FEATURE_P2P
3157 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3158#endif
3159 )
3160 {
3161
3162 hdd_hostapd_state_t *pHostapdState =
3163 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3164 if( pHostapdState->bssState == BSS_START)
3165 {
3166 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3167
3168 if ( status != eHAL_STATUS_SUCCESS )
3169 {
3170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3171 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3172 __LINE__, status );
3173 }
3174 }
3175 }
3176 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3177#ifdef WLAN_FEATURE_P2P
3178 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3179#endif
3180 )
3181 {
3182 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3183
3184 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3185
3186 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3187 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3188 __func__, setKey.peerMac[0], setKey.peerMac[1],
3189 setKey.peerMac[2], setKey.peerMac[3],
3190 setKey.peerMac[4], setKey.peerMac[5]);
3191 if(pAdapter->sessionCtx.station.conn_info.connState ==
3192 eConnectionState_Associated)
3193 {
3194 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3195 pAdapter->sessionId, &setKey, &roamId );
3196
3197 if ( 0 != status )
3198 {
3199 hddLog(VOS_TRACE_LEVEL_ERROR,
3200 "%s: sme_RoamSetKey failure, returned %d",
3201 __func__, status);
3202 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3203 return -EINVAL;
3204 }
3205 }
3206 }
3207#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003208 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003209 return status;
3210}
3211
3212/*
3213 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3214 * This function is used to set the default tx key index
3215 */
3216#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3217static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3218 struct net_device *ndev,
3219 u8 key_index,
3220 bool unicast, bool multicast)
3221#else
3222static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3223 struct net_device *ndev,
3224 u8 key_index)
3225#endif
3226{
3227 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3228 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3229 int status = 0;
3230 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3231
3232 ENTER();
3233
3234 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3235 __func__,pAdapter->device_mode, key_index);
3236
3237 if (CSR_MAX_NUM_KEY <= key_index)
3238 {
3239 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3240 key_index);
3241
3242 return -EINVAL;
3243 }
3244
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003245 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3246 {
3247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3248 "%s:LOGP in Progress. Ignore!!!", __func__);
3249 return -EAGAIN;
3250 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003251
3252 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3253#ifdef WLAN_FEATURE_P2P
3254 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3255#endif
3256 )
3257 {
3258 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3259 (eCSR_ENCRYPT_TYPE_TKIP !=
3260 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3261 (eCSR_ENCRYPT_TYPE_AES !=
3262 pWextState->roamProfile.EncryptionType.encryptionType[0])
3263 )
3264 {
3265 /* if default key index is not same as previous one,
3266 * then update the default key index */
3267
3268 tCsrRoamSetKey setKey;
3269 v_U32_t roamId= 0xFF;
3270 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3271
3272 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3273 __func__, key_index);
3274
3275 Keys->defaultIndex = (u8)key_index;
3276 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3277 setKey.keyId = key_index;
3278 setKey.keyLength = Keys->KeyLength[key_index];
3279
3280 vos_mem_copy(&setKey.Key[0],
3281 &Keys->KeyMaterial[key_index][0],
3282 Keys->KeyLength[key_index]);
3283
3284 setKey.keyDirection = eSIR_TX_ONLY;
3285
3286 vos_mem_copy(setKey.peerMac,
3287 &pHddStaCtx->conn_info.bssId[0],
3288 WNI_CFG_BSSID_LEN);
3289
3290 setKey.encType =
3291 pWextState->roamProfile.EncryptionType.encryptionType[0];
3292
3293 /* issue set key request */
3294 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3295 pAdapter->sessionId, &setKey, &roamId );
3296
3297 if ( 0 != status )
3298 {
3299 hddLog(VOS_TRACE_LEVEL_ERROR,
3300 "%s: sme_RoamSetKey failed, returned %d", __func__,
3301 status);
3302 return -EINVAL;
3303 }
3304 }
3305 }
3306
3307 /* In SoftAp mode setting key direction for default mode */
3308 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3309 {
3310 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3311 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3312 (eCSR_ENCRYPT_TYPE_AES !=
3313 pWextState->roamProfile.EncryptionType.encryptionType[0])
3314 )
3315 {
3316 /* Saving key direction for default key index to TX default */
3317 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3318 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3319 }
3320 }
3321
3322 return status;
3323}
3324
3325/**
3326 * FUNCTION: wlan_hdd_cfg80211_set_channel
3327 * This function is used to set the channel number
3328 */
3329int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3330 struct ieee80211_channel *chan,
3331 enum nl80211_channel_type channel_type
3332 )
3333{
3334 v_U32_t num_ch = 0;
3335 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003336 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003337 int freq = chan->center_freq; /* freq is in MHZ */
3338
3339 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003340
3341 if( NULL == dev )
3342 {
3343 hddLog(VOS_TRACE_LEVEL_ERROR,
3344 "%s: Called with dev = NULL.\n", __func__);
3345 return -ENODEV;
3346 }
3347 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003348
3349 hddLog(VOS_TRACE_LEVEL_INFO,
3350 "%s: device_mode = %d freq = %d \n",__func__,
3351 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003352 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3353 {
3354 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3355 return -EAGAIN;
3356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003357
3358 /*
3359 * Do freq to chan conversion
3360 * TODO: for 11a
3361 */
3362
3363 channel = ieee80211_frequency_to_channel(freq);
3364
3365 /* Check freq range */
3366 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3367 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3368 {
3369 hddLog(VOS_TRACE_LEVEL_ERROR,
3370 "%s: Channel [%d] is outside valid range from %d to %d\n",
3371 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3372 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3373 return -EINVAL;
3374 }
3375
3376 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3377
3378 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3379#ifdef WLAN_FEATURE_P2P
3380 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3381#endif
3382 )
3383 {
3384 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3385 {
3386 hddLog(VOS_TRACE_LEVEL_ERROR,
3387 "%s: Invalid Channel [%d] \n", __func__, channel);
3388 return -EINVAL;
3389 }
3390 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3391 "%s: set channel to [%d] for device mode =%d",
3392 __func__, channel,pAdapter->device_mode);
3393 }
3394 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3395#ifdef WLAN_FEATURE_P2P
3396 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3397#endif
3398 )
3399 {
3400 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3401 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3402 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3403
3404 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3405 {
3406 /* Link is up then return cant set channel*/
3407 hddLog( VOS_TRACE_LEVEL_ERROR,
3408 "%s: IBSS Associated, can't set the channel\n", __func__);
3409 return -EINVAL;
3410 }
3411
3412 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3413 pHddStaCtx->conn_info.operationChannel = channel;
3414 pRoamProfile->ChannelInfo.ChannelList =
3415 &pHddStaCtx->conn_info.operationChannel;
3416 }
3417 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3418#ifdef WLAN_FEATURE_P2P
3419 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3420#endif
3421 )
3422 {
3423 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3424
3425 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3426 {
3427 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3428
3429 /* If auto channel selection is configured as enable/ 1 then ignore
3430 channel set by supplicant
3431 */
3432 if ( cfg_param->apAutoChannelSelection )
3433 {
3434 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3435
3436 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3437 "%s: set channel to auto channel (0) for device mode =%d",
3438 __func__, pAdapter->device_mode);
3439 }
3440 }
3441 }
3442 else
3443 {
3444 hddLog(VOS_TRACE_LEVEL_FATAL,
3445 "%s: Invalid device mode failed to set valid channel", __func__);
3446 return -EINVAL;
3447 }
3448 EXIT();
3449 return 0;
3450}
3451
3452
3453
3454/*
3455 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3456 * This function is used to inform the BSS details to nl80211 interface.
3457 */
3458static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3459 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3460{
3461 struct net_device *dev = pAdapter->dev;
3462 struct wireless_dev *wdev = dev->ieee80211_ptr;
3463 struct wiphy *wiphy = wdev->wiphy;
3464 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3465 int chan_no;
3466 int ie_length;
3467 const char *ie;
3468 unsigned int freq;
3469 struct ieee80211_channel *chan;
3470 int rssi = 0;
3471 struct cfg80211_bss *bss = NULL;
3472
3473 ENTER();
3474
3475 if( NULL == pBssDesc )
3476 {
3477 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3478 return bss;
3479 }
3480
3481 chan_no = pBssDesc->channelId;
3482 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3483 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3484
3485 if( NULL == ie )
3486 {
3487 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3488 return bss;
3489 }
3490
3491#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3492 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3493 {
3494 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3495 }
3496 else
3497 {
3498 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3499 }
3500#else
3501 freq = ieee80211_channel_to_frequency(chan_no);
3502#endif
3503
3504 chan = __ieee80211_get_channel(wiphy, freq);
3505
3506 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3507 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3508 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3509 if (bss == NULL)
3510 {
3511 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3512
3513 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3514 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3515 pBssDesc->capabilityInfo,
3516 pBssDesc->beaconInterval, ie, ie_length,
3517 rssi, GFP_KERNEL ));
3518}
3519 else
3520 {
3521 return bss;
3522 }
3523}
3524
3525
3526
3527/*
3528 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3529 * This function is used to inform the BSS details to nl80211 interface.
3530 */
3531struct cfg80211_bss*
3532wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3533 tSirBssDescription *bss_desc
3534 )
3535{
3536 /*
3537 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3538 already exists in bss data base of cfg80211 for that particular BSS ID.
3539 Using cfg80211_inform_bss_frame to update the bss entry instead of
3540 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3541 now there is no possibility to get the mgmt(probe response) frame from PE,
3542 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3543 cfg80211_inform_bss_frame.
3544 */
3545 struct net_device *dev = pAdapter->dev;
3546 struct wireless_dev *wdev = dev->ieee80211_ptr;
3547 struct wiphy *wiphy = wdev->wiphy;
3548 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003549#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3550 qcom_ie_age *qie_age = NULL;
3551 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3552#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003553 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003554#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003555 const char *ie =
3556 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3557 unsigned int freq;
3558 struct ieee80211_channel *chan;
3559 struct ieee80211_mgmt *mgmt =
3560 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3561 struct cfg80211_bss *bss_status = NULL;
3562 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3563 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003564#ifdef WLAN_OPEN_SOURCE
3565 struct timespec ts;
3566#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003567
3568 ENTER();
3569
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003570 if (!mgmt)
3571 return NULL;
3572
Jeff Johnson295189b2012-06-20 16:38:30 -07003573 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003574
3575#ifdef WLAN_OPEN_SOURCE
3576 /* Android does not want the timestamp from the frame.
3577 Instead it wants a monotonic increasing value */
3578 get_monotonic_boottime(&ts);
3579 mgmt->u.probe_resp.timestamp =
3580 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3581#else
3582 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003583 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3584 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003585
3586#endif
3587
Jeff Johnson295189b2012-06-20 16:38:30 -07003588 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3589 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003590
3591#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3592 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3593 /* Assuming this is the last IE, copy at the end */
3594 ie_length -=sizeof(qcom_ie_age);
3595 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3596 qie_age->element_id = QCOM_VENDOR_IE_ID;
3597 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3598 qie_age->oui_1 = QCOM_OUI1;
3599 qie_age->oui_2 = QCOM_OUI2;
3600 qie_age->oui_3 = QCOM_OUI3;
3601 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3602 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3603#endif
3604
Jeff Johnson295189b2012-06-20 16:38:30 -07003605 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3606
3607 mgmt->frame_control |=
3608 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3609
3610#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3611 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3612 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3613 {
3614 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3615 }
3616 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3617 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3618
3619 {
3620 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3621 }
3622 else
3623 {
3624 kfree(mgmt);
3625 return NULL;
3626 }
3627#else
3628 freq = ieee80211_channel_to_frequency(chan_no);
3629#endif
3630 chan = __ieee80211_get_channel(wiphy, freq);
3631
3632 /*To keep the rssi icon of the connected AP in the scan window
3633 *and the rssi icon of the wireless networks in sync
3634 * */
3635 if (( eConnectionState_Associated ==
3636 pAdapter->sessionCtx.station.conn_info.connState ) &&
3637 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3638 pAdapter->sessionCtx.station.conn_info.bssId,
3639 WNI_CFG_BSSID_LEN)))
3640 {
3641 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3642 rssi = (pAdapter->rssi * 100);
3643 }
3644 else
3645 {
3646 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3647 }
3648
3649 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3650 frame_len, rssi, GFP_KERNEL);
3651 kfree(mgmt);
3652 return bss_status;
3653}
3654
3655/*
3656 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3657 * This function is used to update the BSS data base of CFG8011
3658 */
3659struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3660 tCsrRoamInfo *pRoamInfo
3661 )
3662{
3663 tCsrRoamConnectedProfile roamProfile;
3664 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3665 struct cfg80211_bss *bss = NULL;
3666
3667 ENTER();
3668
3669 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3670 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3671
3672 if (NULL != roamProfile.pBssDesc)
3673 {
3674 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3675 &roamProfile);
3676
3677 if (NULL == bss)
3678 {
3679 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3680 __func__);
3681 }
3682
3683 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3684 }
3685 else
3686 {
3687 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3688 __func__);
3689 }
3690 return bss;
3691}
3692
3693/*
3694 * FUNCTION: wlan_hdd_cfg80211_update_bss
3695 */
3696static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3697 hdd_adapter_t *pAdapter
3698 )
3699{
3700 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3701 tCsrScanResultInfo *pScanResult;
3702 eHalStatus status = 0;
3703 tScanResultHandle pResult;
3704 struct cfg80211_bss *bss_status = NULL;
3705
3706 ENTER();
3707
3708 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3709 {
3710 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3711 return -EAGAIN;
3712 }
3713
3714 /*
3715 * start getting scan results and populate cgf80211 BSS database
3716 */
3717 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3718
3719 /* no scan results */
3720 if (NULL == pResult)
3721 {
3722 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3723 return status;
3724 }
3725
3726 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3727
3728 while (pScanResult)
3729 {
3730 /*
3731 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3732 * entry already exists in bss data base of cfg80211 for that
3733 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3734 * bss entry instead of cfg80211_inform_bss, But this call expects
3735 * mgmt packet as input. As of now there is no possibility to get
3736 * the mgmt(probe response) frame from PE, converting bss_desc to
3737 * ieee80211_mgmt(probe response) and passing to c
3738 * fg80211_inform_bss_frame.
3739 * */
3740
3741 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3742 &pScanResult->BssDescriptor);
3743
3744
3745 if (NULL == bss_status)
3746 {
3747 hddLog(VOS_TRACE_LEVEL_INFO,
3748 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3749 }
3750 else
3751 {
3752 cfg80211_put_bss(bss_status);
3753 }
3754
3755 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3756 }
3757
3758 sme_ScanResultPurge(hHal, pResult);
3759
3760 return 0;
3761}
3762
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003763void
3764hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3765{
3766 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003767 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3768 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3769 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003770} /****** end hddPrintMacAddr() ******/
3771
3772void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003773hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003774{
3775 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003776 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3777 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3778 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3779 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003780} /****** end hddPrintPmkId() ******/
3781
3782//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3783//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3784
3785//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3786//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3787
3788#define dump_bssid(bssid) \
3789 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003790 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3791 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3792 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003793 }
3794
3795#define dump_pmkid(pMac, pmkid) \
3796 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003797 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3798 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3799 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003800 }
3801
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003802#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003803/*
3804 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3805 * This function is used to notify the supplicant of a new PMKSA candidate.
3806 */
3807int wlan_hdd_cfg80211_pmksa_candidate_notify(
3808 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3809 int index, bool preauth )
3810{
Jeff Johnsone7245742012-09-05 17:12:55 -07003811#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003812 struct net_device *dev = pAdapter->dev;
3813
3814 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003815 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003816
3817 if( NULL == pRoamInfo )
3818 {
3819 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3820 return -EINVAL;
3821 }
3822
3823 dump_bssid(pRoamInfo->bssid);
3824 cfg80211_pmksa_candidate_notify(dev, index,
3825 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003826#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003827 return 0;
3828}
3829#endif //FEATURE_WLAN_LFR
3830
Jeff Johnson295189b2012-06-20 16:38:30 -07003831/*
3832 * FUNCTION: hdd_cfg80211_scan_done_callback
3833 * scanning callback function, called after finishing scan
3834 *
3835 */
3836static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3837 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3838{
3839 struct net_device *dev = (struct net_device *) pContext;
3840 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3841 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003842 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3843 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003844 struct cfg80211_scan_request *req = NULL;
3845 int ret = 0;
3846
3847 ENTER();
3848
3849 hddLog(VOS_TRACE_LEVEL_INFO,
3850 "%s called with halHandle = %p, pContext = %p,"
3851 "scanID = %d, returned status = %d\n",
3852 __func__, halHandle, pContext, (int) scanId, (int) status);
3853
3854 //Block on scan req completion variable. Can't wait forever though.
3855 ret = wait_for_completion_interruptible_timeout(
3856 &pScanInfo->scan_req_completion_event,
3857 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3858 if (!ret)
3859 {
3860 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003861 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 }
3863
3864 if(pScanInfo->mScanPending != VOS_TRUE)
3865 {
3866 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003867 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003868 }
3869
3870 /* Check the scanId */
3871 if (pScanInfo->scanId != scanId)
3872 {
3873 hddLog(VOS_TRACE_LEVEL_INFO,
3874 "%s called with mismatched scanId pScanInfo->scanId = %d "
3875 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3876 (int) scanId);
3877 }
3878
Jeff Johnson295189b2012-06-20 16:38:30 -07003879 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3880 pAdapter);
3881
3882 if (0 > ret)
3883 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3884
3885
3886 /* If any client wait scan result through WEXT
3887 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003888 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003889 {
3890 /* The other scan request waiting for current scan finish
3891 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003892 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003893 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003894 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 }
3896 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003897 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003898 {
3899 struct net_device *dev = pAdapter->dev;
3900 union iwreq_data wrqu;
3901 int we_event;
3902 char *msg;
3903
3904 memset(&wrqu, '\0', sizeof(wrqu));
3905 we_event = SIOCGIWSCAN;
3906 msg = NULL;
3907 wireless_send_event(dev, we_event, &wrqu, msg);
3908 }
3909 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003910 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003911
3912 /* Get the Scan Req */
3913 req = pAdapter->request;
3914
3915 if (!req)
3916 {
3917 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003918 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003919 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003920 }
3921
3922 /*
3923 * setting up 0, just in case.
3924 */
3925 req->n_ssids = 0;
3926 req->n_channels = 0;
3927 req->ie = 0;
3928
Jeff Johnson295189b2012-06-20 16:38:30 -07003929 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003930 /* Scan is no longer pending */
3931 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003932
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003933 /*
3934 * cfg80211_scan_done informing NL80211 about completion
3935 * of scanning
3936 */
3937 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003938 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003939
Jeff Johnsone7245742012-09-05 17:12:55 -07003940allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003941 /* release the wake lock at the end of the scan*/
3942 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003943
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003944 /* Acquire wakelock to handle the case where APP's tries to suspend
3945 * immediatly after the driver gets connect request(i.e after scan)
3946 * from supplicant, this result in app's is suspending and not able
3947 * to process the connect request to AP */
3948 hdd_allow_suspend_timeout(100);
3949
Jeff Johnson295189b2012-06-20 16:38:30 -07003950 EXIT();
3951 return 0;
3952}
3953
3954/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08003955 * FUNCTION: hdd_isScanAllowed
3956 * Go through each adapter and check if scan allowed
3957 *
3958 */
3959v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
3960{
3961 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3962 hdd_station_ctx_t *pHddStaCtx = NULL;
3963 hdd_adapter_t *pAdapter = NULL;
3964 VOS_STATUS status = 0;
3965 v_U8_t staId = 0;
3966 v_U8_t *staMac = NULL;
3967
3968 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3969
3970 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3971 {
3972 pAdapter = pAdapterNode->pAdapter;
3973
3974 if( pAdapter )
3975 {
3976 hddLog(VOS_TRACE_LEVEL_INFO,
3977 "%s: Adapter with device mode %d exists",
3978 __func__, pAdapter->device_mode);
3979 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3980 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3981 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
3982 {
3983 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3984 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
3985 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
3986 {
3987 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
3988 hddLog(VOS_TRACE_LEVEL_ERROR,
3989 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
3990 "middle of WPS/EAPOL exchange.", __func__,
3991 staMac[0], staMac[1], staMac[2],
3992 staMac[3], staMac[4], staMac[5]);
3993 return VOS_FALSE;
3994 }
3995 }
3996 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
3997 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
3998 {
3999 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4000 {
4001 if ((pAdapter->aStaInfo[staId].isUsed) &&
4002 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4003 {
4004 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4005
4006 hddLog(VOS_TRACE_LEVEL_ERROR,
4007 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4008 "middle of WPS/EAPOL exchange.", __func__,
4009 staMac[0], staMac[1], staMac[2],
4010 staMac[3], staMac[4], staMac[5]);
4011 return VOS_FALSE;
4012 }
4013 }
4014 }
4015 }
4016 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4017 pAdapterNode = pNext;
4018 }
4019 hddLog(VOS_TRACE_LEVEL_INFO,
4020 "%s: Scan allowed", __func__);
4021 return VOS_TRUE;
4022}
4023
4024/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004025 * FUNCTION: wlan_hdd_cfg80211_scan
4026 * this scan respond to scan trigger and update cfg80211 scan database
4027 * later, scan dump command can be used to recieve scan results
4028 */
4029int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
4030 struct cfg80211_scan_request *request)
4031{
4032 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4033 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4034 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4035 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4036 tCsrScanRequest scanRequest;
4037 tANI_U8 *channelList = NULL, i;
4038 v_U32_t scanId = 0;
4039 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004040 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004041#ifdef WLAN_FEATURE_P2P
4042 v_U8_t* pP2pIe = NULL;
4043#endif
4044
4045 ENTER();
4046
4047 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4048 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004049
4050 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4051 (eConnectionState_Connecting ==
4052 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4053 {
4054 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004055 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4056 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004057 return -EBUSY;
4058 }
4059
Jeff Johnson295189b2012-06-20 16:38:30 -07004060#ifdef WLAN_BTAMP_FEATURE
4061 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004062 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004063 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004064 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004065 "%s: No scanning when AMP is on", __func__);
4066 return -EOPNOTSUPP;
4067 }
4068#endif
4069 //Scan on any other interface is not supported.
4070 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4071 {
4072 hddLog(VOS_TRACE_LEVEL_ERROR,
4073 "%s: Not scanning on device_mode = %d",
4074 __func__, pAdapter->device_mode);
4075 return -EOPNOTSUPP;
4076 }
4077
4078 if (TRUE == pScanInfo->mScanPending)
4079 {
4080 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4081 return -EBUSY;
4082 }
4083
4084 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4085 {
4086 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4087 "%s:LOGP in Progress. Ignore!!!", __func__);
4088 return -EAGAIN;
4089 }
4090
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004091 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4092 {
4093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4094 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4095 return -EAGAIN;
4096 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004097 //Don't Allow Scan and return busy if Remain On
4098 //Channel and action frame is pending
4099 //Otherwise Cancel Remain On Channel and allow Scan
4100 //If no action frame pending
4101 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4102 {
4103 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4104 return -EBUSY;
4105 }
4106
Jeff Johnson295189b2012-06-20 16:38:30 -07004107 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4108 {
4109 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004110 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004111 return -EAGAIN;
4112 }
4113 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4114 {
4115 hddLog(VOS_TRACE_LEVEL_WARN,
4116 "%s: MAX TM Level Scan not allowed", __func__);
4117 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4118 return -EBUSY;
4119 }
4120 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4121
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004122 /* Check if scan is allowed at this point of time.
4123 */
4124 if (!hdd_isScanAllowed(pHddCtx))
4125 {
4126 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4127 return -EBUSY;
4128 }
4129
Jeff Johnson295189b2012-06-20 16:38:30 -07004130 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4131
4132 if (NULL != request)
4133 {
4134 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4135 (int)request->n_ssids);
4136
4137 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4138 * Becasue of this, driver is assuming that this is not wildcard scan and so
4139 * is not aging out the scan results.
4140 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004141 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004142 {
4143 request->n_ssids = 0;
4144 }
4145
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004146 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 {
4148 tCsrSSIDInfo *SsidInfo;
4149 int j;
4150 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4151 /* Allocate num_ssid tCsrSSIDInfo structure */
4152 SsidInfo = scanRequest.SSIDs.SSIDList =
4153 ( tCsrSSIDInfo *)vos_mem_malloc(
4154 request->n_ssids*sizeof(tCsrSSIDInfo));
4155
4156 if(NULL == scanRequest.SSIDs.SSIDList)
4157 {
4158 hddLog(VOS_TRACE_LEVEL_ERROR,
4159 "memory alloc failed SSIDInfo buffer");
4160 return -ENOMEM;
4161 }
4162
4163 /* copy all the ssid's and their length */
4164 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4165 {
4166 /* get the ssid length */
4167 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4168 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4169 SsidInfo->SSID.length);
4170 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4171 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4172 j, SsidInfo->SSID.ssId);
4173 }
4174 /* set the scan type to active */
4175 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4176 }
4177 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4178 {
4179 /* set the scan type to active */
4180 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4181 }
4182 else
4183 {
4184 /*Set the scan type to default type, in this case it is ACTIVE*/
4185 scanRequest.scanType = pScanInfo->scan_mode;
4186 }
4187 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4188 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4189 }
4190 else
4191 {
4192 /* set the scan type to active */
4193 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4194 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4195
4196 /* set min and max channel time to zero */
4197 scanRequest.minChnTime = 0;
4198 scanRequest.maxChnTime = 0;
4199 }
4200
4201 /* set BSSType to default type */
4202 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4203
4204 /*TODO: scan the requested channels only*/
4205
4206 /*Right now scanning all the channels */
4207 if( request )
4208 {
4209 if( request->n_channels )
4210 {
4211 channelList = vos_mem_malloc( request->n_channels );
4212 if( NULL == channelList )
4213 {
4214 status = -ENOMEM;
4215 goto free_mem;
4216 }
4217
4218 for( i = 0 ; i < request->n_channels ; i++ )
4219 channelList[i] = request->channels[i]->hw_value;
4220 }
4221
4222 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4223 scanRequest.ChannelInfo.ChannelList = channelList;
4224
4225 /* set requestType to full scan */
4226 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004227
4228 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4229 * search (Flush on both full scan and social scan but not on single
4230 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4231 */
4232
4233 /* Supplicant does single channel scan after 8-way handshake
4234 * and in that case driver shoudnt flush scan results. If
4235 * driver flushes the scan results here and unfortunately if
4236 * the AP doesnt respond to our probe req then association
4237 * fails which is not desired
4238 */
4239
4240 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4241 {
4242 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4243 pAdapter->sessionId );
4244 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004245
4246 if( request->ie_len )
4247 {
4248 /* save this for future association (join requires this) */
4249 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4250 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4251 pScanInfo->scanAddIE.length = request->ie_len;
4252
4253 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004254 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4255 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004256 )
4257 {
4258 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4259 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4260 }
4261
4262 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4263 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4264
4265#ifdef WLAN_FEATURE_P2P
4266 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4267 request->ie_len);
4268 if (pP2pIe != NULL)
4269 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004270#ifdef WLAN_FEATURE_P2P_DEBUG
4271 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4272 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4273 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4274 {
4275 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4276 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4277 "Go nego completed to Connection is started");
4278 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4279 "for 8way Handshake");
4280 }
4281 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4282 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4283 {
4284 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4285 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4286 "Disconnected state to Connection is started");
4287 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4288 "for 4way Handshake");
4289 }
4290#endif
4291
Jeff Johnsone7245742012-09-05 17:12:55 -07004292 /* no_cck will be set during p2p find to disable 11b rates */
4293 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004294 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004295 hddLog(VOS_TRACE_LEVEL_INFO,
4296 "%s: This is a P2P Search", __func__);
4297 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004298
Jeff Johnsone7245742012-09-05 17:12:55 -07004299 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4300 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004301 /* set requestType to P2P Discovery */
4302 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004303 }
4304
4305 /*
4306 Skip Dfs Channel in case of P2P Search
4307 if it is set in ini file
4308 */
4309 if(cfg_param->skipDfsChnlInP2pSearch)
4310 {
4311 scanRequest.skipDfsChnlInP2pSearch = 1;
4312 }
4313 else
4314 {
4315 scanRequest.skipDfsChnlInP2pSearch = 0;
4316 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004317
Jeff Johnson295189b2012-06-20 16:38:30 -07004318 }
4319 }
4320#endif
4321 }
4322 }
4323
4324 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4325
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004326 /* acquire the wakelock to avoid the apps suspend during the scan. To
4327 * address the following issues.
4328 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4329 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4330 * for long time, this result in apps running at full power for long time.
4331 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4332 * be stuck in full power because of resume BMPS
4333 */
4334 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004335
4336 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004337 pAdapter->sessionId, &scanRequest, &scanId,
4338 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004339
Jeff Johnson295189b2012-06-20 16:38:30 -07004340 if (eHAL_STATUS_SUCCESS != status)
4341 {
4342 hddLog(VOS_TRACE_LEVEL_ERROR,
4343 "%s: sme_ScanRequest returned error %d", __func__, status);
4344 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004345 if(eHAL_STATUS_RESOURCES == status)
4346 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004347 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 -07004348 status = -EBUSY;
4349 } else {
4350 status = -EIO;
4351 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004352 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004353 goto free_mem;
4354 }
4355
4356 pScanInfo->mScanPending = TRUE;
4357 pAdapter->request = request;
4358 pScanInfo->scanId = scanId;
4359
4360 complete(&pScanInfo->scan_req_completion_event);
4361
4362free_mem:
4363 if( scanRequest.SSIDs.SSIDList )
4364 {
4365 vos_mem_free(scanRequest.SSIDs.SSIDList);
4366 }
4367
4368 if( channelList )
4369 vos_mem_free( channelList );
4370
4371 EXIT();
4372
4373 return status;
4374}
4375
4376/*
4377 * FUNCTION: wlan_hdd_cfg80211_connect_start
4378 * This function is used to start the association process
4379 */
4380int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004381 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004382{
4383 int status = 0;
4384 hdd_wext_state_t *pWextState;
4385 v_U32_t roamId;
4386 tCsrRoamProfile *pRoamProfile;
4387 eMib_dot11DesiredBssType connectedBssType;
4388 eCsrAuthType RSNAuthType;
4389
4390 ENTER();
4391
4392 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4393
4394 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4395 {
4396 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4397 return -EINVAL;
4398 }
4399
4400 pRoamProfile = &pWextState->roamProfile;
4401
4402 if (pRoamProfile)
4403 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004404 int ret = 0;
4405 hdd_station_ctx_t *pHddStaCtx;
4406 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4407 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4408
4409 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4410 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4411 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004412 {
4413 /* Issue disconnect to CSR */
4414 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4415 if( eHAL_STATUS_SUCCESS ==
4416 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4417 pAdapter->sessionId,
4418 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4419 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004420 ret = wait_for_completion_interruptible_timeout(
4421 &pAdapter->disconnect_comp_var,
4422 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4423 if (0 == ret)
4424 {
4425 VOS_ASSERT(0);
4426 }
4427 }
4428 }
4429 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4430 {
4431 ret = wait_for_completion_interruptible_timeout(
4432 &pAdapter->disconnect_comp_var,
4433 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4434 if (0 == ret)
4435 {
4436 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004437 }
4438 }
4439
4440 if (HDD_WMM_USER_MODE_NO_QOS ==
4441 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4442 {
4443 /*QoS not enabled in cfg file*/
4444 pRoamProfile->uapsd_mask = 0;
4445 }
4446 else
4447 {
4448 /*QoS enabled, update uapsd mask from cfg file*/
4449 pRoamProfile->uapsd_mask =
4450 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4451 }
4452
4453 pRoamProfile->SSIDs.numOfSSIDs = 1;
4454 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4455 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4456 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4457 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4458 ssid, ssid_len);
4459
4460 if (bssid)
4461 {
4462 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4463 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4464 WNI_CFG_BSSID_LEN);
4465 /* Save BSSID in seperate variable as well, as RoamProfile
4466 BSSID is getting zeroed out in the association process. And in
4467 case of join failure we should send valid BSSID to supplicant
4468 */
4469 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4470 WNI_CFG_BSSID_LEN);
4471 }
4472
4473 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4474 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4475 {
4476 /*set gen ie*/
4477 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4478 /*set auth*/
4479 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4480 }
4481 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4482 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4483 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4484 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4485 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4486 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4487 )
4488 {
4489 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4490 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4491 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4492 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4493 eCSR_AUTH_TYPE_AUTOSWITCH;
4494 pWextState->roamProfile.AuthType.authType[0] =
4495 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4496 }
4497#ifdef FEATURE_WLAN_WAPI
4498 if (pAdapter->wapi_info.nWapiMode)
4499 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004500 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004501 switch (pAdapter->wapi_info.wapiAuthMode)
4502 {
4503 case WAPI_AUTH_MODE_PSK:
4504 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004505 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004506 pAdapter->wapi_info.wapiAuthMode);
4507 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4508 break;
4509 }
4510 case WAPI_AUTH_MODE_CERT:
4511 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004512 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004513 pAdapter->wapi_info.wapiAuthMode);
4514 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4515 break;
4516 }
4517 } // End of switch
4518 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4519 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4520 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004521 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 pRoamProfile->AuthType.numEntries = 1;
4523 pRoamProfile->EncryptionType.numEntries = 1;
4524 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4525 pRoamProfile->mcEncryptionType.numEntries = 1;
4526 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4527 }
4528 }
4529#endif /* FEATURE_WLAN_WAPI */
4530 pRoamProfile->csrPersona = pAdapter->device_mode;
4531
Jeff Johnson32d95a32012-09-10 13:15:23 -07004532 if( operatingChannel )
4533 {
4534 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4535 pRoamProfile->ChannelInfo.numOfChannels = 1;
4536 }
4537
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004538 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4539 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4540 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4541 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004542 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4543 */
4544 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4545 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4546 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004547
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4549 pAdapter->sessionId, pRoamProfile, &roamId);
4550
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004551 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304552 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4553
4554 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004555 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4556 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4557 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304558 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004559 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304560 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004561
4562 pRoamProfile->ChannelInfo.ChannelList = NULL;
4563 pRoamProfile->ChannelInfo.numOfChannels = 0;
4564
Jeff Johnson295189b2012-06-20 16:38:30 -07004565 }
4566 else
4567 {
4568 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4569 return -EINVAL;
4570 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004571 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004572 return status;
4573}
4574
4575/*
4576 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4577 * This function is used to set the authentication type (OPEN/SHARED).
4578 *
4579 */
4580static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4581 enum nl80211_auth_type auth_type)
4582{
4583 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4584 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4585
4586 ENTER();
4587
4588 /*set authentication type*/
4589 switch (auth_type)
4590 {
4591 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4592 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004593#ifdef WLAN_FEATURE_VOWIFI_11R
4594 case NL80211_AUTHTYPE_FT:
4595#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004596 hddLog(VOS_TRACE_LEVEL_INFO,
4597 "%s: set authentication type to OPEN", __func__);
4598 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4599 break;
4600
4601 case NL80211_AUTHTYPE_SHARED_KEY:
4602 hddLog(VOS_TRACE_LEVEL_INFO,
4603 "%s: set authentication type to SHARED", __func__);
4604 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4605 break;
4606#ifdef FEATURE_WLAN_CCX
4607 case NL80211_AUTHTYPE_NETWORK_EAP:
4608 hddLog(VOS_TRACE_LEVEL_INFO,
4609 "%s: set authentication type to CCKM WPA", __func__);
4610 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4611 break;
4612#endif
4613
4614
4615 default:
4616 hddLog(VOS_TRACE_LEVEL_ERROR,
4617 "%s: Unsupported authentication type %d", __func__,
4618 auth_type);
4619 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4620 return -EINVAL;
4621 }
4622
4623 pWextState->roamProfile.AuthType.authType[0] =
4624 pHddStaCtx->conn_info.authType;
4625 return 0;
4626}
4627
4628/*
4629 * FUNCTION: wlan_hdd_set_akm_suite
4630 * This function is used to set the key mgmt type(PSK/8021x).
4631 *
4632 */
4633static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4634 u32 key_mgmt
4635 )
4636{
4637 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4638 ENTER();
4639
4640 /*set key mgmt type*/
4641 switch(key_mgmt)
4642 {
4643 case WLAN_AKM_SUITE_PSK:
4644 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4645 __func__);
4646 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4647 break;
4648
4649 case WLAN_AKM_SUITE_8021X:
4650 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4651 __func__);
4652 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4653 break;
4654#ifdef FEATURE_WLAN_CCX
4655#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4656#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4657 case WLAN_AKM_SUITE_CCKM:
4658 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4659 __func__);
4660 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4661 break;
4662#endif
4663
4664 default:
4665 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4666 __func__, key_mgmt);
4667 return -EINVAL;
4668
4669 }
4670 return 0;
4671}
4672
4673/*
4674 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4675 * This function is used to set the encryption type
4676 * (NONE/WEP40/WEP104/TKIP/CCMP).
4677 */
4678static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4679 u32 cipher,
4680 bool ucast
4681 )
4682{
4683 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4684 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4685 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4686
4687 ENTER();
4688
4689 if (!cipher)
4690 {
4691 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4692 __func__, cipher);
4693 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4694 }
4695 else
4696 {
4697
4698 /*set encryption method*/
4699 switch (cipher)
4700 {
4701 case IW_AUTH_CIPHER_NONE:
4702 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4703 break;
4704
4705 case WLAN_CIPHER_SUITE_WEP40:
4706 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4707 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4708 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4709 else
4710 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4711 break;
4712
4713 case WLAN_CIPHER_SUITE_WEP104:
4714 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4715 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4716 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4717 else
4718 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4719 break;
4720
4721 case WLAN_CIPHER_SUITE_TKIP:
4722 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4723 break;
4724
4725 case WLAN_CIPHER_SUITE_CCMP:
4726 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4727 break;
4728#ifdef FEATURE_WLAN_WAPI
4729 case WLAN_CIPHER_SUITE_SMS4:
4730 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4731 break;
4732#endif
4733
4734#ifdef FEATURE_WLAN_CCX
4735 case WLAN_CIPHER_SUITE_KRK:
4736 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4737 break;
4738#endif
4739 default:
4740 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4741 __func__, cipher);
4742 return -EOPNOTSUPP;
4743 }
4744 }
4745
4746 if (ucast)
4747 {
4748 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4749 __func__, encryptionType);
4750 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4751 pWextState->roamProfile.EncryptionType.numEntries = 1;
4752 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4753 encryptionType;
4754 }
4755 else
4756 {
4757 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4758 __func__, encryptionType);
4759 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4760 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4761 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4762 }
4763
4764 return 0;
4765}
4766
4767
4768/*
4769 * FUNCTION: wlan_hdd_cfg80211_set_ie
4770 * This function is used to parse WPA/RSN IE's.
4771 */
4772int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4773 u8 *ie,
4774 size_t ie_len
4775 )
4776{
4777 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4778 u8 *genie = ie;
4779 v_U16_t remLen = ie_len;
4780#ifdef FEATURE_WLAN_WAPI
4781 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4782 u16 *tmp;
4783 v_U16_t akmsuiteCount;
4784 int *akmlist;
4785#endif
4786 ENTER();
4787
4788 /* clear previous assocAddIE */
4789 pWextState->assocAddIE.length = 0;
4790 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4791
4792 while (remLen >= 2)
4793 {
4794 v_U16_t eLen = 0;
4795 v_U8_t elementId;
4796 elementId = *genie++;
4797 eLen = *genie++;
4798 remLen -= 2;
4799
4800 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4801 __func__, elementId, eLen);
4802
4803 switch ( elementId )
4804 {
4805 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004806 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 -07004807 {
4808 hddLog(VOS_TRACE_LEVEL_ERROR,
4809 "%s: Invalid WPA IE", __func__);
4810 return -EINVAL;
4811 }
4812 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4813 {
4814 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4815 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4816 __func__, eLen + 2);
4817
4818 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4819 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004820 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4821 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004822 VOS_ASSERT(0);
4823 return -ENOMEM;
4824 }
4825 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4826 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4827 pWextState->assocAddIE.length += eLen + 2;
4828
4829 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4830 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4831 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4832 }
4833 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4834 {
4835 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4836 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4837 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4838 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4839 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4840 }
4841#ifdef WLAN_FEATURE_P2P
4842 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4843 P2P_OUI_TYPE_SIZE))
4844 /*Consider P2P IE, only for P2P Client */
4845 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4846 {
4847 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4848 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4849 __func__, eLen + 2);
4850
4851 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4852 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004853 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4854 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004855 VOS_ASSERT(0);
4856 return -ENOMEM;
4857 }
4858 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4859 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4860 pWextState->assocAddIE.length += eLen + 2;
4861
4862 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4863 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4864 }
4865#endif
4866#ifdef WLAN_FEATURE_WFD
4867 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4868 WFD_OUI_TYPE_SIZE))
4869 /*Consider WFD IE, only for P2P Client */
4870 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4871 {
4872 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4873 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4874 __func__, eLen + 2);
4875
4876 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4877 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004878 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4879 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004880 VOS_ASSERT(0);
4881 return -ENOMEM;
4882 }
4883 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4884 // WPS IE + P2P IE + WFD IE
4885 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4886 pWextState->assocAddIE.length += eLen + 2;
4887
4888 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4889 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4890 }
4891#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004892 /* Appending HS 2.0 Indication Element in Assiciation Request */
4893 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004894 HS20_OUI_TYPE_SIZE)) )
4895 {
4896 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4897 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4898 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004899
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004900 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4901 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004902 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4903 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004904 VOS_ASSERT(0);
4905 return -ENOMEM;
4906 }
4907 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4908 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004909
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004910 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4911 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4912 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004913
Jeff Johnson295189b2012-06-20 16:38:30 -07004914 break;
4915 case DOT11F_EID_RSN:
4916 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4917 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4918 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4919 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4920 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4921 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004922 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4923 case DOT11F_EID_EXTCAP:
4924 {
4925 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4926 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4927 __func__, eLen + 2);
4928
4929 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4930 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004931 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4932 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004933 VOS_ASSERT(0);
4934 return -ENOMEM;
4935 }
4936 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4937 pWextState->assocAddIE.length += eLen + 2;
4938
4939 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4940 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4941 break;
4942 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004943#ifdef FEATURE_WLAN_WAPI
4944 case WLAN_EID_WAPI:
4945 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4946 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4947 pAdapter->wapi_info.nWapiMode);
4948 tmp = (u16 *)ie;
4949 tmp = tmp + 2; // Skip element Id and Len, Version
4950 akmsuiteCount = WPA_GET_LE16(tmp);
4951 tmp = tmp + 1;
4952 akmlist = (int *)(tmp);
4953 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4954 {
4955 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4956 }
4957 else
4958 {
4959 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4960 VOS_ASSERT(0);
4961 return -EINVAL;
4962 }
4963
4964 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4965 {
4966 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004967 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4969 }
4970 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4971 {
4972 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004973 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004974 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4975 }
4976 break;
4977#endif
4978 default:
4979 hddLog (VOS_TRACE_LEVEL_ERROR,
4980 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004981 /* when Unknown IE is received we should break and continue
4982 * to the next IE in the buffer instead we were returning
4983 * so changing this to break */
4984 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 }
4986 genie += eLen;
4987 remLen -= eLen;
4988 }
4989 EXIT();
4990 return 0;
4991}
4992
4993/*
4994 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4995 * This function is used to initialize the security
4996 * parameters during connect operation.
4997 */
4998int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4999 struct cfg80211_connect_params *req
5000 )
5001{
5002 int status = 0;
5003 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5004 ENTER();
5005
5006 /*set wpa version*/
5007 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5008
5009 if (req->crypto.wpa_versions)
5010 {
5011 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5012 && ( (req->ie_len)
5013 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5014 // Make sure that it is including a WPA IE.
5015 /* Currently NL is putting WPA version 1 even for open,
5016 * since p2p ie is also put in same buffer.
5017 * */
5018 {
5019 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5020 }
5021 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5022 {
5023 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5024 }
5025 }
5026
5027 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5028 pWextState->wpaVersion);
5029
5030 /*set authentication type*/
5031 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5032
5033 if (0 > status)
5034 {
5035 hddLog(VOS_TRACE_LEVEL_ERROR,
5036 "%s: failed to set authentication type ", __func__);
5037 return status;
5038 }
5039
5040 /*set key mgmt type*/
5041 if (req->crypto.n_akm_suites)
5042 {
5043 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5044 if (0 > status)
5045 {
5046 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5047 __func__);
5048 return status;
5049 }
5050 }
5051
5052 /*set pairwise cipher type*/
5053 if (req->crypto.n_ciphers_pairwise)
5054 {
5055 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5056 req->crypto.ciphers_pairwise[0], true);
5057 if (0 > status)
5058 {
5059 hddLog(VOS_TRACE_LEVEL_ERROR,
5060 "%s: failed to set unicast cipher type", __func__);
5061 return status;
5062 }
5063 }
5064 else
5065 {
5066 /*Reset previous cipher suite to none*/
5067 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5068 if (0 > status)
5069 {
5070 hddLog(VOS_TRACE_LEVEL_ERROR,
5071 "%s: failed to set unicast cipher type", __func__);
5072 return status;
5073 }
5074 }
5075
5076 /*set group cipher type*/
5077 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5078 false);
5079
5080 if (0 > status)
5081 {
5082 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5083 __func__);
5084 return status;
5085 }
5086
5087 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5088 if (req->ie_len)
5089 {
5090 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5091 if ( 0 > status)
5092 {
5093 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5094 __func__);
5095 return status;
5096 }
5097 }
5098
5099 /*incase of WEP set default key information*/
5100 if (req->key && req->key_len)
5101 {
5102 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5103 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5104 )
5105 {
5106 if ( IW_AUTH_KEY_MGMT_802_1X
5107 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5108 {
5109 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5110 __func__);
5111 return -EOPNOTSUPP;
5112 }
5113 else
5114 {
5115 u8 key_len = req->key_len;
5116 u8 key_idx = req->key_idx;
5117
5118 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5119 && (CSR_MAX_NUM_KEY > key_idx)
5120 )
5121 {
5122 hddLog(VOS_TRACE_LEVEL_INFO,
5123 "%s: setting default wep key, key_idx = %hu key_len %hu",
5124 __func__, key_idx, key_len);
5125 vos_mem_copy(
5126 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5127 req->key, key_len);
5128 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5129 (u8)key_len;
5130 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5131 }
5132 }
5133 }
5134 }
5135
5136 return status;
5137}
5138
5139/*
5140 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5141 * This function is used to initialize the security
5142 * parameters during connect operation.
5143 */
5144static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5145 struct net_device *ndev,
5146 struct cfg80211_connect_params *req
5147 )
5148{
5149 int status = 0;
5150 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5151 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5152 hdd_context_t *pHddCtx = NULL;
5153
5154 ENTER();
5155
5156 hddLog(VOS_TRACE_LEVEL_INFO,
5157 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5158
5159 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5160 {
5161 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5162 "%s:LOGP in Progress. Ignore!!!", __func__);
5163 return -EAGAIN;
5164 }
5165
5166#ifdef WLAN_BTAMP_FEATURE
5167 //Infra connect not supported when AMP traffic is on.
5168 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5169 {
5170 hddLog(VOS_TRACE_LEVEL_ERROR,
5171 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005172 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005173 }
5174#endif
5175 /*initialise security parameters*/
5176 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5177
5178 if ( 0 > status)
5179 {
5180 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5181 __func__);
5182 return status;
5183 }
5184
5185 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005186 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5188 (vos_concurrent_sessions_running()))
5189 {
5190 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5191
5192 if (NULL != pVosContext)
5193 {
5194 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5195 if(NULL != pHddCtx)
5196 {
5197 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5198 }
5199 }
5200 }
5201
Mohit Khanna765234a2012-09-11 15:08:35 -07005202 if ( req->channel )
5203 {
5204 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5205 req->ssid_len, req->bssid,
5206 req->channel->hw_value);
5207 }
5208 else
5209 {
5210 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5211 req->ssid_len, req->bssid,
5212 0);
5213 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005214
5215 if (0 > status)
5216 {
5217 //ReEnable BMPS if disabled
5218 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5219 (NULL != pHddCtx))
5220 {
5221 //ReEnable Bmps and Imps back
5222 hdd_enable_bmps_imps(pHddCtx);
5223 }
5224
5225 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5226 return status;
5227 }
5228 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5229 EXIT();
5230 return status;
5231}
5232
5233
5234/*
5235 * FUNCTION: wlan_hdd_cfg80211_disconnect
5236 * This function is used to issue a disconnect request to SME
5237 */
5238static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5239 struct net_device *dev,
5240 u16 reason
5241 )
5242{
5243 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5244 tCsrRoamProfile *pRoamProfile =
5245 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5246 int status = 0;
5247 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5248
5249 ENTER();
5250
5251 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5252 __func__,pAdapter->device_mode);
5253
5254 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5255 __func__, reason);
5256
5257 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5258 {
5259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5260 "%s:LOGP in Progress. Ignore!!!",__func__);
5261 return -EAGAIN;
5262 }
5263 if (NULL != pRoamProfile)
5264 {
5265 /*issue disconnect request to SME, if station is in connected state*/
5266 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5267 {
5268 eCsrRoamDisconnectReason reasonCode =
5269 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5270 switch(reason)
5271 {
5272 case WLAN_REASON_MIC_FAILURE:
5273 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5274 break;
5275
5276 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5277 case WLAN_REASON_DISASSOC_AP_BUSY:
5278 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5279 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5280 break;
5281
5282 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5283 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5284 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5285 break;
5286
5287 case WLAN_REASON_DEAUTH_LEAVING:
5288 default:
5289 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5290 break;
5291 }
5292 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5293 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5294 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5295
5296 /*issue disconnect*/
5297 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5298 pAdapter->sessionId, reasonCode);
5299
5300 if ( 0 != status)
5301 {
5302 hddLog(VOS_TRACE_LEVEL_ERROR,
5303 "%s csrRoamDisconnect failure, returned %d \n",
5304 __func__, (int)status );
5305 return -EINVAL;
5306 }
5307
5308 wait_for_completion_interruptible_timeout(
5309 &pAdapter->disconnect_comp_var,
5310 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5311
5312
5313 /*stop tx queues*/
5314 netif_tx_disable(dev);
5315 netif_carrier_off(dev);
5316 }
5317 }
5318 else
5319 {
5320 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5321 }
5322
5323 return status;
5324}
5325
5326/*
5327 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5328 * This function is used to initialize the security
5329 * settings in IBSS mode.
5330 */
5331static int wlan_hdd_cfg80211_set_privacy_ibss(
5332 hdd_adapter_t *pAdapter,
5333 struct cfg80211_ibss_params *params
5334 )
5335{
5336 int status = 0;
5337 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5338 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5339 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5340
5341 ENTER();
5342
5343 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5344
5345 if (params->ie_len && ( NULL != params->ie) )
5346 {
5347 if (WLAN_EID_RSN == params->ie[0])
5348 {
5349 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5350 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5351 }
5352 else
5353 {
5354 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5355 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5356 }
5357 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5358
5359 if (0 > status)
5360 {
5361 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5362 __func__);
5363 return status;
5364 }
5365 }
5366
5367 pWextState->roamProfile.AuthType.authType[0] =
5368 pHddStaCtx->conn_info.authType =
5369 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5370
5371 if (params->privacy)
5372 {
5373 /* Security enabled IBSS, At this time there is no information available
5374 * about the security paramters, so initialise the encryption type to
5375 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5376 * The correct security parameters will be updated later in
5377 * wlan_hdd_cfg80211_add_key */
5378 /* Hal expects encryption type to be set inorder
5379 *enable privacy bit in beacons */
5380
5381 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5382 }
5383
5384 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5385 pWextState->roamProfile.EncryptionType.numEntries = 1;
5386 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5387
5388 return status;
5389}
5390
5391/*
5392 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5393 * This function is used to create/join an IBSS
5394 */
5395static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5396 struct net_device *dev,
5397 struct cfg80211_ibss_params *params
5398 )
5399{
5400 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5401 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5402 tCsrRoamProfile *pRoamProfile;
5403 int status;
5404 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5405
5406 ENTER();
5407
5408 hddLog(VOS_TRACE_LEVEL_INFO,
5409 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5410
5411 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5412 {
5413 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5414 "%s:LOGP in Progress. Ignore!!!", __func__);
5415 return -EAGAIN;
5416 }
5417
5418 if (NULL == pWextState)
5419 {
5420 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5421 __func__);
5422 return -EIO;
5423 }
5424
5425 pRoamProfile = &pWextState->roamProfile;
5426
5427 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5428 {
5429 hddLog (VOS_TRACE_LEVEL_ERROR,
5430 "%s Interface type is not set to IBSS \n", __func__);
5431 return -EINVAL;
5432 }
5433
5434 /* Set Channel */
5435 if (NULL != params->channel)
5436 {
5437 u8 channelNum;
5438 if (IEEE80211_BAND_5GHZ == params->channel->band)
5439 {
5440 hddLog(VOS_TRACE_LEVEL_ERROR,
5441 "%s: IBSS join is called with unsupported band %d",
5442 __func__, params->channel->band);
5443 return -EOPNOTSUPP;
5444 }
5445
5446 /* Get channel number */
5447 channelNum =
5448 ieee80211_frequency_to_channel(params->channel->center_freq);
5449
5450 /*TODO: use macro*/
5451 if (14 >= channelNum)
5452 {
5453 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5454 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5455 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5456 int indx;
5457
5458 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5459 validChan, &numChans))
5460 {
5461 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5462 __func__);
5463 return -EOPNOTSUPP;
5464 }
5465
5466 for (indx = 0; indx < numChans; indx++)
5467 {
5468 if (channelNum == validChan[indx])
5469 {
5470 break;
5471 }
5472 }
5473 if (indx >= numChans)
5474 {
5475 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5476 __func__, channelNum);
5477 return -EINVAL;
5478 }
5479 /* Set the Operational Channel */
5480 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5481 channelNum);
5482 pRoamProfile->ChannelInfo.numOfChannels = 1;
5483 pHddStaCtx->conn_info.operationChannel = channelNum;
5484 pRoamProfile->ChannelInfo.ChannelList =
5485 &pHddStaCtx->conn_info.operationChannel;
5486 }
5487 else
5488 {
5489 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5490 __func__, channelNum);
5491 return -EINVAL;
5492 }
5493 }
5494
5495 /* Initialize security parameters */
5496 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5497 if (status < 0)
5498 {
5499 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5500 __func__);
5501 return status;
5502 }
5503
5504 /* Issue connect start */
5505 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005506 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005507
5508 if (0 > status)
5509 {
5510 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5511 return status;
5512 }
5513
5514 return 0;
5515}
5516
5517/*
5518 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5519 * This function is used to leave an IBSS
5520 */
5521static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5522 struct net_device *dev
5523 )
5524{
5525 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5526 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5527 tCsrRoamProfile *pRoamProfile;
5528
5529 ENTER();
5530
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005531 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5532 {
5533 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5534 "%s:LOGP in Progress. Ignore!!!", __func__);
5535 return -EAGAIN;
5536 }
5537
Jeff Johnson295189b2012-06-20 16:38:30 -07005538 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5539 if (NULL == pWextState)
5540 {
5541 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5542 __func__);
5543 return -EIO;
5544 }
5545
5546 pRoamProfile = &pWextState->roamProfile;
5547
5548 /* Issue disconnect only if interface type is set to IBSS */
5549 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5550 {
5551 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5552 __func__);
5553 return -EINVAL;
5554 }
5555
5556 /* Issue Disconnect request */
5557 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5558 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5559 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5560
5561 return 0;
5562}
5563
5564/*
5565 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5566 * This function is used to set the phy parameters
5567 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5568 */
5569static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5570 u32 changed)
5571{
5572 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5573 tHalHandle hHal = pHddCtx->hHal;
5574
5575 ENTER();
5576
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005577 if ( pHddCtx->isLogpInProgress )
5578 {
5579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5580 "%s:LOGP in Progress. Ignore!!!", __func__);
5581 return -EAGAIN;
5582 }
5583
Jeff Johnson295189b2012-06-20 16:38:30 -07005584 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5585 {
5586 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5587 WNI_CFG_RTS_THRESHOLD_STAMAX :
5588 wiphy->rts_threshold;
5589
5590 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5591 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5592 {
5593 hddLog(VOS_TRACE_LEVEL_ERROR,
5594 "%s: Invalid RTS Threshold value %hu",
5595 __func__, rts_threshold);
5596 return -EINVAL;
5597 }
5598
5599 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5600 rts_threshold, ccmCfgSetCallback,
5601 eANI_BOOLEAN_TRUE))
5602 {
5603 hddLog(VOS_TRACE_LEVEL_ERROR,
5604 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5605 __func__, rts_threshold);
5606 return -EIO;
5607 }
5608
5609 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5610 rts_threshold);
5611 }
5612
5613 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5614 {
5615 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5616 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5617 wiphy->frag_threshold;
5618
5619 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5620 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5621 {
5622 hddLog(VOS_TRACE_LEVEL_ERROR,
5623 "%s: Invalid frag_threshold value %hu", __func__,
5624 frag_threshold);
5625 return -EINVAL;
5626 }
5627
5628 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5629 frag_threshold, ccmCfgSetCallback,
5630 eANI_BOOLEAN_TRUE))
5631 {
5632 hddLog(VOS_TRACE_LEVEL_ERROR,
5633 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5634 __func__, frag_threshold);
5635 return -EIO;
5636 }
5637
5638 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5639 frag_threshold);
5640 }
5641
5642 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5643 || (changed & WIPHY_PARAM_RETRY_LONG))
5644 {
5645 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5646 wiphy->retry_short :
5647 wiphy->retry_long;
5648
5649 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5650 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5651 {
5652 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5653 __func__, retry_value);
5654 return -EINVAL;
5655 }
5656
5657 if (changed & WIPHY_PARAM_RETRY_SHORT)
5658 {
5659 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5660 retry_value, ccmCfgSetCallback,
5661 eANI_BOOLEAN_TRUE))
5662 {
5663 hddLog(VOS_TRACE_LEVEL_ERROR,
5664 "%s: ccmCfgSetInt failed for long retry count %hu",
5665 __func__, retry_value);
5666 return -EIO;
5667 }
5668 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5669 __func__, retry_value);
5670 }
5671 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5672 {
5673 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5674 retry_value, ccmCfgSetCallback,
5675 eANI_BOOLEAN_TRUE))
5676 {
5677 hddLog(VOS_TRACE_LEVEL_ERROR,
5678 "%s: ccmCfgSetInt failed for short retry count %hu",
5679 __func__, retry_value);
5680 return -EIO;
5681 }
5682 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5683 __func__, retry_value);
5684 }
5685 }
5686
5687 return 0;
5688}
5689
5690/*
5691 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5692 * This function is used to set the txpower
5693 */
5694static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5695#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5696 enum tx_power_setting type,
5697#else
5698 enum nl80211_tx_power_setting type,
5699#endif
5700 int dbm)
5701{
5702 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5703 tHalHandle hHal = pHddCtx->hHal;
5704 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5705 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5706
5707 ENTER();
5708
5709 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5710 dbm, ccmCfgSetCallback,
5711 eANI_BOOLEAN_TRUE))
5712 {
5713 hddLog(VOS_TRACE_LEVEL_ERROR,
5714 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5715 return -EIO;
5716 }
5717
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005718 if ( pHddCtx->isLogpInProgress )
5719 {
5720 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5721 "%s:LOGP in Progress. Ignore!!!", __func__);
5722 return -EAGAIN;
5723 }
5724
Jeff Johnson295189b2012-06-20 16:38:30 -07005725 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5726 dbm);
5727
5728 switch(type)
5729 {
5730 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5731 /* Fall through */
5732 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5733 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5734 {
5735 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5736 __func__);
5737 return -EIO;
5738 }
5739 break;
5740 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5741 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5742 __func__);
5743 return -EOPNOTSUPP;
5744 break;
5745 default:
5746 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5747 __func__, type);
5748 return -EIO;
5749 }
5750
5751 return 0;
5752}
5753
5754/*
5755 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5756 * This function is used to read the txpower
5757 */
5758static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5759{
5760
5761 hdd_adapter_t *pAdapter;
5762 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5763
Jeff Johnsone7245742012-09-05 17:12:55 -07005764 ENTER();
5765
Jeff Johnson295189b2012-06-20 16:38:30 -07005766 if (NULL == pHddCtx)
5767 {
5768 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5769 *dbm = 0;
5770 return -ENOENT;
5771 }
5772
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005773 if ( pHddCtx->isLogpInProgress )
5774 {
5775 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5776 "%s:LOGP in Progress. Ignore!!!", __func__);
5777 return -EAGAIN;
5778 }
5779
Jeff Johnson295189b2012-06-20 16:38:30 -07005780 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5781 if (NULL == pAdapter)
5782 {
5783 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5784 return -ENOENT;
5785 }
5786
5787 wlan_hdd_get_classAstats(pAdapter);
5788 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5789
Jeff Johnsone7245742012-09-05 17:12:55 -07005790 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 return 0;
5792}
5793
5794static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5795 u8* mac, struct station_info *sinfo)
5796{
5797 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5798 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5799 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5800 tANI_U8 rate_flags;
5801
5802 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5803 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5804 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5805
5806 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5807 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5808 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5809 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5810 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5811 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5812 tANI_U16 maxRate = 0;
5813 tANI_U16 myRate;
5814 tANI_U16 currentRate = 0;
5815 tANI_U8 maxSpeedMCS = 0;
5816 tANI_U8 maxMCSIdx = 0;
5817 tANI_U8 rateFlag = 1;
5818 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005819 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005820
Jeff Johnsone7245742012-09-05 17:12:55 -07005821 ENTER();
5822
Jeff Johnson295189b2012-06-20 16:38:30 -07005823 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5824 (0 == ssidlen))
5825 {
5826 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5827 " Invalid ssidlen, %d", __func__, ssidlen);
5828 /*To keep GUI happy*/
5829 return 0;
5830 }
5831
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005832 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5833 {
5834 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5835 "%s:LOGP in Progress. Ignore!!!", __func__);
5836 return -EAGAIN;
5837 }
5838
Jeff Johnson295189b2012-06-20 16:38:30 -07005839 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5840 sinfo->filled |= STATION_INFO_SIGNAL;
5841
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005842 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005843 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5844
5845 //convert to the UI units of 100kbps
5846 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5847
5848#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005849 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 -07005850 sinfo->signal,
5851 pCfg->reportMaxLinkSpeed,
5852 myRate,
5853 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005854 (int) pCfg->linkSpeedRssiMid,
5855 (int) pCfg->linkSpeedRssiLow,
5856 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005857#endif //LINKSPEED_DEBUG_ENABLED
5858
5859 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5860 {
5861 // we do not want to necessarily report the current speed
5862 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5863 {
5864 // report the max possible speed
5865 rssidx = 0;
5866 }
5867 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5868 {
5869 // report the max possible speed with RSSI scaling
5870 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5871 {
5872 // report the max possible speed
5873 rssidx = 0;
5874 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005875 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 {
5877 // report middle speed
5878 rssidx = 1;
5879 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005880 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5881 {
5882 // report middle speed
5883 rssidx = 2;
5884 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 else
5886 {
5887 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005888 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005889 }
5890 }
5891 else
5892 {
5893 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5894 hddLog(VOS_TRACE_LEVEL_ERROR,
5895 "%s: Invalid value for reportMaxLinkSpeed: %u",
5896 __func__, pCfg->reportMaxLinkSpeed);
5897 rssidx = 0;
5898 }
5899
5900 maxRate = 0;
5901
5902 /* Get Basic Rate Set */
5903 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5904 for (i = 0; i < ORLeng; i++)
5905 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005906 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005907 {
5908 /* Validate Rate Set */
5909 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5910 {
5911 currentRate = supported_data_rate[j].supported_rate[rssidx];
5912 break;
5913 }
5914 }
5915 /* Update MAX rate */
5916 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5917 }
5918
5919 /* Get Extended Rate Set */
5920 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5921 for (i = 0; i < ERLeng; i++)
5922 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005923 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005924 {
5925 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5926 {
5927 currentRate = supported_data_rate[j].supported_rate[rssidx];
5928 break;
5929 }
5930 }
5931 /* Update MAX rate */
5932 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5933 }
5934
5935 /* Get MCS Rate Set -- but only if we are connected at MCS
5936 rates or if we are always reporting max speed or if we have
5937 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005938 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005939 {
5940 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5941 rateFlag = 0;
5942 if (rate_flags & eHAL_TX_RATE_HT40)
5943 {
5944 rateFlag |= 1;
5945 }
5946 if (rate_flags & eHAL_TX_RATE_SGI)
5947 {
5948 rateFlag |= 2;
5949 }
5950
5951 for (i = 0; i < MCSLeng; i++)
5952 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005953 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5954 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005955 {
5956 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5957 {
5958 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5959 break;
5960 }
5961 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005962 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005963 {
5964 maxRate = currentRate;
5965 maxSpeedMCS = 1;
5966 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5967 }
5968 }
5969 }
5970
5971 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005972 if (((maxRate < myRate) && (0 == rssidx)) ||
5973 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005974 {
5975 maxRate = myRate;
5976 if (rate_flags & eHAL_TX_RATE_LEGACY)
5977 {
5978 maxSpeedMCS = 0;
5979 }
5980 else
5981 {
5982 maxSpeedMCS = 1;
5983 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5984 }
5985 }
5986
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005987 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005988 {
5989 sinfo->txrate.legacy = maxRate;
5990#ifdef LINKSPEED_DEBUG_ENABLED
5991 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5992#endif //LINKSPEED_DEBUG_ENABLED
5993 }
5994 else
5995 {
5996 sinfo->txrate.mcs = maxMCSIdx;
5997 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5998 if (rate_flags & eHAL_TX_RATE_SGI)
5999 {
6000 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6001 }
6002 if (rate_flags & eHAL_TX_RATE_HT40)
6003 {
6004 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6005 }
6006#ifdef LINKSPEED_DEBUG_ENABLED
6007 pr_info("Reporting MCS rate %d flags %x\n",
6008 sinfo->txrate.mcs,
6009 sinfo->txrate.flags );
6010#endif //LINKSPEED_DEBUG_ENABLED
6011 }
6012 }
6013 else
6014 {
6015 // report current rate instead of max rate
6016
6017 if (rate_flags & eHAL_TX_RATE_LEGACY)
6018 {
6019 //provide to the UI in units of 100kbps
6020 sinfo->txrate.legacy = myRate;
6021#ifdef LINKSPEED_DEBUG_ENABLED
6022 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6023#endif //LINKSPEED_DEBUG_ENABLED
6024 }
6025 else
6026 {
6027 //must be MCS
6028 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6029 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6030 if (rate_flags & eHAL_TX_RATE_SGI)
6031 {
6032 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6033 }
6034 if (rate_flags & eHAL_TX_RATE_HT40)
6035 {
6036 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6037 }
6038#ifdef LINKSPEED_DEBUG_ENABLED
6039 pr_info("Reporting actual MCS rate %d flags %x\n",
6040 sinfo->txrate.mcs,
6041 sinfo->txrate.flags );
6042#endif //LINKSPEED_DEBUG_ENABLED
6043 }
6044 }
6045 sinfo->filled |= STATION_INFO_TX_BITRATE;
6046
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006047 sinfo->tx_packets =
6048 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6049 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6050 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6051 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6052
6053 sinfo->tx_retries =
6054 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6055 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6056 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6057 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6058
6059 sinfo->tx_failed =
6060 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6061 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6062 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6063 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6064
6065 sinfo->filled |=
6066 STATION_INFO_TX_PACKETS |
6067 STATION_INFO_TX_RETRIES |
6068 STATION_INFO_TX_FAILED;
6069
6070 EXIT();
6071 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006072}
6073
6074static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6075 struct net_device *dev, bool mode, v_SINT_t timeout)
6076{
6077 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6078 VOS_STATUS vos_status;
6079
Jeff Johnsone7245742012-09-05 17:12:55 -07006080 ENTER();
6081
Jeff Johnson295189b2012-06-20 16:38:30 -07006082 if (NULL == pAdapter)
6083 {
6084 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6085 return -ENODEV;
6086 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006087 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6088 {
6089 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6090 "%s:LOGP in Progress. Ignore!!!", __func__);
6091 return -EAGAIN;
6092 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006093
6094 /**The get power cmd from the supplicant gets updated by the nl only
6095 *on successful execution of the function call
6096 *we are oppositely mapped w.r.t mode in the driver
6097 **/
6098 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6099
Jeff Johnsone7245742012-09-05 17:12:55 -07006100 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006101 if (VOS_STATUS_E_FAILURE == vos_status)
6102 {
6103 return -EINVAL;
6104 }
6105 return 0;
6106}
6107
6108
6109#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6110static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6111 struct net_device *netdev,
6112 u8 key_index)
6113{
Jeff Johnsone7245742012-09-05 17:12:55 -07006114 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 return 0;
6116}
6117#endif //LINUX_VERSION_CODE
6118
6119#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6120static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6121 struct net_device *dev,
6122 struct ieee80211_txq_params *params)
6123{
Jeff Johnsone7245742012-09-05 17:12:55 -07006124 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006125 return 0;
6126}
6127#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6128static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6129 struct ieee80211_txq_params *params)
6130{
Jeff Johnsone7245742012-09-05 17:12:55 -07006131 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006132 return 0;
6133}
6134#endif //LINUX_VERSION_CODE
6135
6136static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6137 struct net_device *dev, u8 *mac)
6138{
6139 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006140 VOS_STATUS vos_status;
6141 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006142
Jeff Johnsone7245742012-09-05 17:12:55 -07006143 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6145 {
6146 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6147 return -EINVAL;
6148 }
6149
6150 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6151 {
6152 hddLog( LOGE,
6153 "%s: Wlan Load/Unload is in progress", __func__);
6154 return -EBUSY;
6155 }
6156
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006157 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6158 {
6159 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6160 "%s:LOGP in Progress. Ignore!!!", __func__);
6161 return -EAGAIN;
6162 }
6163
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6165#ifdef WLAN_FEATURE_P2P
6166 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6167#endif
6168 )
6169 {
6170 if( NULL == mac )
6171 {
6172 v_U16_t i;
6173 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6174 {
6175 if(pAdapter->aStaInfo[i].isUsed)
6176 {
6177 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6178 hddLog(VOS_TRACE_LEVEL_INFO,
6179 "%s: Delete STA with MAC::"
6180 "%02x:%02x:%02x:%02x:%02x:%02x",
6181 __func__,
6182 macAddr[0], macAddr[1], macAddr[2],
6183 macAddr[3], macAddr[4], macAddr[5]);
6184 hdd_softap_sta_deauth(pAdapter, macAddr);
6185 }
6186 }
6187 }
6188 else
6189 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006190
6191 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6192 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6193 {
6194 hddLog(VOS_TRACE_LEVEL_INFO,
6195 "%s: Skip this DEL STA as this is not used::"
6196 "%02x:%02x:%02x:%02x:%02x:%02x",
6197 __func__,
6198 mac[0], mac[1], mac[2],
6199 mac[3], mac[4], mac[5]);
6200 return -ENOENT;
6201 }
6202
6203 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6204 {
6205 hddLog(VOS_TRACE_LEVEL_INFO,
6206 "%s: Skip this DEL STA as deauth is in progress::"
6207 "%02x:%02x:%02x:%02x:%02x:%02x",
6208 __func__,
6209 mac[0], mac[1], mac[2],
6210 mac[3], mac[4], mac[5]);
6211 return -ENOENT;
6212 }
6213
6214 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6215
Jeff Johnson295189b2012-06-20 16:38:30 -07006216 hddLog(VOS_TRACE_LEVEL_INFO,
6217 "%s: Delete STA with MAC::"
6218 "%02x:%02x:%02x:%02x:%02x:%02x",
6219 __func__,
6220 mac[0], mac[1], mac[2],
6221 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006222
6223 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6224 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6225 {
6226 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6227 hddLog(VOS_TRACE_LEVEL_INFO,
6228 "%s: STA removal failed for ::"
6229 "%02x:%02x:%02x:%02x:%02x:%02x",
6230 __func__,
6231 mac[0], mac[1], mac[2],
6232 mac[3], mac[4], mac[5]);
6233 return -ENOENT;
6234 }
6235
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 }
6237 }
6238
6239 EXIT();
6240
6241 return 0;
6242}
6243
6244static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6245 struct net_device *dev, u8 *mac, struct station_parameters *params)
6246{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006247#ifdef FEATURE_WLAN_TDLS
6248 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6249 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6250 u32 mask, set;
6251 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006252 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006253
6254 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6255 {
6256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6257 "Invalid arguments");
6258 return -EINVAL;
6259 }
6260
6261 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6262 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6263 {
6264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6265 "TDLS Disabled in INI OR not enabled in FW.\
6266 Cannot process TDLS commands \n");
6267 return -ENOTSUPP;
6268 }
6269
6270 mask = params->sta_flags_mask;
6271
6272 set = params->sta_flags_set;
6273
6274
6275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6276 "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
6277
6278 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6279 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6280 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6281 "Add TDLS peer");
6282
6283
6284 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6285 pAdapter->sessionId, mac);
6286
6287 if (VOS_STATUS_SUCCESS != status) {
6288 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6289 "%s: sme_AddTdlsPeerSta failed!", __func__);
6290 }
6291 }
6292 }
6293#endif
6294
Jeff Johnson295189b2012-06-20 16:38:30 -07006295 return 0;
6296}
6297
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006298
6299#ifdef FEATURE_WLAN_LFR
6300static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006301 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006302{
6303#define MAX_PMKSAIDS_IN_CACHE 8
6304 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006305 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006306 tANI_U32 j=0;
6307 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6308 tHalHandle halHandle;
6309 eHalStatus result;
6310 tANI_U8 BSSIDMatched = 0;
6311
Jeff Johnsone7245742012-09-05 17:12:55 -07006312 ENTER();
6313
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006314 // Validate pAdapter
6315 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6316 {
6317 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6318 return -EINVAL;
6319 }
6320
6321 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6322 {
6323 hddLog( LOGE,
6324 "%s: Wlan Load/Unload is in progress", __func__);
6325 return -EBUSY;
6326 }
6327
6328 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6329 {
6330 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6331 "%s:LOGP in Progress. Ignore!!!", __func__);
6332 return -EAGAIN;
6333 }
6334
6335 // Retrieve halHandle
6336 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6337
6338 for (j = 0; j < i; j++)
6339 {
6340 if(vos_mem_compare(PMKIDCache[j].BSSID,
6341 pmksa->bssid, WNI_CFG_BSSID_LEN))
6342 {
6343 /* BSSID matched previous entry. Overwrite it. */
6344 BSSIDMatched = 1;
6345 vos_mem_copy(PMKIDCache[j].BSSID,
6346 pmksa->bssid, WNI_CFG_BSSID_LEN);
6347 vos_mem_copy(PMKIDCache[j].PMKID,
6348 pmksa->pmkid,
6349 CSR_RSN_PMKID_SIZE);
6350 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006351 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006352 dump_bssid(pmksa->bssid);
6353 dump_pmkid(halHandle, pmksa->pmkid);
6354 break;
6355 }
6356 }
6357
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006358 /* Check we compared all entries,if then take the first slot now */
6359 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6360
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006361 if (!BSSIDMatched)
6362 {
6363 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6364 vos_mem_copy(PMKIDCache[i].BSSID,
6365 pmksa->bssid, ETHER_ADDR_LEN);
6366 vos_mem_copy(PMKIDCache[i].PMKID,
6367 pmksa->pmkid,
6368 CSR_RSN_PMKID_SIZE);
6369 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006370 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006371 dump_bssid(pmksa->bssid);
6372 dump_pmkid(halHandle, pmksa->pmkid);
6373 // Increment the HDD Local Cache index
6374 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6375 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6376 }
6377
6378
6379 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6380 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006381 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006382 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006383 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006384 // Finally set the PMKSA ID Cache in CSR
6385 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6386 PMKIDCache,
6387 i );
6388 return 0;
6389}
6390
6391
6392static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006393 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006394{
Jeff Johnsone7245742012-09-05 17:12:55 -07006395 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006396 // TODO: Implement this later.
6397 return 0;
6398}
6399
6400static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6401{
Jeff Johnsone7245742012-09-05 17:12:55 -07006402 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006403 // TODO: Implement this later.
6404 return 0;
6405}
6406#endif
6407
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006408#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6409static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6410 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6411{
6412 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6413 hdd_station_ctx_t *pHddStaCtx;
6414
6415 if (NULL == pAdapter)
6416 {
6417 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6418 return -ENODEV;
6419 }
6420
6421 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6422
6423 // Added for debug on reception of Re-assoc Req.
6424 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6425 {
6426 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6427 ftie->ie_len);
6428 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6429 }
6430
6431#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6432 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6433 ftie->ie_len);
6434#endif
6435
6436 // Pass the received FT IEs to SME
6437 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6438 ftie->ie_len);
6439 return 0;
6440}
6441#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006442
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006443#ifdef FEATURE_WLAN_TDLS
6444static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6445 u8 *peer, u8 action_code, u8 dialog_token,
6446 u16 status_code, const u8 *buf, size_t len)
6447{
6448
6449 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6450 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6451 u8 *buf_1;
6452 size_t len_1 = len;
6453 u8 peerMac[6];
6454 VOS_STATUS status;
6455
6456 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6457 {
6458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6459 "Invalid arguments");
6460 return -EINVAL;
6461 }
6462
6463 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6464 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6465 {
6466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6467 "TDLS Disabled in INI OR not enabled in FW.\
6468 Cannot process TDLS commands \n");
6469 return -ENOTSUPP;
6470 }
6471 vos_mem_copy( peerMac, peer, 6);
6472
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006473#ifdef WLAN_FEATURE_TDLS_DEBUG
6474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6475 "%s: %02x:%02x:%02x:%02x:%02x:%02x) action %d, dialog_token %d status %d, len = %d",
6476 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6477 action_code, dialog_token, status_code, len);
6478#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006479
6480 buf_1 = vos_mem_malloc(len);
6481 if(buf_1 == NULL) {
6482 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6483 "%s: malloc failed!", __func__);
6484 return -ENOMEM;
6485 }
6486 vos_mem_copy(buf_1, buf, len);
6487
6488 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6489 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6490
6491 if (VOS_STATUS_SUCCESS != status) {
6492 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6493 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6494 }
6495
6496 vos_mem_free(buf_1);
6497
6498 return 0;
6499}
6500
6501static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6502 u8 *peer, enum nl80211_tdls_operation oper)
6503{
6504 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6505 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006506#ifdef WLAN_FEATURE_TDLS_DEBUG
6507 const char *tdls_oper_str[]= {
6508 "NL80211_TDLS_DISCOVERY_REQ",
6509 "NL80211_TDLS_SETUP",
6510 "NL80211_TDLS_TEARDOWN",
6511 "NL80211_TDLS_ENABLE_LINK",
6512 "NL80211_TDLS_DISABLE_LINK",
6513 "NL80211_TDLS_UNKONW_OPER"};
6514#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006515
6516 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6517 {
6518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6519 "Invalid arguments");
6520 return -EINVAL;
6521 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006522
6523#ifdef WLAN_FEATURE_TDLS_DEBUG
6524 if((int)oper > 4)
6525 oper = 5;
6526
6527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6528 "%s: %02x:%02x:%02x:%02x:%02x:%02x: %d (%s) ", "tdls_oper",
6529 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5], (int)oper,
6530 tdls_oper_str[(int)oper]);
6531#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006532
6533 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006534 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006535 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006537 "TDLS Disabled in INI OR not enabled in FW.\
6538 Cannot process TDLS commands \n");
6539 return -ENOTSUPP;
6540 }
6541
6542 switch (oper) {
6543 case NL80211_TDLS_ENABLE_LINK:
6544 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006545 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006546 v_U8_t my_peer[6];
6547 v_U8_t ucSTAId;
6548 VOS_STATUS status;
6549
6550 if (peer) {
6551 vos_mem_copy(my_peer, peer, 6);
6552 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6553
6554 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6555 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6556 __func__, peer[0], peer[1],
6557 peer[2], peer[3],
6558 peer[4], peer[5] );
6559
6560 if (-1 == ucSTAId ) {
6561 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
Hoonki Leef63df0d2013-01-16 19:29:14 -08006562 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006563 }
6564
6565 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6566 WLANTL_STA_AUTHENTICATED );
6567
Hoonki Leef63df0d2013-01-16 19:29:14 -08006568 //This can fail only if the staId is not registered yet with TL
6569 //return -EINVAL in such case.
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006570 if (0 != status) {
6571 hddLog(VOS_TRACE_LEVEL_ERROR,
6572 "%s: WLANTL_ChangeSTAState failed, returned %d",
6573 __func__, status);
Hoonki Leef63df0d2013-01-16 19:29:14 -08006574 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006575 }
Hoonki Leef63df0d2013-01-16 19:29:14 -08006576
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006577 } else {
6578 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6579 }
6580 }
6581 break;
6582 case NL80211_TDLS_DISABLE_LINK:
6583 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6584 pAdapter->sessionId, peer );
6585 return 0;
6586 case NL80211_TDLS_TEARDOWN:
6587 case NL80211_TDLS_SETUP:
6588 case NL80211_TDLS_DISCOVERY_REQ:
6589 /* We don't support in-driver setup/teardown/discovery */
6590 return -ENOTSUPP;
6591 default:
6592 return -ENOTSUPP;
6593 }
6594 return 0;
6595}
6596#endif
6597
Jeff Johnson295189b2012-06-20 16:38:30 -07006598/* cfg80211_ops */
6599static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6600{
6601 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6602 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6603 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6604 .change_station = wlan_hdd_change_station,
6605#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6606 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6607 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6608 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006609#else
6610 .start_ap = wlan_hdd_cfg80211_start_ap,
6611 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6612 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006613#endif
6614 .change_bss = wlan_hdd_cfg80211_change_bss,
6615 .add_key = wlan_hdd_cfg80211_add_key,
6616 .get_key = wlan_hdd_cfg80211_get_key,
6617 .del_key = wlan_hdd_cfg80211_del_key,
6618 .set_default_key = wlan_hdd_cfg80211_set_default_key,
6619 .set_channel = wlan_hdd_cfg80211_set_channel,
6620 .scan = wlan_hdd_cfg80211_scan,
6621 .connect = wlan_hdd_cfg80211_connect,
6622 .disconnect = wlan_hdd_cfg80211_disconnect,
6623 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6624 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6625 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6626 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6627 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6628#ifdef WLAN_FEATURE_P2P
6629 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6630 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6631 .mgmt_tx = wlan_hdd_action,
6632#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6633 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6634 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6635 .set_txq_params = wlan_hdd_set_txq_params,
6636#endif
6637#endif
6638 .get_station = wlan_hdd_cfg80211_get_station,
6639 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6640 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006641 .add_station = wlan_hdd_cfg80211_add_station,
6642#ifdef FEATURE_WLAN_LFR
6643 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6644 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6645 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6646#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006647#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6648 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6649#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006650#ifdef FEATURE_WLAN_TDLS
6651 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6652 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6653#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006654};
6655
6656#endif // CONFIG_CFG80211