blob: bc572f1dbd441c1cf1a8b174be06f87a82d66fa6 [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 },
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800351#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700352};
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)
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800548#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700549 | 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
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003325#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07003326/**
3327 * FUNCTION: wlan_hdd_cfg80211_set_channel
3328 * This function is used to set the channel number
3329 */
3330int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3331 struct ieee80211_channel *chan,
3332 enum nl80211_channel_type channel_type
3333 )
3334{
3335 v_U32_t num_ch = 0;
3336 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003337 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003338 int freq = chan->center_freq; /* freq is in MHZ */
3339
3340 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003341
3342 if( NULL == dev )
3343 {
3344 hddLog(VOS_TRACE_LEVEL_ERROR,
3345 "%s: Called with dev = NULL.\n", __func__);
3346 return -ENODEV;
3347 }
3348 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003349
3350 hddLog(VOS_TRACE_LEVEL_INFO,
3351 "%s: device_mode = %d freq = %d \n",__func__,
3352 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003353 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3354 {
3355 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3356 return -EAGAIN;
3357 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003358
3359 /*
3360 * Do freq to chan conversion
3361 * TODO: for 11a
3362 */
3363
3364 channel = ieee80211_frequency_to_channel(freq);
3365
3366 /* Check freq range */
3367 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3368 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3369 {
3370 hddLog(VOS_TRACE_LEVEL_ERROR,
3371 "%s: Channel [%d] is outside valid range from %d to %d\n",
3372 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3373 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3374 return -EINVAL;
3375 }
3376
3377 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3378
3379 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3380#ifdef WLAN_FEATURE_P2P
3381 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3382#endif
3383 )
3384 {
3385 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3386 {
3387 hddLog(VOS_TRACE_LEVEL_ERROR,
3388 "%s: Invalid Channel [%d] \n", __func__, channel);
3389 return -EINVAL;
3390 }
3391 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3392 "%s: set channel to [%d] for device mode =%d",
3393 __func__, channel,pAdapter->device_mode);
3394 }
3395 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3396#ifdef WLAN_FEATURE_P2P
3397 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3398#endif
3399 )
3400 {
3401 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3402 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3403 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3404
3405 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3406 {
3407 /* Link is up then return cant set channel*/
3408 hddLog( VOS_TRACE_LEVEL_ERROR,
3409 "%s: IBSS Associated, can't set the channel\n", __func__);
3410 return -EINVAL;
3411 }
3412
3413 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3414 pHddStaCtx->conn_info.operationChannel = channel;
3415 pRoamProfile->ChannelInfo.ChannelList =
3416 &pHddStaCtx->conn_info.operationChannel;
3417 }
3418 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3419#ifdef WLAN_FEATURE_P2P
3420 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3421#endif
3422 )
3423 {
3424 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3425
3426 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3427 {
3428 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3429
3430 /* If auto channel selection is configured as enable/ 1 then ignore
3431 channel set by supplicant
3432 */
3433 if ( cfg_param->apAutoChannelSelection )
3434 {
3435 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3436
3437 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3438 "%s: set channel to auto channel (0) for device mode =%d",
3439 __func__, pAdapter->device_mode);
3440 }
3441 }
3442 }
3443 else
3444 {
3445 hddLog(VOS_TRACE_LEVEL_FATAL,
3446 "%s: Invalid device mode failed to set valid channel", __func__);
3447 return -EINVAL;
3448 }
3449 EXIT();
3450 return 0;
3451}
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003452#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003453
3454
3455
3456/*
3457 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3458 * This function is used to inform the BSS details to nl80211 interface.
3459 */
3460static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3461 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3462{
3463 struct net_device *dev = pAdapter->dev;
3464 struct wireless_dev *wdev = dev->ieee80211_ptr;
3465 struct wiphy *wiphy = wdev->wiphy;
3466 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3467 int chan_no;
3468 int ie_length;
3469 const char *ie;
3470 unsigned int freq;
3471 struct ieee80211_channel *chan;
3472 int rssi = 0;
3473 struct cfg80211_bss *bss = NULL;
3474
3475 ENTER();
3476
3477 if( NULL == pBssDesc )
3478 {
3479 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3480 return bss;
3481 }
3482
3483 chan_no = pBssDesc->channelId;
3484 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3485 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3486
3487 if( NULL == ie )
3488 {
3489 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3490 return bss;
3491 }
3492
3493#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3494 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3495 {
3496 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3497 }
3498 else
3499 {
3500 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3501 }
3502#else
3503 freq = ieee80211_channel_to_frequency(chan_no);
3504#endif
3505
3506 chan = __ieee80211_get_channel(wiphy, freq);
3507
3508 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3509 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3510 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3511 if (bss == NULL)
3512 {
3513 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3514
3515 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3516 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3517 pBssDesc->capabilityInfo,
3518 pBssDesc->beaconInterval, ie, ie_length,
3519 rssi, GFP_KERNEL ));
3520}
3521 else
3522 {
3523 return bss;
3524 }
3525}
3526
3527
3528
3529/*
3530 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3531 * This function is used to inform the BSS details to nl80211 interface.
3532 */
3533struct cfg80211_bss*
3534wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3535 tSirBssDescription *bss_desc
3536 )
3537{
3538 /*
3539 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3540 already exists in bss data base of cfg80211 for that particular BSS ID.
3541 Using cfg80211_inform_bss_frame to update the bss entry instead of
3542 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3543 now there is no possibility to get the mgmt(probe response) frame from PE,
3544 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3545 cfg80211_inform_bss_frame.
3546 */
3547 struct net_device *dev = pAdapter->dev;
3548 struct wireless_dev *wdev = dev->ieee80211_ptr;
3549 struct wiphy *wiphy = wdev->wiphy;
3550 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003551#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3552 qcom_ie_age *qie_age = NULL;
3553 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3554#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003555 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003556#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003557 const char *ie =
3558 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3559 unsigned int freq;
3560 struct ieee80211_channel *chan;
3561 struct ieee80211_mgmt *mgmt =
3562 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3563 struct cfg80211_bss *bss_status = NULL;
3564 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3565 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003566#ifdef WLAN_OPEN_SOURCE
3567 struct timespec ts;
3568#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003569
3570 ENTER();
3571
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003572 if (!mgmt)
3573 return NULL;
3574
Jeff Johnson295189b2012-06-20 16:38:30 -07003575 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003576
3577#ifdef WLAN_OPEN_SOURCE
3578 /* Android does not want the timestamp from the frame.
3579 Instead it wants a monotonic increasing value */
3580 get_monotonic_boottime(&ts);
3581 mgmt->u.probe_resp.timestamp =
3582 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3583#else
3584 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003585 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3586 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003587
3588#endif
3589
Jeff Johnson295189b2012-06-20 16:38:30 -07003590 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3591 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003592
3593#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3594 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3595 /* Assuming this is the last IE, copy at the end */
3596 ie_length -=sizeof(qcom_ie_age);
3597 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3598 qie_age->element_id = QCOM_VENDOR_IE_ID;
3599 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3600 qie_age->oui_1 = QCOM_OUI1;
3601 qie_age->oui_2 = QCOM_OUI2;
3602 qie_age->oui_3 = QCOM_OUI3;
3603 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3604 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3605#endif
3606
Jeff Johnson295189b2012-06-20 16:38:30 -07003607 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3608
3609 mgmt->frame_control |=
3610 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3611
3612#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3613 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3614 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3615 {
3616 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3617 }
3618 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3619 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3620
3621 {
3622 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3623 }
3624 else
3625 {
3626 kfree(mgmt);
3627 return NULL;
3628 }
3629#else
3630 freq = ieee80211_channel_to_frequency(chan_no);
3631#endif
3632 chan = __ieee80211_get_channel(wiphy, freq);
3633
3634 /*To keep the rssi icon of the connected AP in the scan window
3635 *and the rssi icon of the wireless networks in sync
3636 * */
3637 if (( eConnectionState_Associated ==
3638 pAdapter->sessionCtx.station.conn_info.connState ) &&
3639 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3640 pAdapter->sessionCtx.station.conn_info.bssId,
3641 WNI_CFG_BSSID_LEN)))
3642 {
3643 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3644 rssi = (pAdapter->rssi * 100);
3645 }
3646 else
3647 {
3648 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3649 }
3650
3651 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3652 frame_len, rssi, GFP_KERNEL);
3653 kfree(mgmt);
3654 return bss_status;
3655}
3656
3657/*
3658 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3659 * This function is used to update the BSS data base of CFG8011
3660 */
3661struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3662 tCsrRoamInfo *pRoamInfo
3663 )
3664{
3665 tCsrRoamConnectedProfile roamProfile;
3666 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3667 struct cfg80211_bss *bss = NULL;
3668
3669 ENTER();
3670
3671 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3672 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3673
3674 if (NULL != roamProfile.pBssDesc)
3675 {
3676 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3677 &roamProfile);
3678
3679 if (NULL == bss)
3680 {
3681 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3682 __func__);
3683 }
3684
3685 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3686 }
3687 else
3688 {
3689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3690 __func__);
3691 }
3692 return bss;
3693}
3694
3695/*
3696 * FUNCTION: wlan_hdd_cfg80211_update_bss
3697 */
3698static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3699 hdd_adapter_t *pAdapter
3700 )
3701{
3702 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3703 tCsrScanResultInfo *pScanResult;
3704 eHalStatus status = 0;
3705 tScanResultHandle pResult;
3706 struct cfg80211_bss *bss_status = NULL;
3707
3708 ENTER();
3709
3710 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3711 {
3712 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3713 return -EAGAIN;
3714 }
3715
3716 /*
3717 * start getting scan results and populate cgf80211 BSS database
3718 */
3719 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3720
3721 /* no scan results */
3722 if (NULL == pResult)
3723 {
3724 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3725 return status;
3726 }
3727
3728 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3729
3730 while (pScanResult)
3731 {
3732 /*
3733 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3734 * entry already exists in bss data base of cfg80211 for that
3735 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3736 * bss entry instead of cfg80211_inform_bss, But this call expects
3737 * mgmt packet as input. As of now there is no possibility to get
3738 * the mgmt(probe response) frame from PE, converting bss_desc to
3739 * ieee80211_mgmt(probe response) and passing to c
3740 * fg80211_inform_bss_frame.
3741 * */
3742
3743 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3744 &pScanResult->BssDescriptor);
3745
3746
3747 if (NULL == bss_status)
3748 {
3749 hddLog(VOS_TRACE_LEVEL_INFO,
3750 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3751 }
3752 else
3753 {
3754 cfg80211_put_bss(bss_status);
3755 }
3756
3757 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3758 }
3759
3760 sme_ScanResultPurge(hHal, pResult);
3761
3762 return 0;
3763}
3764
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003765void
3766hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3767{
3768 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003769 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3770 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3771 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003772} /****** end hddPrintMacAddr() ******/
3773
3774void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003775hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003776{
3777 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003778 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3779 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3780 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3781 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003782} /****** end hddPrintPmkId() ******/
3783
3784//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3785//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3786
3787//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3788//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3789
3790#define dump_bssid(bssid) \
3791 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003792 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3793 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3794 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003795 }
3796
3797#define dump_pmkid(pMac, pmkid) \
3798 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003799 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3800 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3801 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003802 }
3803
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003804#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003805/*
3806 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3807 * This function is used to notify the supplicant of a new PMKSA candidate.
3808 */
3809int wlan_hdd_cfg80211_pmksa_candidate_notify(
3810 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3811 int index, bool preauth )
3812{
Jeff Johnsone7245742012-09-05 17:12:55 -07003813#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003814 struct net_device *dev = pAdapter->dev;
3815
3816 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003817 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003818
3819 if( NULL == pRoamInfo )
3820 {
3821 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3822 return -EINVAL;
3823 }
3824
3825 dump_bssid(pRoamInfo->bssid);
3826 cfg80211_pmksa_candidate_notify(dev, index,
3827 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003828#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003829 return 0;
3830}
3831#endif //FEATURE_WLAN_LFR
3832
Jeff Johnson295189b2012-06-20 16:38:30 -07003833/*
3834 * FUNCTION: hdd_cfg80211_scan_done_callback
3835 * scanning callback function, called after finishing scan
3836 *
3837 */
3838static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3839 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3840{
3841 struct net_device *dev = (struct net_device *) pContext;
3842 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3843 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003844 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3845 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003846 struct cfg80211_scan_request *req = NULL;
3847 int ret = 0;
3848
3849 ENTER();
3850
3851 hddLog(VOS_TRACE_LEVEL_INFO,
3852 "%s called with halHandle = %p, pContext = %p,"
3853 "scanID = %d, returned status = %d\n",
3854 __func__, halHandle, pContext, (int) scanId, (int) status);
3855
3856 //Block on scan req completion variable. Can't wait forever though.
3857 ret = wait_for_completion_interruptible_timeout(
3858 &pScanInfo->scan_req_completion_event,
3859 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3860 if (!ret)
3861 {
3862 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003863 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 }
3865
3866 if(pScanInfo->mScanPending != VOS_TRUE)
3867 {
3868 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003869 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003870 }
3871
3872 /* Check the scanId */
3873 if (pScanInfo->scanId != scanId)
3874 {
3875 hddLog(VOS_TRACE_LEVEL_INFO,
3876 "%s called with mismatched scanId pScanInfo->scanId = %d "
3877 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3878 (int) scanId);
3879 }
3880
Jeff Johnson295189b2012-06-20 16:38:30 -07003881 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3882 pAdapter);
3883
3884 if (0 > ret)
3885 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3886
3887
3888 /* If any client wait scan result through WEXT
3889 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003890 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003891 {
3892 /* The other scan request waiting for current scan finish
3893 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003894 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003896 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003897 }
3898 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003899 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003900 {
3901 struct net_device *dev = pAdapter->dev;
3902 union iwreq_data wrqu;
3903 int we_event;
3904 char *msg;
3905
3906 memset(&wrqu, '\0', sizeof(wrqu));
3907 we_event = SIOCGIWSCAN;
3908 msg = NULL;
3909 wireless_send_event(dev, we_event, &wrqu, msg);
3910 }
3911 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003912 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003913
3914 /* Get the Scan Req */
3915 req = pAdapter->request;
3916
3917 if (!req)
3918 {
3919 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003920 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003921 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 }
3923
3924 /*
3925 * setting up 0, just in case.
3926 */
3927 req->n_ssids = 0;
3928 req->n_channels = 0;
3929 req->ie = 0;
3930
Jeff Johnson295189b2012-06-20 16:38:30 -07003931 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003932 /* Scan is no longer pending */
3933 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003934
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003935 /*
3936 * cfg80211_scan_done informing NL80211 about completion
3937 * of scanning
3938 */
3939 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003940 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003941
Jeff Johnsone7245742012-09-05 17:12:55 -07003942allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003943 /* release the wake lock at the end of the scan*/
3944 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003945
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003946 /* Acquire wakelock to handle the case where APP's tries to suspend
3947 * immediatly after the driver gets connect request(i.e after scan)
3948 * from supplicant, this result in app's is suspending and not able
3949 * to process the connect request to AP */
3950 hdd_allow_suspend_timeout(100);
3951
Jeff Johnson295189b2012-06-20 16:38:30 -07003952 EXIT();
3953 return 0;
3954}
3955
3956/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08003957 * FUNCTION: hdd_isScanAllowed
3958 * Go through each adapter and check if scan allowed
3959 *
3960 */
3961v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
3962{
3963 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3964 hdd_station_ctx_t *pHddStaCtx = NULL;
3965 hdd_adapter_t *pAdapter = NULL;
3966 VOS_STATUS status = 0;
3967 v_U8_t staId = 0;
3968 v_U8_t *staMac = NULL;
3969
3970 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3971
3972 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3973 {
3974 pAdapter = pAdapterNode->pAdapter;
3975
3976 if( pAdapter )
3977 {
3978 hddLog(VOS_TRACE_LEVEL_INFO,
3979 "%s: Adapter with device mode %d exists",
3980 __func__, pAdapter->device_mode);
3981 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3982 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3983 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
3984 {
3985 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3986 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
3987 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
3988 {
3989 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
3990 hddLog(VOS_TRACE_LEVEL_ERROR,
3991 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
3992 "middle of WPS/EAPOL exchange.", __func__,
3993 staMac[0], staMac[1], staMac[2],
3994 staMac[3], staMac[4], staMac[5]);
3995 return VOS_FALSE;
3996 }
3997 }
3998 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
3999 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4000 {
4001 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4002 {
4003 if ((pAdapter->aStaInfo[staId].isUsed) &&
4004 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4005 {
4006 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4007
4008 hddLog(VOS_TRACE_LEVEL_ERROR,
4009 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4010 "middle of WPS/EAPOL exchange.", __func__,
4011 staMac[0], staMac[1], staMac[2],
4012 staMac[3], staMac[4], staMac[5]);
4013 return VOS_FALSE;
4014 }
4015 }
4016 }
4017 }
4018 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4019 pAdapterNode = pNext;
4020 }
4021 hddLog(VOS_TRACE_LEVEL_INFO,
4022 "%s: Scan allowed", __func__);
4023 return VOS_TRUE;
4024}
4025
4026/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004027 * FUNCTION: wlan_hdd_cfg80211_scan
4028 * this scan respond to scan trigger and update cfg80211 scan database
4029 * later, scan dump command can be used to recieve scan results
4030 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004031int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4032#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4033 struct net_device *dev,
4034#endif
4035 struct cfg80211_scan_request *request)
4036{
4037#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4038 struct net_device *dev = request->wdev->netdev;
4039#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004040 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4041 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4042 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4043 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4044 tCsrScanRequest scanRequest;
4045 tANI_U8 *channelList = NULL, i;
4046 v_U32_t scanId = 0;
4047 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004048 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004049#ifdef WLAN_FEATURE_P2P
4050 v_U8_t* pP2pIe = NULL;
4051#endif
4052
4053 ENTER();
4054
4055 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4056 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004057
4058 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4059 (eConnectionState_Connecting ==
4060 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4061 {
4062 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004063 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4064 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004065 return -EBUSY;
4066 }
4067
Jeff Johnson295189b2012-06-20 16:38:30 -07004068#ifdef WLAN_BTAMP_FEATURE
4069 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004070 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004071 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004072 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004073 "%s: No scanning when AMP is on", __func__);
4074 return -EOPNOTSUPP;
4075 }
4076#endif
4077 //Scan on any other interface is not supported.
4078 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4079 {
4080 hddLog(VOS_TRACE_LEVEL_ERROR,
4081 "%s: Not scanning on device_mode = %d",
4082 __func__, pAdapter->device_mode);
4083 return -EOPNOTSUPP;
4084 }
4085
4086 if (TRUE == pScanInfo->mScanPending)
4087 {
4088 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4089 return -EBUSY;
4090 }
4091
4092 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4093 {
4094 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4095 "%s:LOGP in Progress. Ignore!!!", __func__);
4096 return -EAGAIN;
4097 }
4098
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004099 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4100 {
4101 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4102 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4103 return -EAGAIN;
4104 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004105 //Don't Allow Scan and return busy if Remain On
4106 //Channel and action frame is pending
4107 //Otherwise Cancel Remain On Channel and allow Scan
4108 //If no action frame pending
4109 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4110 {
4111 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4112 return -EBUSY;
4113 }
4114
Jeff Johnson295189b2012-06-20 16:38:30 -07004115 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4116 {
4117 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004118 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004119 return -EAGAIN;
4120 }
4121 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4122 {
4123 hddLog(VOS_TRACE_LEVEL_WARN,
4124 "%s: MAX TM Level Scan not allowed", __func__);
4125 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4126 return -EBUSY;
4127 }
4128 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4129
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004130 /* Check if scan is allowed at this point of time.
4131 */
4132 if (!hdd_isScanAllowed(pHddCtx))
4133 {
4134 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4135 return -EBUSY;
4136 }
4137
Jeff Johnson295189b2012-06-20 16:38:30 -07004138 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4139
4140 if (NULL != request)
4141 {
4142 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4143 (int)request->n_ssids);
4144
4145 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4146 * Becasue of this, driver is assuming that this is not wildcard scan and so
4147 * is not aging out the scan results.
4148 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004149 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004150 {
4151 request->n_ssids = 0;
4152 }
4153
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004154 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004155 {
4156 tCsrSSIDInfo *SsidInfo;
4157 int j;
4158 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4159 /* Allocate num_ssid tCsrSSIDInfo structure */
4160 SsidInfo = scanRequest.SSIDs.SSIDList =
4161 ( tCsrSSIDInfo *)vos_mem_malloc(
4162 request->n_ssids*sizeof(tCsrSSIDInfo));
4163
4164 if(NULL == scanRequest.SSIDs.SSIDList)
4165 {
4166 hddLog(VOS_TRACE_LEVEL_ERROR,
4167 "memory alloc failed SSIDInfo buffer");
4168 return -ENOMEM;
4169 }
4170
4171 /* copy all the ssid's and their length */
4172 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4173 {
4174 /* get the ssid length */
4175 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4176 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4177 SsidInfo->SSID.length);
4178 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4179 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4180 j, SsidInfo->SSID.ssId);
4181 }
4182 /* set the scan type to active */
4183 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4184 }
4185 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4186 {
4187 /* set the scan type to active */
4188 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4189 }
4190 else
4191 {
4192 /*Set the scan type to default type, in this case it is ACTIVE*/
4193 scanRequest.scanType = pScanInfo->scan_mode;
4194 }
4195 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4196 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4197 }
4198 else
4199 {
4200 /* set the scan type to active */
4201 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4202 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4203
4204 /* set min and max channel time to zero */
4205 scanRequest.minChnTime = 0;
4206 scanRequest.maxChnTime = 0;
4207 }
4208
4209 /* set BSSType to default type */
4210 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4211
4212 /*TODO: scan the requested channels only*/
4213
4214 /*Right now scanning all the channels */
4215 if( request )
4216 {
4217 if( request->n_channels )
4218 {
4219 channelList = vos_mem_malloc( request->n_channels );
4220 if( NULL == channelList )
4221 {
4222 status = -ENOMEM;
4223 goto free_mem;
4224 }
4225
4226 for( i = 0 ; i < request->n_channels ; i++ )
4227 channelList[i] = request->channels[i]->hw_value;
4228 }
4229
4230 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4231 scanRequest.ChannelInfo.ChannelList = channelList;
4232
4233 /* set requestType to full scan */
4234 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004235
4236 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4237 * search (Flush on both full scan and social scan but not on single
4238 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4239 */
4240
4241 /* Supplicant does single channel scan after 8-way handshake
4242 * and in that case driver shoudnt flush scan results. If
4243 * driver flushes the scan results here and unfortunately if
4244 * the AP doesnt respond to our probe req then association
4245 * fails which is not desired
4246 */
4247
4248 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4249 {
4250 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4251 pAdapter->sessionId );
4252 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004253
4254 if( request->ie_len )
4255 {
4256 /* save this for future association (join requires this) */
4257 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4258 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4259 pScanInfo->scanAddIE.length = request->ie_len;
4260
4261 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004262 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4263 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004264 )
4265 {
4266 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4267 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4268 }
4269
4270 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4271 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4272
4273#ifdef WLAN_FEATURE_P2P
4274 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4275 request->ie_len);
4276 if (pP2pIe != NULL)
4277 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004278#ifdef WLAN_FEATURE_P2P_DEBUG
4279 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4280 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4281 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4282 {
4283 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4284 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4285 "Go nego completed to Connection is started");
4286 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4287 "for 8way Handshake");
4288 }
4289 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4290 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4291 {
4292 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4293 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4294 "Disconnected state to Connection is started");
4295 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4296 "for 4way Handshake");
4297 }
4298#endif
4299
Jeff Johnsone7245742012-09-05 17:12:55 -07004300 /* no_cck will be set during p2p find to disable 11b rates */
4301 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004302 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004303 hddLog(VOS_TRACE_LEVEL_INFO,
4304 "%s: This is a P2P Search", __func__);
4305 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004306
Jeff Johnsone7245742012-09-05 17:12:55 -07004307 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4308 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004309 /* set requestType to P2P Discovery */
4310 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004311 }
4312
4313 /*
4314 Skip Dfs Channel in case of P2P Search
4315 if it is set in ini file
4316 */
4317 if(cfg_param->skipDfsChnlInP2pSearch)
4318 {
4319 scanRequest.skipDfsChnlInP2pSearch = 1;
4320 }
4321 else
4322 {
4323 scanRequest.skipDfsChnlInP2pSearch = 0;
4324 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004325
Jeff Johnson295189b2012-06-20 16:38:30 -07004326 }
4327 }
4328#endif
4329 }
4330 }
4331
4332 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4333
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004334 /* acquire the wakelock to avoid the apps suspend during the scan. To
4335 * address the following issues.
4336 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4337 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4338 * for long time, this result in apps running at full power for long time.
4339 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4340 * be stuck in full power because of resume BMPS
4341 */
4342 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004343
4344 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004345 pAdapter->sessionId, &scanRequest, &scanId,
4346 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004347
Jeff Johnson295189b2012-06-20 16:38:30 -07004348 if (eHAL_STATUS_SUCCESS != status)
4349 {
4350 hddLog(VOS_TRACE_LEVEL_ERROR,
4351 "%s: sme_ScanRequest returned error %d", __func__, status);
4352 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004353 if(eHAL_STATUS_RESOURCES == status)
4354 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004355 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 -07004356 status = -EBUSY;
4357 } else {
4358 status = -EIO;
4359 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004360 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004361 goto free_mem;
4362 }
4363
4364 pScanInfo->mScanPending = TRUE;
4365 pAdapter->request = request;
4366 pScanInfo->scanId = scanId;
4367
4368 complete(&pScanInfo->scan_req_completion_event);
4369
4370free_mem:
4371 if( scanRequest.SSIDs.SSIDList )
4372 {
4373 vos_mem_free(scanRequest.SSIDs.SSIDList);
4374 }
4375
4376 if( channelList )
4377 vos_mem_free( channelList );
4378
4379 EXIT();
4380
4381 return status;
4382}
4383
4384/*
4385 * FUNCTION: wlan_hdd_cfg80211_connect_start
4386 * This function is used to start the association process
4387 */
4388int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004389 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004390{
4391 int status = 0;
4392 hdd_wext_state_t *pWextState;
4393 v_U32_t roamId;
4394 tCsrRoamProfile *pRoamProfile;
4395 eMib_dot11DesiredBssType connectedBssType;
4396 eCsrAuthType RSNAuthType;
4397
4398 ENTER();
4399
4400 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4401
4402 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4403 {
4404 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4405 return -EINVAL;
4406 }
4407
4408 pRoamProfile = &pWextState->roamProfile;
4409
4410 if (pRoamProfile)
4411 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004412 int ret = 0;
4413 hdd_station_ctx_t *pHddStaCtx;
4414 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4415 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4416
4417 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4418 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4419 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004420 {
4421 /* Issue disconnect to CSR */
4422 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4423 if( eHAL_STATUS_SUCCESS ==
4424 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4425 pAdapter->sessionId,
4426 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4427 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004428 ret = wait_for_completion_interruptible_timeout(
4429 &pAdapter->disconnect_comp_var,
4430 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4431 if (0 == ret)
4432 {
4433 VOS_ASSERT(0);
4434 }
4435 }
4436 }
4437 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4438 {
4439 ret = wait_for_completion_interruptible_timeout(
4440 &pAdapter->disconnect_comp_var,
4441 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4442 if (0 == ret)
4443 {
4444 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004445 }
4446 }
4447
4448 if (HDD_WMM_USER_MODE_NO_QOS ==
4449 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4450 {
4451 /*QoS not enabled in cfg file*/
4452 pRoamProfile->uapsd_mask = 0;
4453 }
4454 else
4455 {
4456 /*QoS enabled, update uapsd mask from cfg file*/
4457 pRoamProfile->uapsd_mask =
4458 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4459 }
4460
4461 pRoamProfile->SSIDs.numOfSSIDs = 1;
4462 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4463 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4464 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4465 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4466 ssid, ssid_len);
4467
4468 if (bssid)
4469 {
4470 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4471 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4472 WNI_CFG_BSSID_LEN);
4473 /* Save BSSID in seperate variable as well, as RoamProfile
4474 BSSID is getting zeroed out in the association process. And in
4475 case of join failure we should send valid BSSID to supplicant
4476 */
4477 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4478 WNI_CFG_BSSID_LEN);
4479 }
4480
4481 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4482 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4483 {
4484 /*set gen ie*/
4485 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4486 /*set auth*/
4487 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4488 }
4489 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4490 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4491 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4492 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4493 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4494 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4495 )
4496 {
4497 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4498 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4499 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4500 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4501 eCSR_AUTH_TYPE_AUTOSWITCH;
4502 pWextState->roamProfile.AuthType.authType[0] =
4503 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4504 }
4505#ifdef FEATURE_WLAN_WAPI
4506 if (pAdapter->wapi_info.nWapiMode)
4507 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004508 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004509 switch (pAdapter->wapi_info.wapiAuthMode)
4510 {
4511 case WAPI_AUTH_MODE_PSK:
4512 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004513 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004514 pAdapter->wapi_info.wapiAuthMode);
4515 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4516 break;
4517 }
4518 case WAPI_AUTH_MODE_CERT:
4519 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004520 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 pAdapter->wapi_info.wapiAuthMode);
4522 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4523 break;
4524 }
4525 } // End of switch
4526 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4527 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4528 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004529 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004530 pRoamProfile->AuthType.numEntries = 1;
4531 pRoamProfile->EncryptionType.numEntries = 1;
4532 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4533 pRoamProfile->mcEncryptionType.numEntries = 1;
4534 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4535 }
4536 }
4537#endif /* FEATURE_WLAN_WAPI */
4538 pRoamProfile->csrPersona = pAdapter->device_mode;
4539
Jeff Johnson32d95a32012-09-10 13:15:23 -07004540 if( operatingChannel )
4541 {
4542 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4543 pRoamProfile->ChannelInfo.numOfChannels = 1;
4544 }
4545
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004546 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4547 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4548 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4549 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004550 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4551 */
4552 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4553 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4554 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004555
Jeff Johnson295189b2012-06-20 16:38:30 -07004556 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4557 pAdapter->sessionId, pRoamProfile, &roamId);
4558
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004559 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304560 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4561
4562 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004563 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4564 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4565 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304566 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004567 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304568 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004569
4570 pRoamProfile->ChannelInfo.ChannelList = NULL;
4571 pRoamProfile->ChannelInfo.numOfChannels = 0;
4572
Jeff Johnson295189b2012-06-20 16:38:30 -07004573 }
4574 else
4575 {
4576 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4577 return -EINVAL;
4578 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004579 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 return status;
4581}
4582
4583/*
4584 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4585 * This function is used to set the authentication type (OPEN/SHARED).
4586 *
4587 */
4588static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4589 enum nl80211_auth_type auth_type)
4590{
4591 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4592 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4593
4594 ENTER();
4595
4596 /*set authentication type*/
4597 switch (auth_type)
4598 {
4599 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4600 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004601#ifdef WLAN_FEATURE_VOWIFI_11R
4602 case NL80211_AUTHTYPE_FT:
4603#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004604 hddLog(VOS_TRACE_LEVEL_INFO,
4605 "%s: set authentication type to OPEN", __func__);
4606 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4607 break;
4608
4609 case NL80211_AUTHTYPE_SHARED_KEY:
4610 hddLog(VOS_TRACE_LEVEL_INFO,
4611 "%s: set authentication type to SHARED", __func__);
4612 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4613 break;
4614#ifdef FEATURE_WLAN_CCX
4615 case NL80211_AUTHTYPE_NETWORK_EAP:
4616 hddLog(VOS_TRACE_LEVEL_INFO,
4617 "%s: set authentication type to CCKM WPA", __func__);
4618 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4619 break;
4620#endif
4621
4622
4623 default:
4624 hddLog(VOS_TRACE_LEVEL_ERROR,
4625 "%s: Unsupported authentication type %d", __func__,
4626 auth_type);
4627 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4628 return -EINVAL;
4629 }
4630
4631 pWextState->roamProfile.AuthType.authType[0] =
4632 pHddStaCtx->conn_info.authType;
4633 return 0;
4634}
4635
4636/*
4637 * FUNCTION: wlan_hdd_set_akm_suite
4638 * This function is used to set the key mgmt type(PSK/8021x).
4639 *
4640 */
4641static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4642 u32 key_mgmt
4643 )
4644{
4645 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4646 ENTER();
4647
4648 /*set key mgmt type*/
4649 switch(key_mgmt)
4650 {
4651 case WLAN_AKM_SUITE_PSK:
4652 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4653 __func__);
4654 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4655 break;
4656
4657 case WLAN_AKM_SUITE_8021X:
4658 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4659 __func__);
4660 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4661 break;
4662#ifdef FEATURE_WLAN_CCX
4663#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4664#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4665 case WLAN_AKM_SUITE_CCKM:
4666 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4667 __func__);
4668 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4669 break;
4670#endif
4671
4672 default:
4673 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4674 __func__, key_mgmt);
4675 return -EINVAL;
4676
4677 }
4678 return 0;
4679}
4680
4681/*
4682 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4683 * This function is used to set the encryption type
4684 * (NONE/WEP40/WEP104/TKIP/CCMP).
4685 */
4686static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4687 u32 cipher,
4688 bool ucast
4689 )
4690{
4691 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4692 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4693 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4694
4695 ENTER();
4696
4697 if (!cipher)
4698 {
4699 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4700 __func__, cipher);
4701 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4702 }
4703 else
4704 {
4705
4706 /*set encryption method*/
4707 switch (cipher)
4708 {
4709 case IW_AUTH_CIPHER_NONE:
4710 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4711 break;
4712
4713 case WLAN_CIPHER_SUITE_WEP40:
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_WEP40;
4717 else
4718 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4719 break;
4720
4721 case WLAN_CIPHER_SUITE_WEP104:
4722 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4723 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4724 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4725 else
4726 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4727 break;
4728
4729 case WLAN_CIPHER_SUITE_TKIP:
4730 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4731 break;
4732
4733 case WLAN_CIPHER_SUITE_CCMP:
4734 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4735 break;
4736#ifdef FEATURE_WLAN_WAPI
4737 case WLAN_CIPHER_SUITE_SMS4:
4738 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4739 break;
4740#endif
4741
4742#ifdef FEATURE_WLAN_CCX
4743 case WLAN_CIPHER_SUITE_KRK:
4744 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4745 break;
4746#endif
4747 default:
4748 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4749 __func__, cipher);
4750 return -EOPNOTSUPP;
4751 }
4752 }
4753
4754 if (ucast)
4755 {
4756 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4757 __func__, encryptionType);
4758 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4759 pWextState->roamProfile.EncryptionType.numEntries = 1;
4760 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4761 encryptionType;
4762 }
4763 else
4764 {
4765 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4766 __func__, encryptionType);
4767 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4768 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4769 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4770 }
4771
4772 return 0;
4773}
4774
4775
4776/*
4777 * FUNCTION: wlan_hdd_cfg80211_set_ie
4778 * This function is used to parse WPA/RSN IE's.
4779 */
4780int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4781 u8 *ie,
4782 size_t ie_len
4783 )
4784{
4785 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4786 u8 *genie = ie;
4787 v_U16_t remLen = ie_len;
4788#ifdef FEATURE_WLAN_WAPI
4789 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4790 u16 *tmp;
4791 v_U16_t akmsuiteCount;
4792 int *akmlist;
4793#endif
4794 ENTER();
4795
4796 /* clear previous assocAddIE */
4797 pWextState->assocAddIE.length = 0;
4798 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4799
4800 while (remLen >= 2)
4801 {
4802 v_U16_t eLen = 0;
4803 v_U8_t elementId;
4804 elementId = *genie++;
4805 eLen = *genie++;
4806 remLen -= 2;
4807
4808 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4809 __func__, elementId, eLen);
4810
4811 switch ( elementId )
4812 {
4813 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004814 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 -07004815 {
4816 hddLog(VOS_TRACE_LEVEL_ERROR,
4817 "%s: Invalid WPA IE", __func__);
4818 return -EINVAL;
4819 }
4820 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4821 {
4822 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4823 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4824 __func__, eLen + 2);
4825
4826 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4827 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004828 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4829 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004830 VOS_ASSERT(0);
4831 return -ENOMEM;
4832 }
4833 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4834 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4835 pWextState->assocAddIE.length += eLen + 2;
4836
4837 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4838 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4839 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4840 }
4841 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4842 {
4843 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4844 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4845 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4846 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4847 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4848 }
4849#ifdef WLAN_FEATURE_P2P
4850 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4851 P2P_OUI_TYPE_SIZE))
4852 /*Consider P2P IE, only for P2P Client */
4853 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4854 {
4855 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4856 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4857 __func__, eLen + 2);
4858
4859 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4860 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004861 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4862 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004863 VOS_ASSERT(0);
4864 return -ENOMEM;
4865 }
4866 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4867 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4868 pWextState->assocAddIE.length += eLen + 2;
4869
4870 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4871 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4872 }
4873#endif
4874#ifdef WLAN_FEATURE_WFD
4875 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4876 WFD_OUI_TYPE_SIZE))
4877 /*Consider WFD IE, only for P2P Client */
4878 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4879 {
4880 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4881 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4882 __func__, eLen + 2);
4883
4884 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4885 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004886 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4887 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004888 VOS_ASSERT(0);
4889 return -ENOMEM;
4890 }
4891 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4892 // WPS IE + P2P IE + WFD IE
4893 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4894 pWextState->assocAddIE.length += eLen + 2;
4895
4896 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4897 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4898 }
4899#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004900 /* Appending HS 2.0 Indication Element in Assiciation Request */
4901 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004902 HS20_OUI_TYPE_SIZE)) )
4903 {
4904 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4905 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4906 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004907
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004908 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4909 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004910 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4911 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004912 VOS_ASSERT(0);
4913 return -ENOMEM;
4914 }
4915 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4916 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004917
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004918 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4919 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4920 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004921
Jeff Johnson295189b2012-06-20 16:38:30 -07004922 break;
4923 case DOT11F_EID_RSN:
4924 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4925 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4926 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4927 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4928 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4929 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004930 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4931 case DOT11F_EID_EXTCAP:
4932 {
4933 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4934 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4935 __func__, eLen + 2);
4936
4937 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4938 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004939 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4940 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004941 VOS_ASSERT(0);
4942 return -ENOMEM;
4943 }
4944 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4945 pWextState->assocAddIE.length += eLen + 2;
4946
4947 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4948 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4949 break;
4950 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004951#ifdef FEATURE_WLAN_WAPI
4952 case WLAN_EID_WAPI:
4953 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4954 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4955 pAdapter->wapi_info.nWapiMode);
4956 tmp = (u16 *)ie;
4957 tmp = tmp + 2; // Skip element Id and Len, Version
4958 akmsuiteCount = WPA_GET_LE16(tmp);
4959 tmp = tmp + 1;
4960 akmlist = (int *)(tmp);
4961 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4962 {
4963 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4964 }
4965 else
4966 {
4967 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4968 VOS_ASSERT(0);
4969 return -EINVAL;
4970 }
4971
4972 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4973 {
4974 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004975 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004976 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4977 }
4978 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4979 {
4980 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004981 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004982 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4983 }
4984 break;
4985#endif
4986 default:
4987 hddLog (VOS_TRACE_LEVEL_ERROR,
4988 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004989 /* when Unknown IE is received we should break and continue
4990 * to the next IE in the buffer instead we were returning
4991 * so changing this to break */
4992 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 }
4994 genie += eLen;
4995 remLen -= eLen;
4996 }
4997 EXIT();
4998 return 0;
4999}
5000
5001/*
5002 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5003 * This function is used to initialize the security
5004 * parameters during connect operation.
5005 */
5006int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5007 struct cfg80211_connect_params *req
5008 )
5009{
5010 int status = 0;
5011 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5012 ENTER();
5013
5014 /*set wpa version*/
5015 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5016
5017 if (req->crypto.wpa_versions)
5018 {
5019 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5020 && ( (req->ie_len)
5021 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5022 // Make sure that it is including a WPA IE.
5023 /* Currently NL is putting WPA version 1 even for open,
5024 * since p2p ie is also put in same buffer.
5025 * */
5026 {
5027 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5028 }
5029 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5030 {
5031 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5032 }
5033 }
5034
5035 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5036 pWextState->wpaVersion);
5037
5038 /*set authentication type*/
5039 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5040
5041 if (0 > status)
5042 {
5043 hddLog(VOS_TRACE_LEVEL_ERROR,
5044 "%s: failed to set authentication type ", __func__);
5045 return status;
5046 }
5047
5048 /*set key mgmt type*/
5049 if (req->crypto.n_akm_suites)
5050 {
5051 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5052 if (0 > status)
5053 {
5054 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5055 __func__);
5056 return status;
5057 }
5058 }
5059
5060 /*set pairwise cipher type*/
5061 if (req->crypto.n_ciphers_pairwise)
5062 {
5063 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5064 req->crypto.ciphers_pairwise[0], true);
5065 if (0 > status)
5066 {
5067 hddLog(VOS_TRACE_LEVEL_ERROR,
5068 "%s: failed to set unicast cipher type", __func__);
5069 return status;
5070 }
5071 }
5072 else
5073 {
5074 /*Reset previous cipher suite to none*/
5075 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5076 if (0 > status)
5077 {
5078 hddLog(VOS_TRACE_LEVEL_ERROR,
5079 "%s: failed to set unicast cipher type", __func__);
5080 return status;
5081 }
5082 }
5083
5084 /*set group cipher type*/
5085 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5086 false);
5087
5088 if (0 > status)
5089 {
5090 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5091 __func__);
5092 return status;
5093 }
5094
5095 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5096 if (req->ie_len)
5097 {
5098 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5099 if ( 0 > status)
5100 {
5101 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5102 __func__);
5103 return status;
5104 }
5105 }
5106
5107 /*incase of WEP set default key information*/
5108 if (req->key && req->key_len)
5109 {
5110 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5111 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5112 )
5113 {
5114 if ( IW_AUTH_KEY_MGMT_802_1X
5115 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5116 {
5117 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5118 __func__);
5119 return -EOPNOTSUPP;
5120 }
5121 else
5122 {
5123 u8 key_len = req->key_len;
5124 u8 key_idx = req->key_idx;
5125
5126 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5127 && (CSR_MAX_NUM_KEY > key_idx)
5128 )
5129 {
5130 hddLog(VOS_TRACE_LEVEL_INFO,
5131 "%s: setting default wep key, key_idx = %hu key_len %hu",
5132 __func__, key_idx, key_len);
5133 vos_mem_copy(
5134 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5135 req->key, key_len);
5136 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5137 (u8)key_len;
5138 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5139 }
5140 }
5141 }
5142 }
5143
5144 return status;
5145}
5146
5147/*
5148 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5149 * This function is used to initialize the security
5150 * parameters during connect operation.
5151 */
5152static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5153 struct net_device *ndev,
5154 struct cfg80211_connect_params *req
5155 )
5156{
5157 int status = 0;
5158 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5159 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5160 hdd_context_t *pHddCtx = NULL;
5161
5162 ENTER();
5163
5164 hddLog(VOS_TRACE_LEVEL_INFO,
5165 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5166
5167 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5168 {
5169 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5170 "%s:LOGP in Progress. Ignore!!!", __func__);
5171 return -EAGAIN;
5172 }
5173
5174#ifdef WLAN_BTAMP_FEATURE
5175 //Infra connect not supported when AMP traffic is on.
5176 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5177 {
5178 hddLog(VOS_TRACE_LEVEL_ERROR,
5179 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005180 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005181 }
5182#endif
5183 /*initialise security parameters*/
5184 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5185
5186 if ( 0 > status)
5187 {
5188 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5189 __func__);
5190 return status;
5191 }
5192
5193 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005194 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005195 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5196 (vos_concurrent_sessions_running()))
5197 {
5198 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5199
5200 if (NULL != pVosContext)
5201 {
5202 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5203 if(NULL != pHddCtx)
5204 {
5205 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5206 }
5207 }
5208 }
5209
Mohit Khanna765234a2012-09-11 15:08:35 -07005210 if ( req->channel )
5211 {
5212 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5213 req->ssid_len, req->bssid,
5214 req->channel->hw_value);
5215 }
5216 else
5217 {
5218 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5219 req->ssid_len, req->bssid,
5220 0);
5221 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005222
5223 if (0 > status)
5224 {
5225 //ReEnable BMPS if disabled
5226 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5227 (NULL != pHddCtx))
5228 {
5229 //ReEnable Bmps and Imps back
5230 hdd_enable_bmps_imps(pHddCtx);
5231 }
5232
5233 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5234 return status;
5235 }
5236 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5237 EXIT();
5238 return status;
5239}
5240
5241
5242/*
5243 * FUNCTION: wlan_hdd_cfg80211_disconnect
5244 * This function is used to issue a disconnect request to SME
5245 */
5246static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5247 struct net_device *dev,
5248 u16 reason
5249 )
5250{
5251 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5252 tCsrRoamProfile *pRoamProfile =
5253 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5254 int status = 0;
5255 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5256
5257 ENTER();
5258
5259 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5260 __func__,pAdapter->device_mode);
5261
5262 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5263 __func__, reason);
5264
5265 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5266 {
5267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5268 "%s:LOGP in Progress. Ignore!!!",__func__);
5269 return -EAGAIN;
5270 }
5271 if (NULL != pRoamProfile)
5272 {
5273 /*issue disconnect request to SME, if station is in connected state*/
5274 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5275 {
5276 eCsrRoamDisconnectReason reasonCode =
5277 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5278 switch(reason)
5279 {
5280 case WLAN_REASON_MIC_FAILURE:
5281 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5282 break;
5283
5284 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5285 case WLAN_REASON_DISASSOC_AP_BUSY:
5286 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5287 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5288 break;
5289
5290 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5291 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5292 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5293 break;
5294
5295 case WLAN_REASON_DEAUTH_LEAVING:
5296 default:
5297 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5298 break;
5299 }
5300 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5301 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5302 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5303
5304 /*issue disconnect*/
5305 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5306 pAdapter->sessionId, reasonCode);
5307
5308 if ( 0 != status)
5309 {
5310 hddLog(VOS_TRACE_LEVEL_ERROR,
5311 "%s csrRoamDisconnect failure, returned %d \n",
5312 __func__, (int)status );
5313 return -EINVAL;
5314 }
5315
5316 wait_for_completion_interruptible_timeout(
5317 &pAdapter->disconnect_comp_var,
5318 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5319
5320
5321 /*stop tx queues*/
5322 netif_tx_disable(dev);
5323 netif_carrier_off(dev);
5324 }
5325 }
5326 else
5327 {
5328 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5329 }
5330
5331 return status;
5332}
5333
5334/*
5335 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5336 * This function is used to initialize the security
5337 * settings in IBSS mode.
5338 */
5339static int wlan_hdd_cfg80211_set_privacy_ibss(
5340 hdd_adapter_t *pAdapter,
5341 struct cfg80211_ibss_params *params
5342 )
5343{
5344 int status = 0;
5345 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5346 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5347 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5348
5349 ENTER();
5350
5351 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5352
5353 if (params->ie_len && ( NULL != params->ie) )
5354 {
5355 if (WLAN_EID_RSN == params->ie[0])
5356 {
5357 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5358 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5359 }
5360 else
5361 {
5362 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5363 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5364 }
5365 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5366
5367 if (0 > status)
5368 {
5369 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5370 __func__);
5371 return status;
5372 }
5373 }
5374
5375 pWextState->roamProfile.AuthType.authType[0] =
5376 pHddStaCtx->conn_info.authType =
5377 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5378
5379 if (params->privacy)
5380 {
5381 /* Security enabled IBSS, At this time there is no information available
5382 * about the security paramters, so initialise the encryption type to
5383 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5384 * The correct security parameters will be updated later in
5385 * wlan_hdd_cfg80211_add_key */
5386 /* Hal expects encryption type to be set inorder
5387 *enable privacy bit in beacons */
5388
5389 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5390 }
5391
5392 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5393 pWextState->roamProfile.EncryptionType.numEntries = 1;
5394 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5395
5396 return status;
5397}
5398
5399/*
5400 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5401 * This function is used to create/join an IBSS
5402 */
5403static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5404 struct net_device *dev,
5405 struct cfg80211_ibss_params *params
5406 )
5407{
5408 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5409 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5410 tCsrRoamProfile *pRoamProfile;
5411 int status;
5412 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5413
5414 ENTER();
5415
5416 hddLog(VOS_TRACE_LEVEL_INFO,
5417 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5418
5419 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5420 {
5421 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5422 "%s:LOGP in Progress. Ignore!!!", __func__);
5423 return -EAGAIN;
5424 }
5425
5426 if (NULL == pWextState)
5427 {
5428 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5429 __func__);
5430 return -EIO;
5431 }
5432
5433 pRoamProfile = &pWextState->roamProfile;
5434
5435 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5436 {
5437 hddLog (VOS_TRACE_LEVEL_ERROR,
5438 "%s Interface type is not set to IBSS \n", __func__);
5439 return -EINVAL;
5440 }
5441
5442 /* Set Channel */
5443 if (NULL != params->channel)
5444 {
5445 u8 channelNum;
5446 if (IEEE80211_BAND_5GHZ == params->channel->band)
5447 {
5448 hddLog(VOS_TRACE_LEVEL_ERROR,
5449 "%s: IBSS join is called with unsupported band %d",
5450 __func__, params->channel->band);
5451 return -EOPNOTSUPP;
5452 }
5453
5454 /* Get channel number */
5455 channelNum =
5456 ieee80211_frequency_to_channel(params->channel->center_freq);
5457
5458 /*TODO: use macro*/
5459 if (14 >= channelNum)
5460 {
5461 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5462 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5463 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5464 int indx;
5465
5466 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5467 validChan, &numChans))
5468 {
5469 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5470 __func__);
5471 return -EOPNOTSUPP;
5472 }
5473
5474 for (indx = 0; indx < numChans; indx++)
5475 {
5476 if (channelNum == validChan[indx])
5477 {
5478 break;
5479 }
5480 }
5481 if (indx >= numChans)
5482 {
5483 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5484 __func__, channelNum);
5485 return -EINVAL;
5486 }
5487 /* Set the Operational Channel */
5488 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5489 channelNum);
5490 pRoamProfile->ChannelInfo.numOfChannels = 1;
5491 pHddStaCtx->conn_info.operationChannel = channelNum;
5492 pRoamProfile->ChannelInfo.ChannelList =
5493 &pHddStaCtx->conn_info.operationChannel;
5494 }
5495 else
5496 {
5497 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5498 __func__, channelNum);
5499 return -EINVAL;
5500 }
5501 }
5502
5503 /* Initialize security parameters */
5504 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5505 if (status < 0)
5506 {
5507 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5508 __func__);
5509 return status;
5510 }
5511
5512 /* Issue connect start */
5513 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005514 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005515
5516 if (0 > status)
5517 {
5518 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5519 return status;
5520 }
5521
5522 return 0;
5523}
5524
5525/*
5526 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5527 * This function is used to leave an IBSS
5528 */
5529static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5530 struct net_device *dev
5531 )
5532{
5533 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5534 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5535 tCsrRoamProfile *pRoamProfile;
5536
5537 ENTER();
5538
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005539 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5540 {
5541 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5542 "%s:LOGP in Progress. Ignore!!!", __func__);
5543 return -EAGAIN;
5544 }
5545
Jeff Johnson295189b2012-06-20 16:38:30 -07005546 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5547 if (NULL == pWextState)
5548 {
5549 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5550 __func__);
5551 return -EIO;
5552 }
5553
5554 pRoamProfile = &pWextState->roamProfile;
5555
5556 /* Issue disconnect only if interface type is set to IBSS */
5557 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5558 {
5559 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5560 __func__);
5561 return -EINVAL;
5562 }
5563
5564 /* Issue Disconnect request */
5565 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5566 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5567 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5568
5569 return 0;
5570}
5571
5572/*
5573 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5574 * This function is used to set the phy parameters
5575 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5576 */
5577static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5578 u32 changed)
5579{
5580 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5581 tHalHandle hHal = pHddCtx->hHal;
5582
5583 ENTER();
5584
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005585 if ( pHddCtx->isLogpInProgress )
5586 {
5587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5588 "%s:LOGP in Progress. Ignore!!!", __func__);
5589 return -EAGAIN;
5590 }
5591
Jeff Johnson295189b2012-06-20 16:38:30 -07005592 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5593 {
5594 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5595 WNI_CFG_RTS_THRESHOLD_STAMAX :
5596 wiphy->rts_threshold;
5597
5598 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5599 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5600 {
5601 hddLog(VOS_TRACE_LEVEL_ERROR,
5602 "%s: Invalid RTS Threshold value %hu",
5603 __func__, rts_threshold);
5604 return -EINVAL;
5605 }
5606
5607 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5608 rts_threshold, ccmCfgSetCallback,
5609 eANI_BOOLEAN_TRUE))
5610 {
5611 hddLog(VOS_TRACE_LEVEL_ERROR,
5612 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5613 __func__, rts_threshold);
5614 return -EIO;
5615 }
5616
5617 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5618 rts_threshold);
5619 }
5620
5621 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5622 {
5623 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5624 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5625 wiphy->frag_threshold;
5626
5627 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5628 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5629 {
5630 hddLog(VOS_TRACE_LEVEL_ERROR,
5631 "%s: Invalid frag_threshold value %hu", __func__,
5632 frag_threshold);
5633 return -EINVAL;
5634 }
5635
5636 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5637 frag_threshold, ccmCfgSetCallback,
5638 eANI_BOOLEAN_TRUE))
5639 {
5640 hddLog(VOS_TRACE_LEVEL_ERROR,
5641 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5642 __func__, frag_threshold);
5643 return -EIO;
5644 }
5645
5646 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5647 frag_threshold);
5648 }
5649
5650 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5651 || (changed & WIPHY_PARAM_RETRY_LONG))
5652 {
5653 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5654 wiphy->retry_short :
5655 wiphy->retry_long;
5656
5657 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5658 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5659 {
5660 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5661 __func__, retry_value);
5662 return -EINVAL;
5663 }
5664
5665 if (changed & WIPHY_PARAM_RETRY_SHORT)
5666 {
5667 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5668 retry_value, ccmCfgSetCallback,
5669 eANI_BOOLEAN_TRUE))
5670 {
5671 hddLog(VOS_TRACE_LEVEL_ERROR,
5672 "%s: ccmCfgSetInt failed for long retry count %hu",
5673 __func__, retry_value);
5674 return -EIO;
5675 }
5676 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5677 __func__, retry_value);
5678 }
5679 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5680 {
5681 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5682 retry_value, ccmCfgSetCallback,
5683 eANI_BOOLEAN_TRUE))
5684 {
5685 hddLog(VOS_TRACE_LEVEL_ERROR,
5686 "%s: ccmCfgSetInt failed for short retry count %hu",
5687 __func__, retry_value);
5688 return -EIO;
5689 }
5690 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5691 __func__, retry_value);
5692 }
5693 }
5694
5695 return 0;
5696}
5697
5698/*
5699 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5700 * This function is used to set the txpower
5701 */
5702static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5703#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5704 enum tx_power_setting type,
5705#else
5706 enum nl80211_tx_power_setting type,
5707#endif
5708 int dbm)
5709{
5710 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5711 tHalHandle hHal = pHddCtx->hHal;
5712 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5713 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5714
5715 ENTER();
5716
5717 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5718 dbm, ccmCfgSetCallback,
5719 eANI_BOOLEAN_TRUE))
5720 {
5721 hddLog(VOS_TRACE_LEVEL_ERROR,
5722 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5723 return -EIO;
5724 }
5725
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005726 if ( pHddCtx->isLogpInProgress )
5727 {
5728 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5729 "%s:LOGP in Progress. Ignore!!!", __func__);
5730 return -EAGAIN;
5731 }
5732
Jeff Johnson295189b2012-06-20 16:38:30 -07005733 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5734 dbm);
5735
5736 switch(type)
5737 {
5738 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5739 /* Fall through */
5740 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5741 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5742 {
5743 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5744 __func__);
5745 return -EIO;
5746 }
5747 break;
5748 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5749 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5750 __func__);
5751 return -EOPNOTSUPP;
5752 break;
5753 default:
5754 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5755 __func__, type);
5756 return -EIO;
5757 }
5758
5759 return 0;
5760}
5761
5762/*
5763 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5764 * This function is used to read the txpower
5765 */
5766static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5767{
5768
5769 hdd_adapter_t *pAdapter;
5770 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5771
Jeff Johnsone7245742012-09-05 17:12:55 -07005772 ENTER();
5773
Jeff Johnson295189b2012-06-20 16:38:30 -07005774 if (NULL == pHddCtx)
5775 {
5776 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5777 *dbm = 0;
5778 return -ENOENT;
5779 }
5780
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005781 if ( pHddCtx->isLogpInProgress )
5782 {
5783 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5784 "%s:LOGP in Progress. Ignore!!!", __func__);
5785 return -EAGAIN;
5786 }
5787
Jeff Johnson295189b2012-06-20 16:38:30 -07005788 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5789 if (NULL == pAdapter)
5790 {
5791 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5792 return -ENOENT;
5793 }
5794
5795 wlan_hdd_get_classAstats(pAdapter);
5796 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5797
Jeff Johnsone7245742012-09-05 17:12:55 -07005798 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005799 return 0;
5800}
5801
5802static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5803 u8* mac, struct station_info *sinfo)
5804{
5805 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5806 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5807 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5808 tANI_U8 rate_flags;
5809
5810 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5811 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5812 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5813
5814 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5815 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5816 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5817 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5818 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5819 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5820 tANI_U16 maxRate = 0;
5821 tANI_U16 myRate;
5822 tANI_U16 currentRate = 0;
5823 tANI_U8 maxSpeedMCS = 0;
5824 tANI_U8 maxMCSIdx = 0;
5825 tANI_U8 rateFlag = 1;
5826 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005827 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005828
Jeff Johnsone7245742012-09-05 17:12:55 -07005829 ENTER();
5830
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5832 (0 == ssidlen))
5833 {
5834 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5835 " Invalid ssidlen, %d", __func__, ssidlen);
5836 /*To keep GUI happy*/
5837 return 0;
5838 }
5839
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005840 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5841 {
5842 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5843 "%s:LOGP in Progress. Ignore!!!", __func__);
5844 return -EAGAIN;
5845 }
5846
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5848 sinfo->filled |= STATION_INFO_SIGNAL;
5849
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005850 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005851 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5852
5853 //convert to the UI units of 100kbps
5854 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5855
5856#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005857 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 -07005858 sinfo->signal,
5859 pCfg->reportMaxLinkSpeed,
5860 myRate,
5861 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005862 (int) pCfg->linkSpeedRssiMid,
5863 (int) pCfg->linkSpeedRssiLow,
5864 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005865#endif //LINKSPEED_DEBUG_ENABLED
5866
5867 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5868 {
5869 // we do not want to necessarily report the current speed
5870 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5871 {
5872 // report the max possible speed
5873 rssidx = 0;
5874 }
5875 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5876 {
5877 // report the max possible speed with RSSI scaling
5878 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5879 {
5880 // report the max possible speed
5881 rssidx = 0;
5882 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005883 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 {
5885 // report middle speed
5886 rssidx = 1;
5887 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005888 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5889 {
5890 // report middle speed
5891 rssidx = 2;
5892 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005893 else
5894 {
5895 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005896 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 }
5898 }
5899 else
5900 {
5901 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5902 hddLog(VOS_TRACE_LEVEL_ERROR,
5903 "%s: Invalid value for reportMaxLinkSpeed: %u",
5904 __func__, pCfg->reportMaxLinkSpeed);
5905 rssidx = 0;
5906 }
5907
5908 maxRate = 0;
5909
5910 /* Get Basic Rate Set */
5911 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5912 for (i = 0; i < ORLeng; i++)
5913 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005914 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005915 {
5916 /* Validate Rate Set */
5917 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5918 {
5919 currentRate = supported_data_rate[j].supported_rate[rssidx];
5920 break;
5921 }
5922 }
5923 /* Update MAX rate */
5924 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5925 }
5926
5927 /* Get Extended Rate Set */
5928 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5929 for (i = 0; i < ERLeng; i++)
5930 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005931 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005932 {
5933 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5934 {
5935 currentRate = supported_data_rate[j].supported_rate[rssidx];
5936 break;
5937 }
5938 }
5939 /* Update MAX rate */
5940 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5941 }
5942
5943 /* Get MCS Rate Set -- but only if we are connected at MCS
5944 rates or if we are always reporting max speed or if we have
5945 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005946 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 {
5948 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5949 rateFlag = 0;
5950 if (rate_flags & eHAL_TX_RATE_HT40)
5951 {
5952 rateFlag |= 1;
5953 }
5954 if (rate_flags & eHAL_TX_RATE_SGI)
5955 {
5956 rateFlag |= 2;
5957 }
5958
5959 for (i = 0; i < MCSLeng; i++)
5960 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005961 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5962 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005963 {
5964 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5965 {
5966 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5967 break;
5968 }
5969 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005970 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005971 {
5972 maxRate = currentRate;
5973 maxSpeedMCS = 1;
5974 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5975 }
5976 }
5977 }
5978
5979 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005980 if (((maxRate < myRate) && (0 == rssidx)) ||
5981 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005982 {
5983 maxRate = myRate;
5984 if (rate_flags & eHAL_TX_RATE_LEGACY)
5985 {
5986 maxSpeedMCS = 0;
5987 }
5988 else
5989 {
5990 maxSpeedMCS = 1;
5991 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5992 }
5993 }
5994
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005995 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005996 {
5997 sinfo->txrate.legacy = maxRate;
5998#ifdef LINKSPEED_DEBUG_ENABLED
5999 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6000#endif //LINKSPEED_DEBUG_ENABLED
6001 }
6002 else
6003 {
6004 sinfo->txrate.mcs = maxMCSIdx;
6005 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6006 if (rate_flags & eHAL_TX_RATE_SGI)
6007 {
6008 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6009 }
6010 if (rate_flags & eHAL_TX_RATE_HT40)
6011 {
6012 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6013 }
6014#ifdef LINKSPEED_DEBUG_ENABLED
6015 pr_info("Reporting MCS rate %d flags %x\n",
6016 sinfo->txrate.mcs,
6017 sinfo->txrate.flags );
6018#endif //LINKSPEED_DEBUG_ENABLED
6019 }
6020 }
6021 else
6022 {
6023 // report current rate instead of max rate
6024
6025 if (rate_flags & eHAL_TX_RATE_LEGACY)
6026 {
6027 //provide to the UI in units of 100kbps
6028 sinfo->txrate.legacy = myRate;
6029#ifdef LINKSPEED_DEBUG_ENABLED
6030 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6031#endif //LINKSPEED_DEBUG_ENABLED
6032 }
6033 else
6034 {
6035 //must be MCS
6036 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6037 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6038 if (rate_flags & eHAL_TX_RATE_SGI)
6039 {
6040 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6041 }
6042 if (rate_flags & eHAL_TX_RATE_HT40)
6043 {
6044 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6045 }
6046#ifdef LINKSPEED_DEBUG_ENABLED
6047 pr_info("Reporting actual MCS rate %d flags %x\n",
6048 sinfo->txrate.mcs,
6049 sinfo->txrate.flags );
6050#endif //LINKSPEED_DEBUG_ENABLED
6051 }
6052 }
6053 sinfo->filled |= STATION_INFO_TX_BITRATE;
6054
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006055 sinfo->tx_packets =
6056 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6057 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6058 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6059 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6060
6061 sinfo->tx_retries =
6062 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6063 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6064 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6065 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6066
6067 sinfo->tx_failed =
6068 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6069 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6070 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6071 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6072
6073 sinfo->filled |=
6074 STATION_INFO_TX_PACKETS |
6075 STATION_INFO_TX_RETRIES |
6076 STATION_INFO_TX_FAILED;
6077
6078 EXIT();
6079 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006080}
6081
6082static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6083 struct net_device *dev, bool mode, v_SINT_t timeout)
6084{
6085 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6086 VOS_STATUS vos_status;
6087
Jeff Johnsone7245742012-09-05 17:12:55 -07006088 ENTER();
6089
Jeff Johnson295189b2012-06-20 16:38:30 -07006090 if (NULL == pAdapter)
6091 {
6092 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6093 return -ENODEV;
6094 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006095 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6096 {
6097 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6098 "%s:LOGP in Progress. Ignore!!!", __func__);
6099 return -EAGAIN;
6100 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006101
6102 /**The get power cmd from the supplicant gets updated by the nl only
6103 *on successful execution of the function call
6104 *we are oppositely mapped w.r.t mode in the driver
6105 **/
6106 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6107
Jeff Johnsone7245742012-09-05 17:12:55 -07006108 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006109 if (VOS_STATUS_E_FAILURE == vos_status)
6110 {
6111 return -EINVAL;
6112 }
6113 return 0;
6114}
6115
6116
6117#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6118static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6119 struct net_device *netdev,
6120 u8 key_index)
6121{
Jeff Johnsone7245742012-09-05 17:12:55 -07006122 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006123 return 0;
6124}
6125#endif //LINUX_VERSION_CODE
6126
6127#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6128static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6129 struct net_device *dev,
6130 struct ieee80211_txq_params *params)
6131{
Jeff Johnsone7245742012-09-05 17:12:55 -07006132 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006133 return 0;
6134}
6135#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6136static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6137 struct ieee80211_txq_params *params)
6138{
Jeff Johnsone7245742012-09-05 17:12:55 -07006139 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006140 return 0;
6141}
6142#endif //LINUX_VERSION_CODE
6143
6144static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6145 struct net_device *dev, u8 *mac)
6146{
6147 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006148 VOS_STATUS vos_status;
6149 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006150
Jeff Johnsone7245742012-09-05 17:12:55 -07006151 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6153 {
6154 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6155 return -EINVAL;
6156 }
6157
6158 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6159 {
6160 hddLog( LOGE,
6161 "%s: Wlan Load/Unload is in progress", __func__);
6162 return -EBUSY;
6163 }
6164
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006165 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6166 {
6167 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6168 "%s:LOGP in Progress. Ignore!!!", __func__);
6169 return -EAGAIN;
6170 }
6171
Jeff Johnson295189b2012-06-20 16:38:30 -07006172 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6173#ifdef WLAN_FEATURE_P2P
6174 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6175#endif
6176 )
6177 {
6178 if( NULL == mac )
6179 {
6180 v_U16_t i;
6181 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6182 {
6183 if(pAdapter->aStaInfo[i].isUsed)
6184 {
6185 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6186 hddLog(VOS_TRACE_LEVEL_INFO,
6187 "%s: Delete STA with MAC::"
6188 "%02x:%02x:%02x:%02x:%02x:%02x",
6189 __func__,
6190 macAddr[0], macAddr[1], macAddr[2],
6191 macAddr[3], macAddr[4], macAddr[5]);
6192 hdd_softap_sta_deauth(pAdapter, macAddr);
6193 }
6194 }
6195 }
6196 else
6197 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006198
6199 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6200 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6201 {
6202 hddLog(VOS_TRACE_LEVEL_INFO,
6203 "%s: Skip this DEL STA as this is not used::"
6204 "%02x:%02x:%02x:%02x:%02x:%02x",
6205 __func__,
6206 mac[0], mac[1], mac[2],
6207 mac[3], mac[4], mac[5]);
6208 return -ENOENT;
6209 }
6210
6211 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6212 {
6213 hddLog(VOS_TRACE_LEVEL_INFO,
6214 "%s: Skip this DEL STA as deauth is in progress::"
6215 "%02x:%02x:%02x:%02x:%02x:%02x",
6216 __func__,
6217 mac[0], mac[1], mac[2],
6218 mac[3], mac[4], mac[5]);
6219 return -ENOENT;
6220 }
6221
6222 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6223
Jeff Johnson295189b2012-06-20 16:38:30 -07006224 hddLog(VOS_TRACE_LEVEL_INFO,
6225 "%s: Delete STA with MAC::"
6226 "%02x:%02x:%02x:%02x:%02x:%02x",
6227 __func__,
6228 mac[0], mac[1], mac[2],
6229 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006230
6231 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6232 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6233 {
6234 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6235 hddLog(VOS_TRACE_LEVEL_INFO,
6236 "%s: STA removal failed for ::"
6237 "%02x:%02x:%02x:%02x:%02x:%02x",
6238 __func__,
6239 mac[0], mac[1], mac[2],
6240 mac[3], mac[4], mac[5]);
6241 return -ENOENT;
6242 }
6243
Jeff Johnson295189b2012-06-20 16:38:30 -07006244 }
6245 }
6246
6247 EXIT();
6248
6249 return 0;
6250}
6251
6252static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6253 struct net_device *dev, u8 *mac, struct station_parameters *params)
6254{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006255#ifdef FEATURE_WLAN_TDLS
6256 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6257 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6258 u32 mask, set;
6259 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006260 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006261
6262 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6263 {
6264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6265 "Invalid arguments");
6266 return -EINVAL;
6267 }
6268
6269 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6270 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6271 {
6272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6273 "TDLS Disabled in INI OR not enabled in FW.\
6274 Cannot process TDLS commands \n");
6275 return -ENOTSUPP;
6276 }
6277
6278 mask = params->sta_flags_mask;
6279
6280 set = params->sta_flags_set;
6281
6282
6283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6284 "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
6285
6286 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6287 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6289 "Add TDLS peer");
6290
6291
6292 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6293 pAdapter->sessionId, mac);
6294
6295 if (VOS_STATUS_SUCCESS != status) {
6296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6297 "%s: sme_AddTdlsPeerSta failed!", __func__);
6298 }
6299 }
6300 }
6301#endif
6302
Jeff Johnson295189b2012-06-20 16:38:30 -07006303 return 0;
6304}
6305
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006306
6307#ifdef FEATURE_WLAN_LFR
6308static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006309 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006310{
6311#define MAX_PMKSAIDS_IN_CACHE 8
6312 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006313 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006314 tANI_U32 j=0;
6315 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6316 tHalHandle halHandle;
6317 eHalStatus result;
6318 tANI_U8 BSSIDMatched = 0;
6319
Jeff Johnsone7245742012-09-05 17:12:55 -07006320 ENTER();
6321
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006322 // Validate pAdapter
6323 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6324 {
6325 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6326 return -EINVAL;
6327 }
6328
6329 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6330 {
6331 hddLog( LOGE,
6332 "%s: Wlan Load/Unload is in progress", __func__);
6333 return -EBUSY;
6334 }
6335
6336 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6337 {
6338 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6339 "%s:LOGP in Progress. Ignore!!!", __func__);
6340 return -EAGAIN;
6341 }
6342
6343 // Retrieve halHandle
6344 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6345
6346 for (j = 0; j < i; j++)
6347 {
6348 if(vos_mem_compare(PMKIDCache[j].BSSID,
6349 pmksa->bssid, WNI_CFG_BSSID_LEN))
6350 {
6351 /* BSSID matched previous entry. Overwrite it. */
6352 BSSIDMatched = 1;
6353 vos_mem_copy(PMKIDCache[j].BSSID,
6354 pmksa->bssid, WNI_CFG_BSSID_LEN);
6355 vos_mem_copy(PMKIDCache[j].PMKID,
6356 pmksa->pmkid,
6357 CSR_RSN_PMKID_SIZE);
6358 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006359 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006360 dump_bssid(pmksa->bssid);
6361 dump_pmkid(halHandle, pmksa->pmkid);
6362 break;
6363 }
6364 }
6365
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006366 /* Check we compared all entries,if then take the first slot now */
6367 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6368
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006369 if (!BSSIDMatched)
6370 {
6371 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6372 vos_mem_copy(PMKIDCache[i].BSSID,
6373 pmksa->bssid, ETHER_ADDR_LEN);
6374 vos_mem_copy(PMKIDCache[i].PMKID,
6375 pmksa->pmkid,
6376 CSR_RSN_PMKID_SIZE);
6377 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006378 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006379 dump_bssid(pmksa->bssid);
6380 dump_pmkid(halHandle, pmksa->pmkid);
6381 // Increment the HDD Local Cache index
6382 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6383 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6384 }
6385
6386
6387 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6388 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006389 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006390 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006391 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006392 // Finally set the PMKSA ID Cache in CSR
6393 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6394 PMKIDCache,
6395 i );
6396 return 0;
6397}
6398
6399
6400static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006401 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006402{
Jeff Johnsone7245742012-09-05 17:12:55 -07006403 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006404 // TODO: Implement this later.
6405 return 0;
6406}
6407
6408static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6409{
Jeff Johnsone7245742012-09-05 17:12:55 -07006410 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006411 // TODO: Implement this later.
6412 return 0;
6413}
6414#endif
6415
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006416#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6417static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6418 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6419{
6420 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6421 hdd_station_ctx_t *pHddStaCtx;
6422
6423 if (NULL == pAdapter)
6424 {
6425 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6426 return -ENODEV;
6427 }
6428
6429 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6430
6431 // Added for debug on reception of Re-assoc Req.
6432 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6433 {
6434 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6435 ftie->ie_len);
6436 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6437 }
6438
6439#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6440 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6441 ftie->ie_len);
6442#endif
6443
6444 // Pass the received FT IEs to SME
6445 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6446 ftie->ie_len);
6447 return 0;
6448}
6449#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006450
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006451#ifdef FEATURE_WLAN_TDLS
6452static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6453 u8 *peer, u8 action_code, u8 dialog_token,
6454 u16 status_code, const u8 *buf, size_t len)
6455{
6456
6457 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6458 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6459 u8 *buf_1;
6460 size_t len_1 = len;
6461 u8 peerMac[6];
6462 VOS_STATUS status;
6463
6464 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6465 {
6466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6467 "Invalid arguments");
6468 return -EINVAL;
6469 }
6470
6471 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6472 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6473 {
6474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6475 "TDLS Disabled in INI OR not enabled in FW.\
6476 Cannot process TDLS commands \n");
6477 return -ENOTSUPP;
6478 }
6479 vos_mem_copy( peerMac, peer, 6);
6480
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006481#ifdef WLAN_FEATURE_TDLS_DEBUG
6482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6483 "%s: %02x:%02x:%02x:%02x:%02x:%02x) action %d, dialog_token %d status %d, len = %d",
6484 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6485 action_code, dialog_token, status_code, len);
6486#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006487
6488 buf_1 = vos_mem_malloc(len);
6489 if(buf_1 == NULL) {
6490 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6491 "%s: malloc failed!", __func__);
6492 return -ENOMEM;
6493 }
6494 vos_mem_copy(buf_1, buf, len);
6495
6496 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6497 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6498
6499 if (VOS_STATUS_SUCCESS != status) {
6500 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6501 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6502 }
6503
6504 vos_mem_free(buf_1);
6505
6506 return 0;
6507}
6508
6509static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6510 u8 *peer, enum nl80211_tdls_operation oper)
6511{
6512 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6513 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006514#ifdef WLAN_FEATURE_TDLS_DEBUG
6515 const char *tdls_oper_str[]= {
6516 "NL80211_TDLS_DISCOVERY_REQ",
6517 "NL80211_TDLS_SETUP",
6518 "NL80211_TDLS_TEARDOWN",
6519 "NL80211_TDLS_ENABLE_LINK",
6520 "NL80211_TDLS_DISABLE_LINK",
6521 "NL80211_TDLS_UNKONW_OPER"};
6522#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006523
6524 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6525 {
6526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6527 "Invalid arguments");
6528 return -EINVAL;
6529 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006530
6531#ifdef WLAN_FEATURE_TDLS_DEBUG
6532 if((int)oper > 4)
6533 oper = 5;
6534
6535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6536 "%s: %02x:%02x:%02x:%02x:%02x:%02x: %d (%s) ", "tdls_oper",
6537 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5], (int)oper,
6538 tdls_oper_str[(int)oper]);
6539#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006540
6541 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006542 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006543 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006545 "TDLS Disabled in INI OR not enabled in FW.\
6546 Cannot process TDLS commands \n");
6547 return -ENOTSUPP;
6548 }
6549
6550 switch (oper) {
6551 case NL80211_TDLS_ENABLE_LINK:
6552 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006553 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006554 v_U8_t my_peer[6];
6555 v_U8_t ucSTAId;
6556 VOS_STATUS status;
6557
6558 if (peer) {
6559 vos_mem_copy(my_peer, peer, 6);
6560 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6561
6562 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6563 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6564 __func__, peer[0], peer[1],
6565 peer[2], peer[3],
6566 peer[4], peer[5] );
6567
6568 if (-1 == ucSTAId ) {
6569 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
Hoonki Leef63df0d2013-01-16 19:29:14 -08006570 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006571 }
6572
6573 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6574 WLANTL_STA_AUTHENTICATED );
6575
Hoonki Leef63df0d2013-01-16 19:29:14 -08006576 //This can fail only if the staId is not registered yet with TL
6577 //return -EINVAL in such case.
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006578 if (0 != status) {
6579 hddLog(VOS_TRACE_LEVEL_ERROR,
6580 "%s: WLANTL_ChangeSTAState failed, returned %d",
6581 __func__, status);
Hoonki Leef63df0d2013-01-16 19:29:14 -08006582 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006583 }
Hoonki Leef63df0d2013-01-16 19:29:14 -08006584
Chilam NG571c65a2013-01-19 12:27:36 +05306585 wlan_hdd_tdls_set_link_status(peer, eTDLS_LINK_CONNECTED);
6586
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006587 } else {
6588 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6589 }
6590 }
6591 break;
6592 case NL80211_TDLS_DISABLE_LINK:
6593 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6594 pAdapter->sessionId, peer );
6595 return 0;
6596 case NL80211_TDLS_TEARDOWN:
6597 case NL80211_TDLS_SETUP:
6598 case NL80211_TDLS_DISCOVERY_REQ:
6599 /* We don't support in-driver setup/teardown/discovery */
6600 return -ENOTSUPP;
6601 default:
6602 return -ENOTSUPP;
6603 }
6604 return 0;
6605}
Chilam NG571c65a2013-01-19 12:27:36 +05306606
6607int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
6608 struct net_device *dev, u8 *peer)
6609{
6610 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
6611 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6612
6613 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
6614 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
6615}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006616#endif
6617
Jeff Johnson295189b2012-06-20 16:38:30 -07006618/* cfg80211_ops */
6619static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6620{
6621 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6622 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6623 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6624 .change_station = wlan_hdd_change_station,
6625#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6626 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6627 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6628 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006629#else
6630 .start_ap = wlan_hdd_cfg80211_start_ap,
6631 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6632 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006633#endif
6634 .change_bss = wlan_hdd_cfg80211_change_bss,
6635 .add_key = wlan_hdd_cfg80211_add_key,
6636 .get_key = wlan_hdd_cfg80211_get_key,
6637 .del_key = wlan_hdd_cfg80211_del_key,
6638 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006639#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07006640 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006641#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006642 .scan = wlan_hdd_cfg80211_scan,
6643 .connect = wlan_hdd_cfg80211_connect,
6644 .disconnect = wlan_hdd_cfg80211_disconnect,
6645 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6646 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6647 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6648 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6649 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6650#ifdef WLAN_FEATURE_P2P
6651 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6652 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6653 .mgmt_tx = wlan_hdd_action,
6654#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6655 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6656 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6657 .set_txq_params = wlan_hdd_set_txq_params,
6658#endif
6659#endif
6660 .get_station = wlan_hdd_cfg80211_get_station,
6661 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6662 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006663 .add_station = wlan_hdd_cfg80211_add_station,
6664#ifdef FEATURE_WLAN_LFR
6665 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6666 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6667 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6668#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006669#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6670 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6671#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006672#ifdef FEATURE_WLAN_TDLS
6673 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6674 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6675#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006676};
6677
6678#endif // CONFIG_CFG80211