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