blob: 31b3dd6bf8aa1efb19875cad48879f16f0490a08 [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
Lee Hoonkic1262f22013-01-24 21:59:00 -0800141#ifndef WLAN_FEATURE_TDLS_DEBUG
142#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
143#else
144#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
145#endif
146
Jeff Johnson295189b2012-06-20 16:38:30 -0700147static const u32 hdd_cipher_suites[] =
148{
149 WLAN_CIPHER_SUITE_WEP40,
150 WLAN_CIPHER_SUITE_WEP104,
151 WLAN_CIPHER_SUITE_TKIP,
152#ifdef FEATURE_WLAN_CCX
153#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
154 WLAN_CIPHER_SUITE_KRK,
155 WLAN_CIPHER_SUITE_CCMP,
156#else
157 WLAN_CIPHER_SUITE_CCMP,
158#endif
159#ifdef FEATURE_WLAN_WAPI
160 WLAN_CIPHER_SUITE_SMS4,
161#endif
162};
163
164static inline int is_broadcast_ether_addr(const u8 *addr)
165{
166 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
167 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
168}
169
170static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
171{
172 HDD2GHZCHAN(2412, 1, 0) ,
173 HDD2GHZCHAN(2417, 2, 0) ,
174 HDD2GHZCHAN(2422, 3, 0) ,
175 HDD2GHZCHAN(2427, 4, 0) ,
176 HDD2GHZCHAN(2432, 5, 0) ,
177 HDD2GHZCHAN(2437, 6, 0) ,
178 HDD2GHZCHAN(2442, 7, 0) ,
179 HDD2GHZCHAN(2447, 8, 0) ,
180 HDD2GHZCHAN(2452, 9, 0) ,
181 HDD2GHZCHAN(2457, 10, 0) ,
182 HDD2GHZCHAN(2462, 11, 0) ,
183 HDD2GHZCHAN(2467, 12, 0) ,
184 HDD2GHZCHAN(2472, 13, 0) ,
185 HDD2GHZCHAN(2484, 14, 0) ,
186};
187
188#ifdef WLAN_FEATURE_P2P
189static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
190{
191 HDD2GHZCHAN(2412, 1, 0) ,
192 HDD2GHZCHAN(2437, 6, 0) ,
193 HDD2GHZCHAN(2462, 11, 0) ,
194};
195#endif
196
197static struct ieee80211_channel hdd_channels_5_GHZ[] =
198{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700199 HDD5GHZCHAN(4920, 240, 0) ,
200 HDD5GHZCHAN(4940, 244, 0) ,
201 HDD5GHZCHAN(4960, 248, 0) ,
202 HDD5GHZCHAN(4980, 252, 0) ,
203 HDD5GHZCHAN(5040, 208, 0) ,
204 HDD5GHZCHAN(5060, 212, 0) ,
205 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700206 HDD5GHZCHAN(5180, 36, 0) ,
207 HDD5GHZCHAN(5200, 40, 0) ,
208 HDD5GHZCHAN(5220, 44, 0) ,
209 HDD5GHZCHAN(5240, 48, 0) ,
210 HDD5GHZCHAN(5260, 52, 0) ,
211 HDD5GHZCHAN(5280, 56, 0) ,
212 HDD5GHZCHAN(5300, 60, 0) ,
213 HDD5GHZCHAN(5320, 64, 0) ,
214 HDD5GHZCHAN(5500,100, 0) ,
215 HDD5GHZCHAN(5520,104, 0) ,
216 HDD5GHZCHAN(5540,108, 0) ,
217 HDD5GHZCHAN(5560,112, 0) ,
218 HDD5GHZCHAN(5580,116, 0) ,
219 HDD5GHZCHAN(5600,120, 0) ,
220 HDD5GHZCHAN(5620,124, 0) ,
221 HDD5GHZCHAN(5640,128, 0) ,
222 HDD5GHZCHAN(5660,132, 0) ,
223 HDD5GHZCHAN(5680,136, 0) ,
224 HDD5GHZCHAN(5700,140, 0) ,
225 HDD5GHZCHAN(5745,149, 0) ,
226 HDD5GHZCHAN(5765,153, 0) ,
227 HDD5GHZCHAN(5785,157, 0) ,
228 HDD5GHZCHAN(5805,161, 0) ,
229 HDD5GHZCHAN(5825,165, 0) ,
230};
231
232static struct ieee80211_rate g_mode_rates[] =
233{
234 HDD_G_MODE_RATETAB(10, 0x1, 0),
235 HDD_G_MODE_RATETAB(20, 0x2, 0),
236 HDD_G_MODE_RATETAB(55, 0x4, 0),
237 HDD_G_MODE_RATETAB(110, 0x8, 0),
238 HDD_G_MODE_RATETAB(60, 0x10, 0),
239 HDD_G_MODE_RATETAB(90, 0x20, 0),
240 HDD_G_MODE_RATETAB(120, 0x40, 0),
241 HDD_G_MODE_RATETAB(180, 0x80, 0),
242 HDD_G_MODE_RATETAB(240, 0x100, 0),
243 HDD_G_MODE_RATETAB(360, 0x200, 0),
244 HDD_G_MODE_RATETAB(480, 0x400, 0),
245 HDD_G_MODE_RATETAB(540, 0x800, 0),
246};
247
248static struct ieee80211_rate a_mode_rates[] =
249{
250 HDD_G_MODE_RATETAB(60, 0x10, 0),
251 HDD_G_MODE_RATETAB(90, 0x20, 0),
252 HDD_G_MODE_RATETAB(120, 0x40, 0),
253 HDD_G_MODE_RATETAB(180, 0x80, 0),
254 HDD_G_MODE_RATETAB(240, 0x100, 0),
255 HDD_G_MODE_RATETAB(360, 0x200, 0),
256 HDD_G_MODE_RATETAB(480, 0x400, 0),
257 HDD_G_MODE_RATETAB(540, 0x800, 0),
258};
259
260static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
261{
262 .channels = hdd_channels_2_4_GHZ,
263 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
264 .band = IEEE80211_BAND_2GHZ,
265 .bitrates = g_mode_rates,
266 .n_bitrates = g_mode_rates_size,
267 .ht_cap.ht_supported = 1,
268 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
269 | IEEE80211_HT_CAP_GRN_FLD
270 | IEEE80211_HT_CAP_DSSSCCK40
271 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
272 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
273 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
274 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
275 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
276 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
277};
278
279#ifdef WLAN_FEATURE_P2P
280static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
281{
282 .channels = hdd_social_channels_2_4_GHZ,
283 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
284 .band = IEEE80211_BAND_2GHZ,
285 .bitrates = g_mode_rates,
286 .n_bitrates = g_mode_rates_size,
287 .ht_cap.ht_supported = 1,
288 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
289 | IEEE80211_HT_CAP_GRN_FLD
290 | IEEE80211_HT_CAP_DSSSCCK40
291 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
292 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
293 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
294 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
295 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
296 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
297};
298#endif
299
300static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
301{
302 .channels = hdd_channels_5_GHZ,
303 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
304 .band = IEEE80211_BAND_5GHZ,
305 .bitrates = a_mode_rates,
306 .n_bitrates = a_mode_rates_size,
307 .ht_cap.ht_supported = 1,
308 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
309 | IEEE80211_HT_CAP_GRN_FLD
310 | IEEE80211_HT_CAP_DSSSCCK40
311 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
312 | IEEE80211_HT_CAP_SGI_40
313 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
314 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
315 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
316 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
317 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
318 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
319};
320
321/* This structure contain information what kind of frame are expected in
322 TX/RX direction for each kind of interface */
323static const struct ieee80211_txrx_stypes
324wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
325 [NL80211_IFTYPE_STATION] = {
326 .tx = 0xffff,
327 .rx = BIT(SIR_MAC_MGMT_ACTION) |
328 BIT(SIR_MAC_MGMT_PROBE_REQ),
329 },
330 [NL80211_IFTYPE_AP] = {
331 .tx = 0xffff,
332 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
333 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
334 BIT(SIR_MAC_MGMT_PROBE_REQ) |
335 BIT(SIR_MAC_MGMT_DISASSOC) |
336 BIT(SIR_MAC_MGMT_AUTH) |
337 BIT(SIR_MAC_MGMT_DEAUTH) |
338 BIT(SIR_MAC_MGMT_ACTION),
339 },
340#ifdef WLAN_FEATURE_P2P
341 [NL80211_IFTYPE_P2P_CLIENT] = {
342 .tx = 0xffff,
343 .rx = BIT(SIR_MAC_MGMT_ACTION) |
344 BIT(SIR_MAC_MGMT_PROBE_REQ),
345 },
346 [NL80211_IFTYPE_P2P_GO] = {
347 /* This is also same as for SoftAP */
348 .tx = 0xffff,
349 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
350 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
351 BIT(SIR_MAC_MGMT_PROBE_REQ) |
352 BIT(SIR_MAC_MGMT_DISASSOC) |
353 BIT(SIR_MAC_MGMT_AUTH) |
354 BIT(SIR_MAC_MGMT_DEAUTH) |
355 BIT(SIR_MAC_MGMT_ACTION),
356 },
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800357#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700358};
359
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800360#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
361#ifdef WLAN_FEATURE_P2P
362static const struct ieee80211_iface_limit
363wlan_hdd_iface_limit[] = {
364 {
365 /* max=2 is to support JellyBean architecture which has wlan0
366 * and p2p0 interfaces during init. p2p0 is considered station
367 * interface until a group is formed */
368 .max = 2,
369 .types = BIT(NL80211_IFTYPE_STATION),
370 },
371 {
372 .max = 1,
373 .types = BIT(NL80211_IFTYPE_AP),
374 },
375 {
376 .max = 1,
377 .types = BIT(NL80211_IFTYPE_P2P_GO) |
378 BIT(NL80211_IFTYPE_P2P_CLIENT),
379 },
380};
381
382/* By default, only single channel concurrency is allowed */
383static struct ieee80211_iface_combination
384wlan_hdd_iface_combination = {
385 .limits = wlan_hdd_iface_limit,
386 .num_different_channels = 1,
387 .max_interfaces = 2,
388 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
389 .beacon_int_infra_match = false,
390};
391#endif
392#endif
393
Jeff Johnson295189b2012-06-20 16:38:30 -0700394static struct cfg80211_ops wlan_hdd_cfg80211_ops;
395
396/* Data rate 100KBPS based on IE Index */
397struct index_data_rate_type
398{
399 v_U8_t beacon_rate_index;
400 v_U16_t supported_rate[4];
401};
402
403/* 11B, 11G Rate table include Basic rate and Extended rate
404 The IDX field is the rate index
405 The HI field is the rate when RSSI is strong or being ignored
406 (in this case we report actual rate)
407 The MID field is the rate when RSSI is moderate
408 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
409 The LO field is the rate when RSSI is low
410 (in this case we don't report rates, actual current rate used)
411 */
412static const struct
413{
414 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700415 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700416} supported_data_rate[] =
417{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700418/* IDX HI HM LM LO (RSSI-based index */
419 {2, { 10, 10, 10, 0}},
420 {4, { 20, 20, 10, 0}},
421 {11, { 55, 20, 10, 0}},
422 {12, { 60, 55, 20, 0}},
423 {18, { 90, 55, 20, 0}},
424 {22, {110, 55, 20, 0}},
425 {24, {120, 90, 60, 0}},
426 {36, {180, 120, 60, 0}},
427 {44, {220, 180, 60, 0}},
428 {48, {240, 180, 90, 0}},
429 {66, {330, 180, 90, 0}},
430 {72, {360, 240, 90, 0}},
431 {96, {480, 240, 120, 0}},
432 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700433};
434
435/* MCS Based rate table */
436static struct index_data_rate_type supported_mcs_rate[] =
437{
438/* MCS L20 L40 S20 S40 */
439 {0, {65, 135, 72, 150}},
440 {1, {130, 270, 144, 300}},
441 {2, {195, 405, 217, 450}},
442 {3, {260, 540, 289, 600}},
443 {4, {390, 810, 433, 900}},
444 {5, {520, 1080, 578, 1200}},
445 {6, {585, 1215, 650, 1350}},
446 {7, {650, 1350, 722, 1500}}
447};
448
449extern struct net_device_ops net_ops_struct;
450
451/*
452 * FUNCTION: wlan_hdd_cfg80211_init
453 * This function is called by hdd_wlan_startup()
454 * during initialization.
455 * This function is used to initialize and register wiphy structure.
456 */
457struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
458{
459 struct wiphy *wiphy;
460 ENTER();
461
462 /*
463 * Create wiphy device
464 */
465 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
466
467 if (!wiphy)
468 {
469 /* Print error and jump into err label and free the memory */
470 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
471 return NULL;
472 }
473
474 return wiphy;
475}
476
477/*
478 * FUNCTION: wlan_hdd_cfg80211_update_band
479 * This function is called from the supplicant through a
480 * private ioctl to change the band value
481 */
482int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
483{
Jeff Johnsone7245742012-09-05 17:12:55 -0700484 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700485 switch(eBand)
486 {
487 case eCSR_BAND_24:
488 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
489 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
490 break;
491 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700492#ifdef WLAN_FEATURE_P2P
493 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
494#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700495 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700496#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700497 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
498 break;
499 case eCSR_BAND_ALL:
500 default:
501 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
502 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
503 }
504 return 0;
505}
506/*
507 * FUNCTION: wlan_hdd_cfg80211_init
508 * This function is called by hdd_wlan_startup()
509 * during initialization.
510 * This function is used to initialize and register wiphy structure.
511 */
512int wlan_hdd_cfg80211_register(struct device *dev,
513 struct wiphy *wiphy,
514 hdd_config_t *pCfg
515 )
516{
Jeff Johnsone7245742012-09-05 17:12:55 -0700517 ENTER();
518
Jeff Johnson295189b2012-06-20 16:38:30 -0700519 /* Now bind the underlying wlan device with wiphy */
520 set_wiphy_dev(wiphy, dev);
521
522 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
523
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700524 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700525
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700526#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700527 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
528 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
529 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700530 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700531#endif
James Zmuda77fb5ae2013-01-29 08:00:17 -0800532#ifdef FEATURE_WLAN_LFR
533 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
534#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800535#ifdef FEATURE_WLAN_TDLS
536 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
537 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
538#endif
539
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700540 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
541 driver can still register regulatory callback and
542 it will get CRDA setting in wiphy->band[], but
543 driver need to determine what to do with both
544 regulatory settings */
545 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700546
Jeff Johnson295189b2012-06-20 16:38:30 -0700547 wiphy->max_scan_ssids = MAX_SCAN_SSID;
548
549 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
550
551 /* Supports STATION & AD-HOC modes right now */
552 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
553 | BIT(NL80211_IFTYPE_ADHOC)
554#ifdef WLAN_FEATURE_P2P
555 | BIT(NL80211_IFTYPE_P2P_CLIENT)
556 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800557#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 | BIT(NL80211_IFTYPE_AP);
559
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800560#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
561#ifdef WLAN_FEATURE_P2P
562 if( pCfg->enableMCC )
563 {
564 /* Currently, supports up to two channels */
565 wlan_hdd_iface_combination.num_different_channels = 2;
566
567 if( !pCfg->allowMCCGODiffBI )
568 wlan_hdd_iface_combination.beacon_int_infra_match = true;
569
570 }
571 wiphy->iface_combinations = &wlan_hdd_iface_combination;
572 wiphy->n_iface_combinations = 1;
573#endif
574#endif
575
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 /* Before registering we need to update the ht capabilitied based
577 * on ini values*/
578 if( !pCfg->ShortGI20MhzEnable )
579 {
580 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
581 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
582 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
583 }
584
585 if( !pCfg->ShortGI40MhzEnable )
586 {
587 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
588 }
589
590 if( !pCfg->nChannelBondingMode5GHz )
591 {
592 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
593 }
594
595 /*Initialize band capability*/
596 switch(pCfg->nBandCapability)
597 {
598 case eCSR_BAND_24:
599 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
600 break;
601 case eCSR_BAND_5G:
602#ifdef WLAN_FEATURE_P2P
603 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
604#endif
605 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
606 break;
607 case eCSR_BAND_ALL:
608 default:
609 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
610 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
611 }
612 /*Initialise the supported cipher suite details*/
613 wiphy->cipher_suites = hdd_cipher_suites;
614 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
615
616 /*signal strength in mBm (100*dBm) */
617 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
618
619#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
620#ifdef WLAN_FEATURE_P2P
621 wiphy->max_remain_on_channel_duration = 1000;
622#endif
623#endif
624
625 /* Register our wiphy dev with cfg80211 */
626 if (0 > wiphy_register(wiphy))
627 {
628 /* print eror */
629 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
630 return -EIO;
631 }
632
633 EXIT();
634 return 0;
635}
636
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700637/* In this function we will try to get default country code from crda.
638 If the gCrdaDefaultCountryCode is configured in ini file,
639 we will try to call user space crda to get the regulatory settings for
640 that country. We will timeout if we can't get it from crda.
641 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
642*/
643int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
644{
645 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
646 if (memcmp(pCfg->crdaDefaultCountryCode,
647 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
648 {
649 init_completion(&pHddCtx->driver_crda_req);
650 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
651 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
652 CRDA_WAIT_TIME);
653 }
654 return 0;
655}
656
Jeff Johnson295189b2012-06-20 16:38:30 -0700657/* In this function we will do all post VOS start initialization.
658 In this function we will register for all frame in which supplicant
659 is interested.
660*/
661void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
662{
663#ifdef WLAN_FEATURE_P2P
664 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
665 /* Register for all P2P action, public action etc frames */
666 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
667
Jeff Johnsone7245742012-09-05 17:12:55 -0700668 ENTER();
669
Jeff Johnson295189b2012-06-20 16:38:30 -0700670 /* Right now we are registering these frame when driver is getting
671 initialized. Once we will move to 2.6.37 kernel, in which we have
672 frame register ops, we will move this code as a part of that */
673 /* GAS Initial Request */
674 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
675 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
676
677 /* GAS Initial Response */
678 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
679 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
680
681 /* GAS Comeback Request */
682 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
683 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
684
685 /* GAS Comeback Response */
686 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
687 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
688
689 /* P2P Public Action */
690 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
691 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
692 P2P_PUBLIC_ACTION_FRAME_SIZE );
693
694 /* P2P Action */
695 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
696 (v_U8_t*)P2P_ACTION_FRAME,
697 P2P_ACTION_FRAME_SIZE );
698#endif /* WLAN_FEATURE_P2P */
699}
700
701void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
702{
703#ifdef WLAN_FEATURE_P2P
704 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
705 /* Register for all P2P action, public action etc frames */
706 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
707
Jeff Johnsone7245742012-09-05 17:12:55 -0700708 ENTER();
709
Jeff Johnson295189b2012-06-20 16:38:30 -0700710 /* Right now we are registering these frame when driver is getting
711 initialized. Once we will move to 2.6.37 kernel, in which we have
712 frame register ops, we will move this code as a part of that */
713 /* GAS Initial Request */
714
715 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
716 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
717
718 /* GAS Initial Response */
719 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
720 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
721
722 /* GAS Comeback Request */
723 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
724 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
725
726 /* GAS Comeback Response */
727 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
728 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
729
730 /* P2P Public Action */
731 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
732 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
733 P2P_PUBLIC_ACTION_FRAME_SIZE );
734
735 /* P2P Action */
736 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
737 (v_U8_t*)P2P_ACTION_FRAME,
738 P2P_ACTION_FRAME_SIZE );
739#endif /* WLAN_FEATURE_P2P */
740}
741
742#ifdef FEATURE_WLAN_WAPI
743void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
744 const u8 *mac_addr, u8 *key , int key_Len)
745{
746 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
747 tCsrRoamSetKey setKey;
748 v_BOOL_t isConnected = TRUE;
749 int status = 0;
750 v_U32_t roamId= 0xFF;
751 tANI_U8 *pKeyPtr = NULL;
752 int n = 0;
753
754 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
755 __func__,pAdapter->device_mode);
756
757 setKey.keyId = key_index; // Store Key ID
758 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
759 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
760 setKey.paeRole = 0 ; // the PAE role
761 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
762 {
763 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
764 }
765 else
766 {
767 isConnected = hdd_connIsConnected(pHddStaCtx);
768 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
769 }
770 setKey.keyLength = key_Len;
771 pKeyPtr = setKey.Key;
772 memcpy( pKeyPtr, key, key_Len);
773
774 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
775 __func__, key_Len);
776 for (n = 0 ; n < key_Len; n++)
777 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
778 __func__,n,setKey.Key[n]);
779
780 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
781 if ( isConnected )
782 {
783 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
784 pAdapter->sessionId, &setKey, &roamId );
785 }
786 if ( status != 0 )
787 {
788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
789 "[%4d] sme_RoamSetKey returned ERROR status= %d",
790 __LINE__, status );
791 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
792 }
793}
794#endif /* FEATURE_WLAN_WAPI*/
795
796#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
797int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
798 beacon_data_t **ppBeacon,
799 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700800#else
801int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
802 beacon_data_t **ppBeacon,
803 struct cfg80211_beacon_data *params,
804 int dtim_period)
805#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700806{
807 int size;
808 beacon_data_t *beacon = NULL;
809 beacon_data_t *old = NULL;
810 int head_len,tail_len;
811
Jeff Johnsone7245742012-09-05 17:12:55 -0700812 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700813 if (params->head && !params->head_len)
814 return -EINVAL;
815
816 old = pAdapter->sessionCtx.ap.beacon;
817
818 if (!params->head && !old)
819 return -EINVAL;
820
821 if (params->tail && !params->tail_len)
822 return -EINVAL;
823
824#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
825 /* Kernel 3.0 is not updating dtim_period for set beacon */
826 if (!params->dtim_period)
827 return -EINVAL;
828#endif
829
830 if(params->head)
831 head_len = params->head_len;
832 else
833 head_len = old->head_len;
834
835 if(params->tail || !old)
836 tail_len = params->tail_len;
837 else
838 tail_len = old->tail_len;
839
840 size = sizeof(beacon_data_t) + head_len + tail_len;
841
842 beacon = kzalloc(size, GFP_KERNEL);
843
844 if( beacon == NULL )
845 return -ENOMEM;
846
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700847#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700848 if(params->dtim_period || !old )
849 beacon->dtim_period = params->dtim_period;
850 else
851 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700852#else
853 if(dtim_period || !old )
854 beacon->dtim_period = dtim_period;
855 else
856 beacon->dtim_period = old->dtim_period;
857#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700858
859 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
860 beacon->tail = beacon->head + head_len;
861 beacon->head_len = head_len;
862 beacon->tail_len = tail_len;
863
864 if(params->head) {
865 memcpy (beacon->head,params->head,beacon->head_len);
866 }
867 else {
868 if(old)
869 memcpy (beacon->head,old->head,beacon->head_len);
870 }
871
872 if(params->tail) {
873 memcpy (beacon->tail,params->tail,beacon->tail_len);
874 }
875 else {
876 if(old)
877 memcpy (beacon->tail,old->tail,beacon->tail_len);
878 }
879
880 *ppBeacon = beacon;
881
882 kfree(old);
883
884 return 0;
885
886}
Jeff Johnson295189b2012-06-20 16:38:30 -0700887
888v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
889{
890 int left = length;
891 v_U8_t *ptr = pIes;
892 v_U8_t elem_id,elem_len;
893
894 while(left >= 2)
895 {
896 elem_id = ptr[0];
897 elem_len = ptr[1];
898 left -= 2;
899 if(elem_len > left)
900 {
901 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700902 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 eid,elem_len,left);
904 return NULL;
905 }
906 if (elem_id == eid)
907 {
908 return ptr;
909 }
910
911 left -= elem_len;
912 ptr += (elem_len + 2);
913 }
914 return NULL;
915}
916
Jeff Johnson295189b2012-06-20 16:38:30 -0700917/* Check if rate is 11g rate or not */
918static int wlan_hdd_rate_is_11g(u8 rate)
919{
920 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
921 u8 i;
922 for (i = 0; i < 8; i++)
923 {
924 if(rate == gRateArray[i])
925 return TRUE;
926 }
927 return FALSE;
928}
929
930/* Check for 11g rate and set proper 11g only mode */
931static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
932 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
933{
934 u8 i, num_rates = pIe[0];
935
936 pIe += 1;
937 for ( i = 0; i < num_rates; i++)
938 {
939 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
940 {
941 /* If rate set have 11g rate than change the mode to 11G */
942 *pSapHw_mode = eSAP_DOT11_MODE_11g;
943 if (pIe[i] & BASIC_RATE_MASK)
944 {
945 /* If we have 11g rate as basic rate, it means mode
946 is 11g only mode.
947 */
948 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
949 *pCheckRatesfor11g = FALSE;
950 }
951 }
952 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
953 {
954 *require_ht = TRUE;
955 }
956 }
957 return;
958}
959
960static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
961{
962 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
963 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
964 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
965 u8 checkRatesfor11g = TRUE;
966 u8 require_ht = FALSE;
967 u8 *pIe=NULL;
968
969 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
970
971 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
972 pBeacon->head_len, WLAN_EID_SUPP_RATES);
973 if (pIe != NULL)
974 {
975 pIe += 1;
976 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
977 &pConfig->SapHw_mode);
978 }
979
980 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
981 WLAN_EID_EXT_SUPP_RATES);
982 if (pIe != NULL)
983 {
984
985 pIe += 1;
986 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
987 &pConfig->SapHw_mode);
988 }
989
990 if( pConfig->channel > 14 )
991 {
992 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
993 }
994
995 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
996 WLAN_EID_HT_CAPABILITY);
997
998 if(pIe)
999 {
1000 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1001 if(require_ht)
1002 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1003 }
1004}
1005
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001006#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001007static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1008 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001009#else
1010static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1011 struct cfg80211_beacon_data *params)
1012#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001013{
1014 v_U8_t *genie;
1015 v_U8_t total_ielen = 0, ielen = 0;
1016 v_U8_t *pIe = NULL;
1017 v_U8_t addIE[1] = {0};
1018 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -07001019 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001020
1021 genie = vos_mem_malloc(MAX_GENIE_LEN);
1022
1023 if(genie == NULL) {
1024
1025 return -ENOMEM;
1026 }
1027
1028 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1029
1030 if(pIe)
1031 {
1032 /*Copy the wps IE*/
1033 ielen = pIe[1] + 2;
1034 if( ielen <=MAX_GENIE_LEN)
1035 {
1036 vos_mem_copy(genie, pIe, ielen);
1037 }
1038 else
1039 {
1040 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001041 ret = -EINVAL;
1042 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001043 }
1044 total_ielen = ielen;
1045 }
1046
1047#ifdef WLAN_FEATURE_WFD
1048 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1049
1050 if(pIe)
1051 {
1052 ielen = pIe[1] + 2;
1053 if(total_ielen + ielen <= MAX_GENIE_LEN) {
1054 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
1055 }
1056 else {
1057 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001058 ret = -EINVAL;
1059 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001060 }
1061 total_ielen += ielen;
1062 }
1063#endif
1064
1065#ifdef WLAN_FEATURE_P2P
1066 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1067
1068 if(pIe)
1069 {
1070 ielen = pIe[1] + 2;
1071 if(total_ielen + ielen <= MAX_GENIE_LEN)
1072 {
1073 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1074 }
1075 else
1076 {
1077 hddLog( VOS_TRACE_LEVEL_ERROR,
1078 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001079 ret = -EINVAL;
1080 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001081 }
1082 total_ielen += ielen;
1083 }
1084#endif
1085
1086 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1087 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1088 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1089 {
1090 hddLog(LOGE,
1091 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001092 ret = -EINVAL;
1093 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001094 }
1095
1096 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1097 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1098 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1099 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1100 ==eHAL_STATUS_FAILURE)
1101 {
1102 hddLog(LOGE,
1103 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001104 ret = -EINVAL;
1105 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 }
1107
1108 // Added for ProResp IE
1109 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1110 {
1111 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1112 u8 probe_rsp_ie_len[3] = {0};
1113 u8 counter = 0;
1114 /* Check Probe Resp Length if it is greater then 255 then Store
1115 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1116 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1117 Store More then 255 bytes into One Variable.
1118 */
1119 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1120 {
1121 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1122 {
1123 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1124 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1125 }
1126 else
1127 {
1128 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1129 rem_probe_resp_ie_len = 0;
1130 }
1131 }
1132
1133 rem_probe_resp_ie_len = 0;
1134
1135 if (probe_rsp_ie_len[0] > 0)
1136 {
1137 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1138 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1139 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1140 probe_rsp_ie_len[0], NULL,
1141 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1142 {
1143 hddLog(LOGE,
1144 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001145 ret = -EINVAL;
1146 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001147 }
1148 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1149 }
1150
1151 if (probe_rsp_ie_len[1] > 0)
1152 {
1153 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1154 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1155 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1156 probe_rsp_ie_len[1], NULL,
1157 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1158 {
1159 hddLog(LOGE,
1160 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001161 ret = -EINVAL;
1162 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 }
1164 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1165 }
1166
1167 if (probe_rsp_ie_len[2] > 0)
1168 {
1169 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1170 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1171 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1172 probe_rsp_ie_len[2], NULL,
1173 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1174 {
1175 hddLog(LOGE,
1176 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001177 ret = -EINVAL;
1178 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 }
1180 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1181 }
1182
1183 if (probe_rsp_ie_len[1] == 0 )
1184 {
1185 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1186 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1187 eANI_BOOLEAN_FALSE) )
1188 {
1189 hddLog(LOGE,
1190 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1191 }
1192 }
1193
1194 if (probe_rsp_ie_len[2] == 0 )
1195 {
1196 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1197 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1198 eANI_BOOLEAN_FALSE) )
1199 {
1200 hddLog(LOGE,
1201 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1202 }
1203 }
1204
1205 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1206 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1207 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1208 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1209 == eHAL_STATUS_FAILURE)
1210 {
1211 hddLog(LOGE,
1212 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001213 ret = -EINVAL;
1214 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001215 }
1216 }
1217 else
1218 {
1219 // Reset WNI_CFG_PROBE_RSP Flags
1220 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1221
1222 hddLog(VOS_TRACE_LEVEL_INFO,
1223 "%s: No Probe Response IE received in set beacon",
1224 __func__);
1225 }
1226
1227 // Added for AssocResp IE
1228 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1229 {
1230 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1231 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1232 params->assocresp_ies_len, NULL,
1233 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1234 {
1235 hddLog(LOGE,
1236 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001237 ret = -EINVAL;
1238 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001239 }
1240
1241 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1242 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1243 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1244 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1245 == eHAL_STATUS_FAILURE)
1246 {
1247 hddLog(LOGE,
1248 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001249 ret = -EINVAL;
1250 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001251 }
1252 }
1253 else
1254 {
1255 hddLog(VOS_TRACE_LEVEL_INFO,
1256 "%s: No Assoc Response IE received in set beacon",
1257 __func__);
1258
1259 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1260 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1261 eANI_BOOLEAN_FALSE) )
1262 {
1263 hddLog(LOGE,
1264 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1265 }
1266 }
1267
Jeff Johnsone7245742012-09-05 17:12:55 -07001268done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001269 vos_mem_free(genie);
1270 return 0;
1271}
Jeff Johnson295189b2012-06-20 16:38:30 -07001272
1273/*
1274 * FUNCTION: wlan_hdd_validate_operation_channel
1275 * called by wlan_hdd_cfg80211_start_bss() and
1276 * wlan_hdd_cfg80211_set_channel()
1277 * This function validates whether given channel is part of valid
1278 * channel list.
1279 */
1280static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1281{
1282
1283 v_U32_t num_ch = 0;
1284 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1285 u32 indx = 0;
1286 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1287
1288 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1289
1290 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1291 valid_ch, &num_ch))
1292 {
1293 hddLog(VOS_TRACE_LEVEL_ERROR,
1294 "%s: failed to get valid channel list\n", __func__);
1295 return VOS_STATUS_E_FAILURE;
1296 }
1297
1298 for (indx = 0; indx < num_ch; indx++)
1299 {
1300 if (channel == valid_ch[indx])
1301 {
1302 break;
1303 }
1304 }
1305
1306 if (indx >= num_ch)
1307 {
1308 hddLog(VOS_TRACE_LEVEL_ERROR,
1309 "%s: Invalid Channel [%d] \n", __func__, channel);
1310 return VOS_STATUS_E_FAILURE;
1311 }
1312 return VOS_STATUS_SUCCESS;
1313
1314}
1315
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301316/*
1317 * FUNCTION: wlan_hdd_select_cbmode
1318 * called by wlan_hdd_cfg80211_start_bss() and
1319 * This function selects the cbmode based on primary channel
1320 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001321VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301322{
1323 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001324 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1325 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1326
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301327 if(
1328#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001329 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1330 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301331#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001332 SapHw_mode != eSAP_DOT11_MODE_11n &&
1333 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301334 )
1335 {
1336 return VOS_STATUS_SUCCESS;
1337 }
1338
1339 if (!pConfigIni->nChannelBondingMode5GHz) {
1340 return VOS_STATUS_SUCCESS;
1341 }
1342
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001343 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301344 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1345
1346 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1347
1348#ifdef WLAN_FEATURE_11AC
1349
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001350 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1351 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301352 {
1353 if ( channel== 36 || channel == 52 || channel == 100 ||
1354 channel == 116 || channel == 149 )
1355 {
1356 smeConfig.csrConfig.channelBondingMode5GHz =
1357 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1358 }
1359 else if ( channel == 40 || channel == 56 || channel == 104 ||
1360 channel == 120 || channel == 153 )
1361 {
1362 smeConfig.csrConfig.channelBondingMode5GHz =
1363 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1364 }
1365 else if ( channel == 44 || channel == 60 || channel == 108 ||
1366 channel == 124 || channel == 157 )
1367 {
1368 smeConfig.csrConfig.channelBondingMode5GHz =
1369 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1370 }
1371 else if ( channel == 48 || channel == 64 || channel == 112 ||
1372 channel == 128 || channel == 161 )
1373 {
1374 smeConfig.csrConfig.channelBondingMode5GHz =
1375 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1376 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301377 }
1378#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001379 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1380 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301381 {
1382 if ( channel== 40 || channel == 48 || channel == 56 ||
1383 channel == 64 || channel == 104 || channel == 112 ||
1384 channel == 120 || channel == 128 || channel == 136 ||
1385 channel == 144 || channel == 153 || channel == 161 )
1386 {
1387 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1388 }
1389 else if ( channel== 36 || channel == 44 || channel == 52 ||
1390 channel == 60 || channel == 100 || channel == 108 ||
1391 channel == 116 || channel == 124 || channel == 132 ||
1392 channel == 140 || channel == 149 || channel == 157 )
1393 {
1394 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1395 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301396 }
1397 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1398
1399 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1400 return VOS_STATUS_SUCCESS;
1401}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001402
Jeff Johnson295189b2012-06-20 16:38:30 -07001403#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1404static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1405 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001406#else
1407static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1408 struct cfg80211_beacon_data *params,
1409 const u8 *ssid, size_t ssid_len,
1410 enum nl80211_hidden_ssid hidden_ssid)
1411#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001412{
1413 tsap_Config_t *pConfig;
1414 beacon_data_t *pBeacon = NULL;
1415 struct ieee80211_mgmt *pMgmt_frame;
1416 v_U8_t *pIe=NULL;
1417 v_U16_t capab_info;
1418 eCsrAuthType RSNAuthType;
1419 eCsrEncryptionType RSNEncryptType;
1420 eCsrEncryptionType mcRSNEncryptType;
1421 int status = VOS_STATUS_SUCCESS;
1422 tpWLAN_SAPEventCB pSapEventCallback;
1423 hdd_hostapd_state_t *pHostapdState;
1424 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1425 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1426 struct qc_mac_acl_entry *acl_entry = NULL;
1427 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001428 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001429
1430 ENTER();
1431
1432 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1433
1434 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1435
1436 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1437
1438 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1439
1440 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1441
1442 //channel is already set in the set_channel Call back
1443 //pConfig->channel = pCommitConfig->channel;
1444
1445 /*Protection parameter to enable or disable*/
1446 pConfig->protEnabled =
1447 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1448
1449 pConfig->dtim_period = pBeacon->dtim_period;
1450
1451 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1452 pConfig->dtim_period);
1453
1454
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001455 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001456 {
1457 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001458 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001459 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001460 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001461 tANI_BOOLEAN restartNeeded;
1462 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1463 pConfig->ieee80211d = 1;
1464 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1465 sme_setRegInfo(hHal, pConfig->countryCode);
1466 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1467 /*
1468 * If auto channel is configured i.e. channel is 0,
1469 * so skip channel validation.
1470 */
1471 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001472 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001473 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1474 {
1475 hddLog(VOS_TRACE_LEVEL_ERROR,
1476 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1477 return -EINVAL;
1478 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001479 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001480 /*
1481 * Validate the given channel range for the given country code
1482 */
1483 else
1484 {
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001485 if(1 != pHddCtx->is_dynamic_channel_range_set)
Ng Chilamfc416462012-12-27 17:26:52 -08001486 {
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001487 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001488 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
Ng Chilamfc416462012-12-27 17:26:52 -08001489 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001490 }
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001491
Ng Chilamfc416462012-12-27 17:26:52 -08001492 pHddCtx->is_dynamic_channel_range_set = 0;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001493 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001494 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001495 else
1496 {
1497 pConfig->ieee80211d = 0;
1498 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001499 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001500 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001501 {
1502 pConfig->ieee80211d = 0;
1503 }
1504 pConfig->authType = eSAP_AUTO_SWITCH;
1505
1506 capab_info = pMgmt_frame->u.beacon.capab_info;
1507
1508 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1509 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1510
1511 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1512
1513 /*Set wps station to configured*/
1514 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1515
1516 if(pIe)
1517 {
1518 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1519 {
1520 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1521 return -EINVAL;
1522 }
1523 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1524 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001525 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001526 /* Check 15 bit of WPS IE as it contain information for wps state
1527 * WPS state
1528 */
1529 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1530 {
1531 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1532 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1533 {
1534 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1535 }
1536 }
1537 }
1538 else
1539 {
1540 pConfig->wps_state = SAP_WPS_DISABLED;
1541 }
1542 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1543
1544 pConfig->RSNWPAReqIELength = 0;
1545 pConfig->pRSNWPAReqIE = NULL;
1546 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1547 WLAN_EID_RSN);
1548 if(pIe && pIe[1])
1549 {
1550 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1551 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1552 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1553 /* The actual processing may eventually be more extensive than
1554 * this. Right now, just consume any PMKIDs that are sent in
1555 * by the app.
1556 * */
1557 status = hdd_softap_unpackIE(
1558 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1559 &RSNEncryptType,
1560 &mcRSNEncryptType,
1561 &RSNAuthType,
1562 pConfig->pRSNWPAReqIE[1]+2,
1563 pConfig->pRSNWPAReqIE );
1564
1565 if( VOS_STATUS_SUCCESS == status )
1566 {
1567 /* Now copy over all the security attributes you have
1568 * parsed out
1569 * */
1570 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1571 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1572 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1573 = RSNEncryptType;
1574 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1575 "EncryptionType = %d mcEncryptionType = %d\n"),
1576 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1577 }
1578 }
1579
1580 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1581 pBeacon->tail, pBeacon->tail_len);
1582
1583 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1584 {
1585 if (pConfig->pRSNWPAReqIE)
1586 {
1587 /*Mixed mode WPA/WPA2*/
1588 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1589 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1590 }
1591 else
1592 {
1593 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1594 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1595 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1596 status = hdd_softap_unpackIE(
1597 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1598 &RSNEncryptType,
1599 &mcRSNEncryptType,
1600 &RSNAuthType,
1601 pConfig->pRSNWPAReqIE[1]+2,
1602 pConfig->pRSNWPAReqIE );
1603
1604 if( VOS_STATUS_SUCCESS == status )
1605 {
1606 /* Now copy over all the security attributes you have
1607 * parsed out
1608 * */
1609 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1610 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1611 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1612 = RSNEncryptType;
1613 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1614 "EncryptionType = %d mcEncryptionType = %d\n"),
1615 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1616 }
1617 }
1618 }
1619
1620 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1621
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001622#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001623 if (params->ssid != NULL)
1624 {
1625 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1626 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1627 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1628 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1629 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001630#else
1631 if (ssid != NULL)
1632 {
1633 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1634 pConfig->SSIDinfo.ssid.length = ssid_len;
1635 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1636 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1637 }
1638#endif
1639
Jeff Johnson295189b2012-06-20 16:38:30 -07001640 vos_mem_copy(pConfig->self_macaddr.bytes,
1641 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1642
1643 /* default value */
1644 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1645 pConfig->num_accept_mac = 0;
1646 pConfig->num_deny_mac = 0;
1647
1648 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1649 pBeacon->tail, pBeacon->tail_len);
1650
1651 /* pIe for black list is following form:
1652 type : 1 byte
1653 length : 1 byte
1654 OUI : 4 bytes
1655 acl type : 1 byte
1656 no of mac addr in black list: 1 byte
1657 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1658 */
1659 if ((pIe != NULL) && (pIe[1] != 0))
1660 {
1661 pConfig->SapMacaddr_acl = pIe[6];
1662 pConfig->num_deny_mac = pIe[7];
1663 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1664 pIe[6], pIe[7]);
1665 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1666 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1667 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1668 for (i = 0; i < pConfig->num_deny_mac; i++)
1669 {
1670 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1671 acl_entry++;
1672 }
1673 }
1674 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1675 pBeacon->tail, pBeacon->tail_len);
1676
1677 /* pIe for white list is following form:
1678 type : 1 byte
1679 length : 1 byte
1680 OUI : 4 bytes
1681 acl type : 1 byte
1682 no of mac addr in white list: 1 byte
1683 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1684 */
1685 if ((pIe != NULL) && (pIe[1] != 0))
1686 {
1687 pConfig->SapMacaddr_acl = pIe[6];
1688 pConfig->num_accept_mac = pIe[7];
1689 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1690 pIe[6], pIe[7]);
1691 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1692 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1693 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1694 for (i = 0; i < pConfig->num_accept_mac; i++)
1695 {
1696 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1697 acl_entry++;
1698 }
1699 }
1700 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1701
Jeff Johnsone7245742012-09-05 17:12:55 -07001702#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001703 /* Overwrite the hostapd setting for HW mode only for 11ac.
1704 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1705 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1706 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1707 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1708 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1709 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1710 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001711 {
1712 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1713 }
1714#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301715
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001716 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1717 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001718 // ht_capab is not what the name conveys,this is used for protection bitmap
1719 pConfig->ht_capab =
1720 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1721
1722 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1723 {
1724 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1725 return -EINVAL;
1726 }
1727
1728 //Uapsd Enabled Bit
1729 pConfig->UapsdEnable =
1730 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1731 //Enable OBSS protection
1732 pConfig->obssProtEnabled =
1733 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1734
1735 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1736 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1737 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1738 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1739 (int)pConfig->channel);
1740 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1741 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1742 pConfig->authType);
1743 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1744 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1745 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1746 pConfig->protEnabled, pConfig->obssProtEnabled);
1747
1748 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1749 {
1750 //Bss already started. just return.
1751 //TODO Probably it should update some beacon params.
1752 hddLog( LOGE, "Bss Already started...Ignore the request");
1753 EXIT();
1754 return 0;
1755 }
1756
1757 pConfig->persona = pHostapdAdapter->device_mode;
1758
1759 pSapEventCallback = hdd_hostapd_SAPEventCB;
1760 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1761 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1762 {
1763 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1764 return -EINVAL;
1765 }
1766
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001767 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001768 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1769
1770 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1771
1772 if (!VOS_IS_STATUS_SUCCESS(status))
1773 {
1774 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1775 ("ERROR: HDD vos wait for single_event failed!!\n"));
1776 VOS_ASSERT(0);
1777 }
1778
1779 //Succesfully started Bss update the state bit.
1780 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1781
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001782#ifdef WLAN_FEATURE_P2P_DEBUG
1783 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1784 {
1785 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1786 {
1787 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1788 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001789 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001790 }
1791 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1792 {
1793 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1794 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001795 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001796 }
1797 }
1798#endif
1799
Jeff Johnson295189b2012-06-20 16:38:30 -07001800 pHostapdState->bCommit = TRUE;
1801 EXIT();
1802
1803 return 0;
1804}
1805
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001806#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001807static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1808 struct net_device *dev,
1809 struct beacon_parameters *params)
1810{
1811 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1812 int status=VOS_STATUS_SUCCESS;
1813
1814 ENTER();
1815
1816 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1817
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001818 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1819 {
1820 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1821 "%s:LOGP in Progress. Ignore!!!", __func__);
1822 return -EAGAIN;
1823 }
1824
Jeff Johnson295189b2012-06-20 16:38:30 -07001825 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1826#ifdef WLAN_FEATURE_P2P
1827 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1828#endif
1829 )
1830 {
1831 beacon_data_t *old,*new;
1832
1833 old = pAdapter->sessionCtx.ap.beacon;
1834
1835 if (old)
1836 return -EALREADY;
1837
1838 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1839
1840 if(status != VOS_STATUS_SUCCESS)
1841 {
1842 hddLog(VOS_TRACE_LEVEL_FATAL,
1843 "%s:Error!!! Allocating the new beacon\n",__func__);
1844 return -EINVAL;
1845 }
1846
1847 pAdapter->sessionCtx.ap.beacon = new;
1848
1849 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1850 }
1851
1852 EXIT();
1853 return status;
1854}
1855
1856static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1857 struct net_device *dev,
1858 struct beacon_parameters *params)
1859{
1860 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1861 int status=VOS_STATUS_SUCCESS;
1862
1863 ENTER();
1864
1865 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1866 __func__,pAdapter->device_mode);
1867
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001868 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1869 {
1870 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1871 "%s:LOGP in Progress. Ignore!!!", __func__);
1872 return -EAGAIN;
1873 }
1874
Jeff Johnson295189b2012-06-20 16:38:30 -07001875 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1876#ifdef WLAN_FEATURE_P2P
1877 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1878#endif
1879 )
1880 {
1881 beacon_data_t *old,*new;
1882
1883 old = pAdapter->sessionCtx.ap.beacon;
1884
1885 if (!old)
1886 return -ENOENT;
1887
1888 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1889
1890 if(status != VOS_STATUS_SUCCESS) {
1891 hddLog(VOS_TRACE_LEVEL_FATAL,
1892 "%s: Error!!! Allocating the new beacon\n",__func__);
1893 return -EINVAL;
1894 }
1895
1896 pAdapter->sessionCtx.ap.beacon = new;
1897
1898 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1899 }
1900
1901 EXIT();
1902 return status;
1903}
1904
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001905#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1906
1907#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001908static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1909 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001910#else
1911static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1912 struct net_device *dev)
1913#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001914{
1915 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001916 hdd_context_t *pHddCtx = NULL;
1917 hdd_scaninfo_t *pScanInfo = NULL;
1918 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001919 VOS_STATUS status = 0;
1920
1921 ENTER();
1922
1923 if (NULL == pAdapter)
1924 {
1925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001926 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001927 return -ENODEV;
1928 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001929 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1930 {
1931 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1932 "%s:LOGP in Progress. Ignore!!!", __func__);
1933 return -EAGAIN;
1934 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001935
1936 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1937 if (NULL == pHddCtx)
1938 {
1939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001940 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001941 return -ENODEV;
1942 }
1943
1944 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1945 if (NULL == staAdapter)
1946 {
1947 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1948 if (NULL == staAdapter)
1949 {
1950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001951 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001952 return -ENODEV;
1953 }
1954 }
1955
1956 pScanInfo = &pHddCtx->scan_info;
1957
Jeff Johnson295189b2012-06-20 16:38:30 -07001958 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1959 {
1960 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1961 return -EAGAIN;
1962 }
1963
1964 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1965
1966 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1967 __func__,pAdapter->device_mode);
1968
Jeff Johnsone7245742012-09-05 17:12:55 -07001969 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1970 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001971 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001972 hdd_abort_mac_scan(staAdapter->pHddCtx);
1973 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001974 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07001975 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1976 if (!status)
1977 {
1978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08001979 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001980 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001981 VOS_ASSERT(pScanInfo->mScanPending);
1982 return 0;
1983 }
1984 }
1985
Jeff Johnson295189b2012-06-20 16:38:30 -07001986 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1987#ifdef WLAN_FEATURE_P2P
1988 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1989#endif
1990 )
1991 {
1992 beacon_data_t *old;
1993
1994 old = pAdapter->sessionCtx.ap.beacon;
1995
1996 if (!old)
1997 return -ENOENT;
1998
1999#ifdef CONFIG_CFG80211
2000 hdd_cleanup_actionframe(pHddCtx, pAdapter);
2001#endif
2002
2003 mutex_lock(&pHddCtx->sap_lock);
2004 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2005 {
2006 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2007 {
2008 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2009
2010 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2011
2012 if (!VOS_IS_STATUS_SUCCESS(status))
2013 {
2014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2015 ("ERROR: HDD vos wait for single_event failed!!\n"));
2016 VOS_ASSERT(0);
2017 }
2018 }
2019 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2020 }
2021 mutex_unlock(&pHddCtx->sap_lock);
2022
2023 if(status != VOS_STATUS_SUCCESS)
2024 {
2025 hddLog(VOS_TRACE_LEVEL_FATAL,
2026 "%s:Error!!! Stopping the BSS\n",__func__);
2027 return -EINVAL;
2028 }
2029
2030 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2031 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2032 ==eHAL_STATUS_FAILURE)
2033 {
2034 hddLog(LOGE,
2035 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2036 }
2037
2038 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2039 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2040 eANI_BOOLEAN_FALSE) )
2041 {
2042 hddLog(LOGE,
2043 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2044 }
2045
2046 // Reset WNI_CFG_PROBE_RSP Flags
2047 wlan_hdd_reset_prob_rspies(pAdapter);
2048
2049 pAdapter->sessionCtx.ap.beacon = NULL;
2050 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002051#ifdef WLAN_FEATURE_P2P_DEBUG
2052 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2053 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2054 {
2055 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2056 "GO got removed");
2057 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2058 }
2059#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002060 }
2061 EXIT();
2062 return status;
2063}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002064
2065#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2066
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302067static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2068 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002069 struct cfg80211_ap_settings *params)
2070{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302071 hdd_adapter_t *pAdapter;
2072 hdd_context_t *pHddCtx;
2073 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002074
2075 ENTER();
2076
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302077 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002078 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2080 "%s: Device is Null", __func__);
2081 return -ENODEV;
2082 }
2083
2084 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2085 if (NULL == pAdapter)
2086 {
2087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2088 "%s: HDD adapter is Null", __func__);
2089 return -ENODEV;
2090 }
2091
2092 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2093 {
2094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2095 "%s: HDD adapter magic is invalid", __func__);
2096 return -ENODEV;
2097 }
2098
2099 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2100 if (NULL == pHddCtx)
2101 {
2102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2103 "%s: HDD context is Null", __func__);
2104 return -ENODEV;
2105 }
2106
2107 if (pHddCtx->isLogpInProgress)
2108 {
2109 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2110 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002111 return -EAGAIN;
2112 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302113
2114 if (pHddCtx->isLoadUnloadInProgress)
2115 {
2116 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2117 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2118 return -EAGAIN;
2119 }
2120
2121 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2122 __func__, pAdapter->device_mode);
2123
2124 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002125#ifdef WLAN_FEATURE_P2P
2126 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2127#endif
2128 )
2129 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302130 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002131
2132 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302133
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002134 if (old)
2135 return -EALREADY;
2136
2137 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2138
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302139 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002140 {
2141 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302142 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002143 return -EINVAL;
2144 }
2145 pAdapter->sessionCtx.ap.beacon = new;
2146 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2147 params->ssid_len, params->hidden_ssid);
2148 }
2149
2150 EXIT();
2151 return status;
2152}
2153
2154
2155static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2156 struct net_device *dev,
2157 struct cfg80211_beacon_data *params)
2158{
2159 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2160 int status=VOS_STATUS_SUCCESS;
2161
2162 ENTER();
2163
2164 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2165 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002166 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2167 {
2168 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2169 return -EAGAIN;
2170 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002171
2172 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2173#ifdef WLAN_FEATURE_P2P
2174 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2175#endif
2176 )
2177 {
2178 beacon_data_t *old,*new;
2179
2180 old = pAdapter->sessionCtx.ap.beacon;
2181
2182 if (!old)
2183 return -ENOENT;
2184
2185 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2186
2187 if(status != VOS_STATUS_SUCCESS) {
2188 hddLog(VOS_TRACE_LEVEL_FATAL,
2189 "%s: Error!!! Allocating the new beacon\n",__func__);
2190 return -EINVAL;
2191 }
2192
2193 pAdapter->sessionCtx.ap.beacon = new;
2194
2195 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2196 }
2197
2198 EXIT();
2199 return status;
2200}
2201
2202#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2203
Jeff Johnson295189b2012-06-20 16:38:30 -07002204
2205static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2206 struct net_device *dev,
2207 struct bss_parameters *params)
2208{
2209 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2210
2211 ENTER();
2212
2213 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2214 __func__,pAdapter->device_mode);
2215
2216 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2217#ifdef WLAN_FEATURE_P2P
2218 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2219#endif
2220 )
2221 {
2222 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2223 * want to update this parameter */
2224 if (-1 != params->ap_isolate)
2225 {
2226 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2227 }
2228 }
2229
2230 EXIT();
2231 return 0;
2232}
2233
2234/*
2235 * FUNCTION: wlan_hdd_cfg80211_change_iface
2236 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2237 */
2238int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2239 struct net_device *ndev,
2240 enum nl80211_iftype type,
2241 u32 *flags,
2242 struct vif_params *params
2243 )
2244{
2245 struct wireless_dev *wdev;
2246 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2247 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002248 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002249 tCsrRoamProfile *pRoamProfile = NULL;
2250 eCsrRoamBssType LastBSSType;
2251 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2252 eMib_dot11DesiredBssType connectedBssType;
2253 VOS_STATUS status;
2254
2255 ENTER();
2256
2257 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2258 {
2259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2260 return -EAGAIN;
2261 }
2262
2263 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2264 __func__, pAdapter->device_mode);
2265
2266 wdev = ndev->ieee80211_ptr;
2267
2268#ifdef WLAN_BTAMP_FEATURE
2269 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2270 (NL80211_IFTYPE_ADHOC == type)||
2271 (NL80211_IFTYPE_AP == type)||
2272 (NL80211_IFTYPE_P2P_GO == type))
2273 {
2274 pHddCtx->isAmpAllowed = VOS_FALSE;
2275 // stop AMP traffic
2276 status = WLANBAP_StopAmp();
2277 if(VOS_STATUS_SUCCESS != status )
2278 {
2279 pHddCtx->isAmpAllowed = VOS_TRUE;
2280 hddLog(VOS_TRACE_LEVEL_FATAL,
2281 "%s: Failed to stop AMP", __func__);
2282 return -EINVAL;
2283 }
2284 }
2285#endif //WLAN_BTAMP_FEATURE
2286 /* Reset the current device mode bit mask*/
2287 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2288
2289 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2290#ifdef WLAN_FEATURE_P2P
2291 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002292 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002293#endif
2294 )
2295 {
2296 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2297 pRoamProfile = &pWextState->roamProfile;
2298 LastBSSType = pRoamProfile->BSSType;
2299
2300 switch (type)
2301 {
2302 case NL80211_IFTYPE_STATION:
2303#ifdef WLAN_FEATURE_P2P
2304 case NL80211_IFTYPE_P2P_CLIENT:
2305#endif
2306 hddLog(VOS_TRACE_LEVEL_INFO,
2307 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2308 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002309#ifdef WLAN_FEATURE_11AC
2310 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2311 {
2312 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2313 }
2314#endif
2315 pRoamProfile->phyMode =
2316 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002317 wdev->iftype = type;
2318#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002319 //Check for sub-string p2p to confirm its a p2p interface
2320 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002321 {
2322 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2323 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2324 }
2325 else
2326 {
2327 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002328 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002329 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002330#endif
2331 break;
2332 case NL80211_IFTYPE_ADHOC:
2333 hddLog(VOS_TRACE_LEVEL_INFO,
2334 "%s: setting interface Type to ADHOC", __func__);
2335 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2336 pRoamProfile->phyMode =
2337 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2338 wdev->iftype = type;
2339 break;
2340
2341 case NL80211_IFTYPE_AP:
2342#ifdef WLAN_FEATURE_P2P
2343 case NL80211_IFTYPE_P2P_GO:
2344#endif
2345 {
2346 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2347 "%s: setting interface Type to %s", __func__,
2348 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2349
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002350 //Cancel any remain on channel for GO mode
2351 if (NL80211_IFTYPE_P2P_GO == type)
2352 {
2353 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2354 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002355 if (NL80211_IFTYPE_AP == type)
2356 {
2357 /* As Loading WLAN Driver one interface being created for p2p device
2358 * address. This will take one HW STA and the max number of clients
2359 * that can connect to softAP will be reduced by one. so while changing
2360 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2361 * interface as it is not required in SoftAP mode.
2362 */
2363
2364 // Get P2P Adapter
2365 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2366
2367 if (pP2pAdapter)
2368 {
2369 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2370 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2371 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2372 }
2373 }
2374
Jeff Johnson295189b2012-06-20 16:38:30 -07002375 //De-init the adapter.
2376 hdd_stop_adapter( pHddCtx, pAdapter );
2377 hdd_deinit_adapter( pHddCtx, pAdapter );
2378 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2379#ifdef WLAN_SOFTAP_FEATURE
2380#ifdef WLAN_FEATURE_P2P
2381 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2382 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2383#else
2384 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2385#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002386
2387 //Disable BMPS and IMPS if enabled
2388 //before starting Go
2389 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2390 {
2391 if(VOS_STATUS_E_FAILURE ==
2392 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2393 {
2394 //Fail to Exit BMPS
2395 VOS_ASSERT(0);
2396 }
2397 }
2398
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002399 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2400 (pConfig->apRandomBssidEnabled))
2401 {
2402 /* To meet Android requirements create a randomized
2403 MAC address of the form 02:1A:11:Fx:xx:xx */
2404 get_random_bytes(&ndev->dev_addr[3], 3);
2405 ndev->dev_addr[0] = 0x02;
2406 ndev->dev_addr[1] = 0x1A;
2407 ndev->dev_addr[2] = 0x11;
2408 ndev->dev_addr[3] |= 0xF0;
2409 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2410 VOS_MAC_ADDR_SIZE);
2411 pr_info("wlan: Generated HotSpot BSSID "
2412 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2413 ndev->dev_addr[0],
2414 ndev->dev_addr[1],
2415 ndev->dev_addr[2],
2416 ndev->dev_addr[3],
2417 ndev->dev_addr[4],
2418 ndev->dev_addr[5]);
2419 }
2420
Jeff Johnson295189b2012-06-20 16:38:30 -07002421 hdd_set_ap_ops( pAdapter->dev );
2422
2423 status = hdd_init_ap_mode(pAdapter);
2424 if(status != VOS_STATUS_SUCCESS)
2425 {
2426 hddLog(VOS_TRACE_LEVEL_FATAL,
2427 "%s: Error initializing the ap mode", __func__);
2428 return -EINVAL;
2429 }
2430 hdd_set_conparam(1);
2431
2432#endif
2433 /*interface type changed update in wiphy structure*/
2434 if(wdev)
2435 {
2436 wdev->iftype = type;
2437 pHddCtx->change_iface = type;
2438 }
2439 else
2440 {
2441 hddLog(VOS_TRACE_LEVEL_ERROR,
2442 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2443 return -EINVAL;
2444 }
2445 goto done;
2446 }
2447
2448 default:
2449 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2450 __func__);
2451 return -EOPNOTSUPP;
2452 }
2453 }
2454 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2455#ifdef WLAN_FEATURE_P2P
2456 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2457#endif
2458 )
2459 {
2460 switch(type)
2461 {
2462 case NL80211_IFTYPE_STATION:
2463#ifdef WLAN_FEATURE_P2P
2464 case NL80211_IFTYPE_P2P_CLIENT:
2465#endif
2466 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002467 hdd_stop_adapter( pHddCtx, pAdapter );
2468 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002469 wdev->iftype = type;
2470#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002471 //Check for sub-string p2p to confirm its a p2p interface
2472 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002473 {
2474 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2475 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2476 }
2477 else
2478 {
2479 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002480 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002481 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002482#endif
2483 hdd_set_conparam(0);
2484 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2486 hdd_set_station_ops( pAdapter->dev );
2487 status = hdd_init_station_mode( pAdapter );
2488 if( VOS_STATUS_SUCCESS != status )
2489 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002490 /* In case of JB, for P2P-GO, only change interface will be called,
2491 * This is the right place to enable back bmps_imps()
2492 */
2493 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002494 goto done;
2495 case NL80211_IFTYPE_AP:
2496#ifdef WLAN_FEATURE_P2P
2497 case NL80211_IFTYPE_P2P_GO:
2498#endif
2499 wdev->iftype = type;
2500#ifdef WLAN_FEATURE_P2P
2501 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2502 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2503#endif
2504 goto done;
2505 default:
2506 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2507 __func__);
2508 return -EOPNOTSUPP;
2509
2510 }
2511
2512 }
2513 else
2514 {
2515 return -EOPNOTSUPP;
2516 }
2517
2518
2519 if(pRoamProfile)
2520 {
2521 if ( LastBSSType != pRoamProfile->BSSType )
2522 {
2523 /*interface type changed update in wiphy structure*/
2524 wdev->iftype = type;
2525
2526 /*the BSS mode changed, We need to issue disconnect
2527 if connected or in IBSS disconnect state*/
2528 if ( hdd_connGetConnectedBssType(
2529 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2530 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2531 {
2532 /*need to issue a disconnect to CSR.*/
2533 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2534 if( eHAL_STATUS_SUCCESS ==
2535 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2536 pAdapter->sessionId,
2537 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2538 {
2539 wait_for_completion_interruptible_timeout(
2540 &pAdapter->disconnect_comp_var,
2541 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2542 }
2543 }
2544 }
2545 }
2546
2547done:
2548 /*set bitmask based on updated value*/
2549 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2550#ifdef WLAN_BTAMP_FEATURE
2551 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2552 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2553 {
2554 //we are ok to do AMP
2555 pHddCtx->isAmpAllowed = VOS_TRUE;
2556 }
2557#endif //WLAN_BTAMP_FEATURE
2558 EXIT();
2559 return 0;
2560}
2561
2562static int wlan_hdd_change_station(struct wiphy *wiphy,
2563 struct net_device *dev,
2564 u8 *mac,
2565 struct station_parameters *params)
2566{
2567 VOS_STATUS status = VOS_STATUS_SUCCESS;
2568 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2569 v_MACADDR_t STAMacAddress;
2570
Jeff Johnsone7245742012-09-05 17:12:55 -07002571 ENTER();
2572
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002573 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2574 {
2575 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2576 "%s:LOGP in Progress. Ignore!!!", __func__);
2577 return -EAGAIN;
2578 }
2579
Jeff Johnson295189b2012-06-20 16:38:30 -07002580 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2581
2582 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2583#ifdef WLAN_FEATURE_P2P
2584 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2585#endif
2586 )
2587 {
2588 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2589 {
2590 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2591 WLANTL_STA_AUTHENTICATED);
2592
2593 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002594 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002595 return -EINVAL;
2596 }
2597 }
2598
Jeff Johnsone7245742012-09-05 17:12:55 -07002599 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002600 return status;
2601}
2602
2603/*
2604 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2605 * This function is used to get peer station index in IBSS mode
2606 */
2607static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2608{
2609 u8 idx = 0;
2610 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2611 ENTER();
2612 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2613 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2614 {
2615 if ( (0 !=
2616 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2617 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2618 temp, VOS_MAC_ADDR_SIZE)
2619 )
2620 {
2621 return idx;
2622 }
2623 }
2624 return idx;
2625}
2626
2627
2628/*
2629 * FUNCTION: wlan_hdd_cfg80211_add_key
2630 * This function is used to initialize the key information
2631 */
2632#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2633static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2634 struct net_device *ndev,
2635 u8 key_index, bool pairwise,
2636 const u8 *mac_addr,
2637 struct key_params *params
2638 )
2639#else
2640static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2641 struct net_device *ndev,
2642 u8 key_index, const u8 *mac_addr,
2643 struct key_params *params
2644 )
2645#endif
2646{
2647 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2648 tCsrRoamSetKey setKey;
2649 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2650 int status = 0;
2651 v_U32_t roamId= 0xFF;
2652 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2653 hdd_hostapd_state_t *pHostapdState;
2654 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002655 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002656
2657 ENTER();
2658
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002659 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2660 {
2661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2662 "%s:LOGP in Progress. Ignore!!!", __func__);
2663 return -EAGAIN;
2664 }
2665
Jeff Johnson295189b2012-06-20 16:38:30 -07002666 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2667 __func__,pAdapter->device_mode);
2668
2669 if (CSR_MAX_NUM_KEY <= key_index)
2670 {
2671 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2672 key_index);
2673
2674 return -EINVAL;
2675 }
2676
2677 hddLog(VOS_TRACE_LEVEL_INFO,
2678 "%s: called with key index = %d & key length %d",
2679 __func__, key_index, params->key_len);
2680
2681 /*extract key idx, key len and key*/
2682 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2683 setKey.keyId = key_index;
2684 setKey.keyLength = params->key_len;
2685 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2686
2687 switch (params->cipher)
2688 {
2689 case WLAN_CIPHER_SUITE_WEP40:
2690 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2691 break;
2692
2693 case WLAN_CIPHER_SUITE_WEP104:
2694 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2695 break;
2696
2697 case WLAN_CIPHER_SUITE_TKIP:
2698 {
2699 u8 *pKey = &setKey.Key[0];
2700 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2701
2702 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2703
2704 /*Supplicant sends the 32bytes key in this order
2705
2706 |--------------|----------|----------|
2707 | Tk1 |TX-MIC | RX Mic |
2708 |--------------|----------|----------|
2709 <---16bytes---><--8bytes--><--8bytes-->
2710
2711 */
2712 /*Sme expects the 32 bytes key to be in the below order
2713
2714 |--------------|----------|----------|
2715 | Tk1 |RX-MIC | TX Mic |
2716 |--------------|----------|----------|
2717 <---16bytes---><--8bytes--><--8bytes-->
2718 */
2719 /* Copy the Temporal Key 1 (TK1) */
2720 vos_mem_copy(pKey, params->key,16);
2721
2722 /*Copy the rx mic first*/
2723 vos_mem_copy(&pKey[16],&params->key[24],8);
2724
2725 /*Copy the tx mic */
2726 vos_mem_copy(&pKey[24],&params->key[16],8);
2727
2728
2729 break;
2730 }
2731
2732 case WLAN_CIPHER_SUITE_CCMP:
2733 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2734 break;
2735
2736#ifdef FEATURE_WLAN_WAPI
2737 case WLAN_CIPHER_SUITE_SMS4:
2738 {
2739 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2740 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2741 params->key, params->key_len);
2742 return 0;
2743 }
2744#endif
2745#ifdef FEATURE_WLAN_CCX
2746 case WLAN_CIPHER_SUITE_KRK:
2747 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2748 break;
2749#endif
2750 default:
2751 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2752 __func__, params->cipher);
2753 return -EOPNOTSUPP;
2754 }
2755
2756 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2757 __func__, setKey.encType);
2758
2759
2760
2761 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2762#ifdef WLAN_FEATURE_P2P
2763 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2764#endif
2765 )
2766 {
2767
2768
2769 if (
2770#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2771 (!pairwise)
2772#else
2773 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2774#endif
2775 )
2776 {
2777 /* set group key*/
2778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002779 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002780 __func__, __LINE__);
2781 setKey.keyDirection = eSIR_RX_ONLY;
2782 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2783 }
2784 else
2785 {
2786 /* set pairwise key*/
2787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2788 "%s- %d: setting pairwise key",
2789 __func__, __LINE__);
2790 setKey.keyDirection = eSIR_TX_RX;
2791 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2792 }
2793
2794 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2795 if( pHostapdState->bssState == BSS_START )
2796 {
2797 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2798
2799 if ( status != eHAL_STATUS_SUCCESS )
2800 {
2801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2802 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2803 __LINE__, status );
2804 }
2805 }
2806
2807 /* Saving WEP keys */
2808 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2809 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2810 {
2811 //Save the wep key in ap context. Issue setkey after the BSS is started.
2812 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2813 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2814 }
2815 else
2816 {
2817 //Save the key in ap context. Issue setkey after the BSS is started.
2818 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2819 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2820 }
2821 }
2822 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2823#ifdef WLAN_FEATURE_P2P
2824 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2825#endif
2826 )
2827 {
2828 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2829 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2830
2831 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2832
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08002833 pWextState->roamProfile.Keys.defaultIndex = key_index;
2834
2835
Jeff Johnson295189b2012-06-20 16:38:30 -07002836 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2837 params->key, params->key_len);
2838
2839 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2840
2841 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2842 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2843 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2844 )
2845 &&
2846 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2847 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2848 )
2849 )
2850 {
2851 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2852 * interface, copy bssid for pairwise key and group macaddr for
2853 * group key initialization*/
2854
2855 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2856
2857 pWextState->roamProfile.negotiatedUCEncryptionType =
2858 pHddStaCtx->conn_info.ucEncryptionType =
2859 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2860 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2861 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2862
2863
2864 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2865 "%s: Negotiated encryption type %d", __func__,
2866 pWextState->roamProfile.negotiatedUCEncryptionType);
2867
2868 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2869 &pWextState->roamProfile, true);
2870 setKey.keyLength = 0;
2871 setKey.keyDirection = eSIR_TX_RX;
2872
2873#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2874 if (pairwise)
2875 {
2876#endif
2877 if (mac_addr)
2878 {
2879 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2880 }
2881 else
2882 {
2883 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2884 * and peerMacAddress in case of IBSS*/
2885 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2886 {
2887 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2888 if (HDD_MAX_NUM_IBSS_STA != staidx)
2889 {
2890 vos_mem_copy(setKey.peerMac,
2891 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2892 WNI_CFG_BSSID_LEN);
2893
2894 }
2895 else
2896 {
2897 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2898 __func__);
2899 return -EOPNOTSUPP;
2900 }
2901 }
2902 else
2903 {
2904 vos_mem_copy(setKey.peerMac,
2905 &pHddStaCtx->conn_info.bssId[0],
2906 WNI_CFG_BSSID_LEN);
2907 }
2908 }
2909#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2910 }
2911 else
2912 {
2913 /* set group key*/
2914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2915 "%s- %d: setting Group key",
2916 __func__, __LINE__);
2917 setKey.keyDirection = eSIR_RX_ONLY;
2918 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2919 }
2920#endif
2921 }
2922 else if (
2923#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2924 (!pairwise)
2925#else
2926 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2927#endif
2928 )
2929 {
2930 /* set group key*/
2931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2932 "%s- %d: setting Group key",
2933 __func__, __LINE__);
2934 setKey.keyDirection = eSIR_RX_ONLY;
2935 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2936 }
2937 else
2938 {
2939 /* set pairwise key*/
2940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2941 "%s- %d: setting pairwise key",
2942 __func__, __LINE__);
2943 setKey.keyDirection = eSIR_TX_RX;
2944 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2945 }
2946
2947 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2948 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2949 __func__, setKey.peerMac[0], setKey.peerMac[1],
2950 setKey.peerMac[2], setKey.peerMac[3],
2951 setKey.peerMac[4], setKey.peerMac[5],
2952 setKey.keyDirection);
2953
2954 vos_status = wlan_hdd_check_ula_done(pAdapter);
2955
2956 if ( vos_status != VOS_STATUS_SUCCESS )
2957 {
2958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2959 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2960 __LINE__, vos_status );
2961
2962 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2963
2964 return -EINVAL;
2965
2966 }
2967
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002968#ifdef WLAN_FEATURE_VOWIFI_11R
2969 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2970 Save the key in the UMAC and include it in the ADD BSS request */
2971 /*TODO 11r - is this used?? */
2972 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2973 if( halStatus == eHAL_STATUS_SUCCESS )
2974 {
2975 return halStatus;
2976 }
2977#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002978
2979 /* issue set key request to SME*/
2980 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2981 pAdapter->sessionId, &setKey, &roamId );
2982
2983 if ( 0 != status )
2984 {
2985 hddLog(VOS_TRACE_LEVEL_ERROR,
2986 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2987 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2988 return -EINVAL;
2989 }
2990
2991
2992 /* in case of IBSS as there was no information available about WEP keys during
2993 * IBSS join, group key intialized with NULL key, so re-initialize group key
2994 * with correct value*/
2995 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2996 !( ( IW_AUTH_KEY_MGMT_802_1X
2997 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2998 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2999 )
3000 &&
3001 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3002 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3003 )
3004 )
3005 {
3006 setKey.keyDirection = eSIR_RX_ONLY;
3007 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3008
3009 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3010 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3011 __func__, setKey.peerMac[0], setKey.peerMac[1],
3012 setKey.peerMac[2], setKey.peerMac[3],
3013 setKey.peerMac[4], setKey.peerMac[5],
3014 setKey.keyDirection);
3015
3016 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3017 pAdapter->sessionId, &setKey, &roamId );
3018
3019 if ( 0 != status )
3020 {
3021 hddLog(VOS_TRACE_LEVEL_ERROR,
3022 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3023 __func__, status);
3024 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3025 return -EINVAL;
3026 }
3027 }
3028 }
3029
3030 return 0;
3031}
3032
3033/*
3034 * FUNCTION: wlan_hdd_cfg80211_get_key
3035 * This function is used to get the key information
3036 */
3037#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3038static int wlan_hdd_cfg80211_get_key(
3039 struct wiphy *wiphy,
3040 struct net_device *ndev,
3041 u8 key_index, bool pairwise,
3042 const u8 *mac_addr, void *cookie,
3043 void (*callback)(void *cookie, struct key_params*)
3044 )
3045#else
3046static int wlan_hdd_cfg80211_get_key(
3047 struct wiphy *wiphy,
3048 struct net_device *ndev,
3049 u8 key_index, const u8 *mac_addr, void *cookie,
3050 void (*callback)(void *cookie, struct key_params*)
3051 )
3052#endif
3053{
3054 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3055 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3056 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3057 struct key_params params;
3058
3059 ENTER();
3060
3061 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3062 __func__,pAdapter->device_mode);
3063
3064 memset(&params, 0, sizeof(params));
3065
3066 if (CSR_MAX_NUM_KEY <= key_index)
3067 {
3068 return -EINVAL;
3069 }
3070
3071 switch(pRoamProfile->EncryptionType.encryptionType[0])
3072 {
3073 case eCSR_ENCRYPT_TYPE_NONE:
3074 params.cipher = IW_AUTH_CIPHER_NONE;
3075 break;
3076
3077 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3078 case eCSR_ENCRYPT_TYPE_WEP40:
3079 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3080 break;
3081
3082 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3083 case eCSR_ENCRYPT_TYPE_WEP104:
3084 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3085 break;
3086
3087 case eCSR_ENCRYPT_TYPE_TKIP:
3088 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3089 break;
3090
3091 case eCSR_ENCRYPT_TYPE_AES:
3092 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3093 break;
3094
3095 default:
3096 params.cipher = IW_AUTH_CIPHER_NONE;
3097 break;
3098 }
3099
3100 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3101 params.seq_len = 0;
3102 params.seq = NULL;
3103 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3104 callback(cookie, &params);
3105 return 0;
3106}
3107
3108/*
3109 * FUNCTION: wlan_hdd_cfg80211_del_key
3110 * This function is used to delete the key information
3111 */
3112#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3113static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3114 struct net_device *ndev,
3115 u8 key_index,
3116 bool pairwise,
3117 const u8 *mac_addr
3118 )
3119#else
3120static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3121 struct net_device *ndev,
3122 u8 key_index,
3123 const u8 *mac_addr
3124 )
3125#endif
3126{
3127 int status = 0;
3128
3129 //This code needs to be revisited. There is sme_removeKey API, we should
3130 //plan to use that. After the change to use correct index in setkey,
3131 //it is observed that this is invalidating peer
3132 //key index whenever re-key is done. This is affecting data link.
3133 //It should be ok to ignore del_key.
3134#if 0
3135 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3136 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3137 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3138 tCsrRoamSetKey setKey;
3139 v_U32_t roamId= 0xFF;
3140
3141 ENTER();
3142
3143 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3144 __func__,pAdapter->device_mode);
3145
3146 if (CSR_MAX_NUM_KEY <= key_index)
3147 {
3148 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3149 key_index);
3150
3151 return -EINVAL;
3152 }
3153
3154 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3155 setKey.keyId = key_index;
3156
3157 if (mac_addr)
3158 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3159 else
3160 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3161
3162 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3163
3164 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3165#ifdef WLAN_FEATURE_P2P
3166 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3167#endif
3168 )
3169 {
3170
3171 hdd_hostapd_state_t *pHostapdState =
3172 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3173 if( pHostapdState->bssState == BSS_START)
3174 {
3175 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3176
3177 if ( status != eHAL_STATUS_SUCCESS )
3178 {
3179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3180 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3181 __LINE__, status );
3182 }
3183 }
3184 }
3185 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3186#ifdef WLAN_FEATURE_P2P
3187 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3188#endif
3189 )
3190 {
3191 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3192
3193 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3194
3195 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3196 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3197 __func__, setKey.peerMac[0], setKey.peerMac[1],
3198 setKey.peerMac[2], setKey.peerMac[3],
3199 setKey.peerMac[4], setKey.peerMac[5]);
3200 if(pAdapter->sessionCtx.station.conn_info.connState ==
3201 eConnectionState_Associated)
3202 {
3203 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3204 pAdapter->sessionId, &setKey, &roamId );
3205
3206 if ( 0 != status )
3207 {
3208 hddLog(VOS_TRACE_LEVEL_ERROR,
3209 "%s: sme_RoamSetKey failure, returned %d",
3210 __func__, status);
3211 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3212 return -EINVAL;
3213 }
3214 }
3215 }
3216#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003217 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003218 return status;
3219}
3220
3221/*
3222 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3223 * This function is used to set the default tx key index
3224 */
3225#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3226static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3227 struct net_device *ndev,
3228 u8 key_index,
3229 bool unicast, bool multicast)
3230#else
3231static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3232 struct net_device *ndev,
3233 u8 key_index)
3234#endif
3235{
3236 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3237 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3238 int status = 0;
3239 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3240
3241 ENTER();
3242
3243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3244 __func__,pAdapter->device_mode, key_index);
3245
3246 if (CSR_MAX_NUM_KEY <= key_index)
3247 {
3248 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3249 key_index);
3250
3251 return -EINVAL;
3252 }
3253
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003254 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3255 {
3256 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3257 "%s:LOGP in Progress. Ignore!!!", __func__);
3258 return -EAGAIN;
3259 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003260
3261 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3262#ifdef WLAN_FEATURE_P2P
3263 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3264#endif
3265 )
3266 {
3267 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3268 (eCSR_ENCRYPT_TYPE_TKIP !=
3269 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3270 (eCSR_ENCRYPT_TYPE_AES !=
3271 pWextState->roamProfile.EncryptionType.encryptionType[0])
3272 )
3273 {
3274 /* if default key index is not same as previous one,
3275 * then update the default key index */
3276
3277 tCsrRoamSetKey setKey;
3278 v_U32_t roamId= 0xFF;
3279 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3280
3281 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3282 __func__, key_index);
3283
3284 Keys->defaultIndex = (u8)key_index;
3285 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3286 setKey.keyId = key_index;
3287 setKey.keyLength = Keys->KeyLength[key_index];
3288
3289 vos_mem_copy(&setKey.Key[0],
3290 &Keys->KeyMaterial[key_index][0],
3291 Keys->KeyLength[key_index]);
3292
3293 setKey.keyDirection = eSIR_TX_ONLY;
3294
3295 vos_mem_copy(setKey.peerMac,
3296 &pHddStaCtx->conn_info.bssId[0],
3297 WNI_CFG_BSSID_LEN);
3298
3299 setKey.encType =
3300 pWextState->roamProfile.EncryptionType.encryptionType[0];
3301
3302 /* issue set key request */
3303 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3304 pAdapter->sessionId, &setKey, &roamId );
3305
3306 if ( 0 != status )
3307 {
3308 hddLog(VOS_TRACE_LEVEL_ERROR,
3309 "%s: sme_RoamSetKey failed, returned %d", __func__,
3310 status);
3311 return -EINVAL;
3312 }
3313 }
3314 }
3315
3316 /* In SoftAp mode setting key direction for default mode */
3317 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3318 {
3319 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3320 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3321 (eCSR_ENCRYPT_TYPE_AES !=
3322 pWextState->roamProfile.EncryptionType.encryptionType[0])
3323 )
3324 {
3325 /* Saving key direction for default key index to TX default */
3326 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3327 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3328 }
3329 }
3330
3331 return status;
3332}
3333
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003334#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07003335/**
3336 * FUNCTION: wlan_hdd_cfg80211_set_channel
3337 * This function is used to set the channel number
3338 */
3339int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3340 struct ieee80211_channel *chan,
3341 enum nl80211_channel_type channel_type
3342 )
3343{
3344 v_U32_t num_ch = 0;
3345 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003346 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 int freq = chan->center_freq; /* freq is in MHZ */
3348
3349 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003350
3351 if( NULL == dev )
3352 {
3353 hddLog(VOS_TRACE_LEVEL_ERROR,
3354 "%s: Called with dev = NULL.\n", __func__);
3355 return -ENODEV;
3356 }
3357 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003358
3359 hddLog(VOS_TRACE_LEVEL_INFO,
3360 "%s: device_mode = %d freq = %d \n",__func__,
3361 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003362 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3363 {
3364 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3365 return -EAGAIN;
3366 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003367
3368 /*
3369 * Do freq to chan conversion
3370 * TODO: for 11a
3371 */
3372
3373 channel = ieee80211_frequency_to_channel(freq);
3374
3375 /* Check freq range */
3376 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3377 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3378 {
3379 hddLog(VOS_TRACE_LEVEL_ERROR,
3380 "%s: Channel [%d] is outside valid range from %d to %d\n",
3381 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3382 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3383 return -EINVAL;
3384 }
3385
3386 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3387
3388 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3389#ifdef WLAN_FEATURE_P2P
3390 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3391#endif
3392 )
3393 {
3394 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3395 {
3396 hddLog(VOS_TRACE_LEVEL_ERROR,
3397 "%s: Invalid Channel [%d] \n", __func__, channel);
3398 return -EINVAL;
3399 }
3400 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3401 "%s: set channel to [%d] for device mode =%d",
3402 __func__, channel,pAdapter->device_mode);
3403 }
3404 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3405#ifdef WLAN_FEATURE_P2P
3406 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3407#endif
3408 )
3409 {
3410 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3411 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3412 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3413
3414 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3415 {
3416 /* Link is up then return cant set channel*/
3417 hddLog( VOS_TRACE_LEVEL_ERROR,
3418 "%s: IBSS Associated, can't set the channel\n", __func__);
3419 return -EINVAL;
3420 }
3421
3422 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3423 pHddStaCtx->conn_info.operationChannel = channel;
3424 pRoamProfile->ChannelInfo.ChannelList =
3425 &pHddStaCtx->conn_info.operationChannel;
3426 }
3427 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3428#ifdef WLAN_FEATURE_P2P
3429 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3430#endif
3431 )
3432 {
3433 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3434
3435 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3436 {
3437 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3438
3439 /* If auto channel selection is configured as enable/ 1 then ignore
3440 channel set by supplicant
3441 */
3442 if ( cfg_param->apAutoChannelSelection )
3443 {
3444 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3445
3446 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3447 "%s: set channel to auto channel (0) for device mode =%d",
3448 __func__, pAdapter->device_mode);
3449 }
3450 }
3451 }
3452 else
3453 {
3454 hddLog(VOS_TRACE_LEVEL_FATAL,
3455 "%s: Invalid device mode failed to set valid channel", __func__);
3456 return -EINVAL;
3457 }
3458 EXIT();
3459 return 0;
3460}
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003461#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003462
3463
3464
3465/*
3466 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3467 * This function is used to inform the BSS details to nl80211 interface.
3468 */
3469static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3470 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3471{
3472 struct net_device *dev = pAdapter->dev;
3473 struct wireless_dev *wdev = dev->ieee80211_ptr;
3474 struct wiphy *wiphy = wdev->wiphy;
3475 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3476 int chan_no;
3477 int ie_length;
3478 const char *ie;
3479 unsigned int freq;
3480 struct ieee80211_channel *chan;
3481 int rssi = 0;
3482 struct cfg80211_bss *bss = NULL;
3483
3484 ENTER();
3485
3486 if( NULL == pBssDesc )
3487 {
3488 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3489 return bss;
3490 }
3491
3492 chan_no = pBssDesc->channelId;
3493 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3494 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3495
3496 if( NULL == ie )
3497 {
3498 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3499 return bss;
3500 }
3501
3502#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3503 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3504 {
3505 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3506 }
3507 else
3508 {
3509 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3510 }
3511#else
3512 freq = ieee80211_channel_to_frequency(chan_no);
3513#endif
3514
3515 chan = __ieee80211_get_channel(wiphy, freq);
3516
3517 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3518 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3519 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3520 if (bss == NULL)
3521 {
3522 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3523
3524 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3525 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3526 pBssDesc->capabilityInfo,
3527 pBssDesc->beaconInterval, ie, ie_length,
3528 rssi, GFP_KERNEL ));
3529}
3530 else
3531 {
3532 return bss;
3533 }
3534}
3535
3536
3537
3538/*
3539 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3540 * This function is used to inform the BSS details to nl80211 interface.
3541 */
3542struct cfg80211_bss*
3543wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3544 tSirBssDescription *bss_desc
3545 )
3546{
3547 /*
3548 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3549 already exists in bss data base of cfg80211 for that particular BSS ID.
3550 Using cfg80211_inform_bss_frame to update the bss entry instead of
3551 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3552 now there is no possibility to get the mgmt(probe response) frame from PE,
3553 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3554 cfg80211_inform_bss_frame.
3555 */
3556 struct net_device *dev = pAdapter->dev;
3557 struct wireless_dev *wdev = dev->ieee80211_ptr;
3558 struct wiphy *wiphy = wdev->wiphy;
3559 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003560#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3561 qcom_ie_age *qie_age = NULL;
3562 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3563#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003564 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003565#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003566 const char *ie =
3567 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3568 unsigned int freq;
3569 struct ieee80211_channel *chan;
3570 struct ieee80211_mgmt *mgmt =
3571 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3572 struct cfg80211_bss *bss_status = NULL;
3573 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3574 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003575#ifdef WLAN_OPEN_SOURCE
3576 struct timespec ts;
3577#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003578
3579 ENTER();
3580
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003581 if (!mgmt)
3582 return NULL;
3583
Jeff Johnson295189b2012-06-20 16:38:30 -07003584 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003585
3586#ifdef WLAN_OPEN_SOURCE
3587 /* Android does not want the timestamp from the frame.
3588 Instead it wants a monotonic increasing value */
3589 get_monotonic_boottime(&ts);
3590 mgmt->u.probe_resp.timestamp =
3591 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3592#else
3593 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003594 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3595 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003596
3597#endif
3598
Jeff Johnson295189b2012-06-20 16:38:30 -07003599 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3600 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003601
3602#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3603 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3604 /* Assuming this is the last IE, copy at the end */
3605 ie_length -=sizeof(qcom_ie_age);
3606 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3607 qie_age->element_id = QCOM_VENDOR_IE_ID;
3608 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3609 qie_age->oui_1 = QCOM_OUI1;
3610 qie_age->oui_2 = QCOM_OUI2;
3611 qie_age->oui_3 = QCOM_OUI3;
3612 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3613 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3614#endif
3615
Jeff Johnson295189b2012-06-20 16:38:30 -07003616 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3617
3618 mgmt->frame_control |=
3619 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3620
3621#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3622 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3623 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3624 {
3625 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3626 }
3627 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3628 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3629
3630 {
3631 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3632 }
3633 else
3634 {
3635 kfree(mgmt);
3636 return NULL;
3637 }
3638#else
3639 freq = ieee80211_channel_to_frequency(chan_no);
3640#endif
3641 chan = __ieee80211_get_channel(wiphy, freq);
3642
3643 /*To keep the rssi icon of the connected AP in the scan window
3644 *and the rssi icon of the wireless networks in sync
3645 * */
3646 if (( eConnectionState_Associated ==
3647 pAdapter->sessionCtx.station.conn_info.connState ) &&
3648 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3649 pAdapter->sessionCtx.station.conn_info.bssId,
3650 WNI_CFG_BSSID_LEN)))
3651 {
3652 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3653 rssi = (pAdapter->rssi * 100);
3654 }
3655 else
3656 {
3657 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3658 }
3659
3660 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3661 frame_len, rssi, GFP_KERNEL);
3662 kfree(mgmt);
3663 return bss_status;
3664}
3665
3666/*
3667 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3668 * This function is used to update the BSS data base of CFG8011
3669 */
3670struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3671 tCsrRoamInfo *pRoamInfo
3672 )
3673{
3674 tCsrRoamConnectedProfile roamProfile;
3675 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3676 struct cfg80211_bss *bss = NULL;
3677
3678 ENTER();
3679
3680 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3681 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3682
3683 if (NULL != roamProfile.pBssDesc)
3684 {
3685 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3686 &roamProfile);
3687
3688 if (NULL == bss)
3689 {
3690 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3691 __func__);
3692 }
3693
3694 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3695 }
3696 else
3697 {
3698 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3699 __func__);
3700 }
3701 return bss;
3702}
3703
3704/*
3705 * FUNCTION: wlan_hdd_cfg80211_update_bss
3706 */
3707static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3708 hdd_adapter_t *pAdapter
3709 )
3710{
3711 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3712 tCsrScanResultInfo *pScanResult;
3713 eHalStatus status = 0;
3714 tScanResultHandle pResult;
3715 struct cfg80211_bss *bss_status = NULL;
3716
3717 ENTER();
3718
3719 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3720 {
3721 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3722 return -EAGAIN;
3723 }
3724
3725 /*
3726 * start getting scan results and populate cgf80211 BSS database
3727 */
3728 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3729
3730 /* no scan results */
3731 if (NULL == pResult)
3732 {
3733 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3734 return status;
3735 }
3736
3737 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3738
3739 while (pScanResult)
3740 {
3741 /*
3742 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3743 * entry already exists in bss data base of cfg80211 for that
3744 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3745 * bss entry instead of cfg80211_inform_bss, But this call expects
3746 * mgmt packet as input. As of now there is no possibility to get
3747 * the mgmt(probe response) frame from PE, converting bss_desc to
3748 * ieee80211_mgmt(probe response) and passing to c
3749 * fg80211_inform_bss_frame.
3750 * */
3751
3752 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3753 &pScanResult->BssDescriptor);
3754
3755
3756 if (NULL == bss_status)
3757 {
3758 hddLog(VOS_TRACE_LEVEL_INFO,
3759 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3760 }
3761 else
3762 {
3763 cfg80211_put_bss(bss_status);
3764 }
3765
3766 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3767 }
3768
3769 sme_ScanResultPurge(hHal, pResult);
3770
3771 return 0;
3772}
3773
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003774void
3775hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3776{
3777 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003778 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3779 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3780 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003781} /****** end hddPrintMacAddr() ******/
3782
3783void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003784hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003785{
3786 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003787 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3788 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3789 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3790 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003791} /****** end hddPrintPmkId() ******/
3792
3793//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3794//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3795
3796//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3797//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3798
3799#define dump_bssid(bssid) \
3800 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003801 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3802 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3803 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003804 }
3805
3806#define dump_pmkid(pMac, pmkid) \
3807 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003808 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3809 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3810 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003811 }
3812
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003813#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003814/*
3815 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3816 * This function is used to notify the supplicant of a new PMKSA candidate.
3817 */
3818int wlan_hdd_cfg80211_pmksa_candidate_notify(
3819 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3820 int index, bool preauth )
3821{
Jeff Johnsone7245742012-09-05 17:12:55 -07003822#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003823 struct net_device *dev = pAdapter->dev;
3824
3825 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003826 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003827
3828 if( NULL == pRoamInfo )
3829 {
3830 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3831 return -EINVAL;
3832 }
3833
3834 dump_bssid(pRoamInfo->bssid);
3835 cfg80211_pmksa_candidate_notify(dev, index,
3836 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003837#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003838 return 0;
3839}
3840#endif //FEATURE_WLAN_LFR
3841
Jeff Johnson295189b2012-06-20 16:38:30 -07003842/*
3843 * FUNCTION: hdd_cfg80211_scan_done_callback
3844 * scanning callback function, called after finishing scan
3845 *
3846 */
3847static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3848 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3849{
3850 struct net_device *dev = (struct net_device *) pContext;
3851 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3852 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003853 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3854 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003855 struct cfg80211_scan_request *req = NULL;
3856 int ret = 0;
3857
3858 ENTER();
3859
3860 hddLog(VOS_TRACE_LEVEL_INFO,
3861 "%s called with halHandle = %p, pContext = %p,"
3862 "scanID = %d, returned status = %d\n",
3863 __func__, halHandle, pContext, (int) scanId, (int) status);
3864
3865 //Block on scan req completion variable. Can't wait forever though.
3866 ret = wait_for_completion_interruptible_timeout(
3867 &pScanInfo->scan_req_completion_event,
3868 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3869 if (!ret)
3870 {
3871 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003872 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003873 }
3874
3875 if(pScanInfo->mScanPending != VOS_TRUE)
3876 {
3877 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003878 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003879 }
3880
3881 /* Check the scanId */
3882 if (pScanInfo->scanId != scanId)
3883 {
3884 hddLog(VOS_TRACE_LEVEL_INFO,
3885 "%s called with mismatched scanId pScanInfo->scanId = %d "
3886 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3887 (int) scanId);
3888 }
3889
Jeff Johnson295189b2012-06-20 16:38:30 -07003890 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3891 pAdapter);
3892
3893 if (0 > ret)
3894 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3895
3896
3897 /* If any client wait scan result through WEXT
3898 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003899 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003900 {
3901 /* The other scan request waiting for current scan finish
3902 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003903 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003904 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003905 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003906 }
3907 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003908 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003909 {
3910 struct net_device *dev = pAdapter->dev;
3911 union iwreq_data wrqu;
3912 int we_event;
3913 char *msg;
3914
3915 memset(&wrqu, '\0', sizeof(wrqu));
3916 we_event = SIOCGIWSCAN;
3917 msg = NULL;
3918 wireless_send_event(dev, we_event, &wrqu, msg);
3919 }
3920 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003921 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003922
3923 /* Get the Scan Req */
3924 req = pAdapter->request;
3925
3926 if (!req)
3927 {
3928 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003929 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003930 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003931 }
3932
3933 /*
3934 * setting up 0, just in case.
3935 */
3936 req->n_ssids = 0;
3937 req->n_channels = 0;
3938 req->ie = 0;
3939
Jeff Johnson295189b2012-06-20 16:38:30 -07003940 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003941 /* Scan is no longer pending */
3942 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003943
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003944 /*
3945 * cfg80211_scan_done informing NL80211 about completion
3946 * of scanning
3947 */
3948 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003949 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003950
Jeff Johnsone7245742012-09-05 17:12:55 -07003951allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003952 /* release the wake lock at the end of the scan*/
3953 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003954
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003955 /* Acquire wakelock to handle the case where APP's tries to suspend
3956 * immediatly after the driver gets connect request(i.e after scan)
3957 * from supplicant, this result in app's is suspending and not able
3958 * to process the connect request to AP */
3959 hdd_allow_suspend_timeout(100);
3960
Jeff Johnson295189b2012-06-20 16:38:30 -07003961 EXIT();
3962 return 0;
3963}
3964
3965/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08003966 * FUNCTION: hdd_isScanAllowed
3967 * Go through each adapter and check if scan allowed
3968 *
3969 */
3970v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
3971{
3972 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3973 hdd_station_ctx_t *pHddStaCtx = NULL;
3974 hdd_adapter_t *pAdapter = NULL;
3975 VOS_STATUS status = 0;
3976 v_U8_t staId = 0;
3977 v_U8_t *staMac = NULL;
3978
3979 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3980
3981 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3982 {
3983 pAdapter = pAdapterNode->pAdapter;
3984
3985 if( pAdapter )
3986 {
3987 hddLog(VOS_TRACE_LEVEL_INFO,
3988 "%s: Adapter with device mode %d exists",
3989 __func__, pAdapter->device_mode);
3990 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3991 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3992 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
3993 {
3994 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3995 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
3996 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
3997 {
3998 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
3999 hddLog(VOS_TRACE_LEVEL_ERROR,
4000 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4001 "middle of WPS/EAPOL exchange.", __func__,
4002 staMac[0], staMac[1], staMac[2],
4003 staMac[3], staMac[4], staMac[5]);
4004 return VOS_FALSE;
4005 }
4006 }
4007 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4008 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4009 {
4010 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4011 {
4012 if ((pAdapter->aStaInfo[staId].isUsed) &&
4013 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4014 {
4015 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4016
4017 hddLog(VOS_TRACE_LEVEL_ERROR,
4018 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4019 "middle of WPS/EAPOL exchange.", __func__,
4020 staMac[0], staMac[1], staMac[2],
4021 staMac[3], staMac[4], staMac[5]);
4022 return VOS_FALSE;
4023 }
4024 }
4025 }
4026 }
4027 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4028 pAdapterNode = pNext;
4029 }
4030 hddLog(VOS_TRACE_LEVEL_INFO,
4031 "%s: Scan allowed", __func__);
4032 return VOS_TRUE;
4033}
4034
4035/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004036 * FUNCTION: wlan_hdd_cfg80211_scan
4037 * this scan respond to scan trigger and update cfg80211 scan database
4038 * later, scan dump command can be used to recieve scan results
4039 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004040int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4041#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4042 struct net_device *dev,
4043#endif
4044 struct cfg80211_scan_request *request)
4045{
4046#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4047 struct net_device *dev = request->wdev->netdev;
4048#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004049 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4050 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4051 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4052 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4053 tCsrScanRequest scanRequest;
4054 tANI_U8 *channelList = NULL, i;
4055 v_U32_t scanId = 0;
4056 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004057 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004058#ifdef WLAN_FEATURE_P2P
4059 v_U8_t* pP2pIe = NULL;
4060#endif
4061
4062 ENTER();
4063
4064 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4065 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004066
4067 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4068 (eConnectionState_Connecting ==
4069 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4070 {
4071 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004072 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4073 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004074 return -EBUSY;
4075 }
4076
Jeff Johnson295189b2012-06-20 16:38:30 -07004077#ifdef WLAN_BTAMP_FEATURE
4078 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004079 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004081 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004082 "%s: No scanning when AMP is on", __func__);
4083 return -EOPNOTSUPP;
4084 }
4085#endif
4086 //Scan on any other interface is not supported.
4087 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4088 {
4089 hddLog(VOS_TRACE_LEVEL_ERROR,
4090 "%s: Not scanning on device_mode = %d",
4091 __func__, pAdapter->device_mode);
4092 return -EOPNOTSUPP;
4093 }
4094
4095 if (TRUE == pScanInfo->mScanPending)
4096 {
4097 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4098 return -EBUSY;
4099 }
4100
4101 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4102 {
4103 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4104 "%s:LOGP in Progress. Ignore!!!", __func__);
4105 return -EAGAIN;
4106 }
4107
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004108 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4109 {
4110 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4111 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4112 return -EAGAIN;
4113 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004114 //Don't Allow Scan and return busy if Remain On
4115 //Channel and action frame is pending
4116 //Otherwise Cancel Remain On Channel and allow Scan
4117 //If no action frame pending
4118 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4119 {
4120 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4121 return -EBUSY;
4122 }
4123
Jeff Johnson295189b2012-06-20 16:38:30 -07004124 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4125 {
4126 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004127 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004128 return -EAGAIN;
4129 }
4130 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4131 {
4132 hddLog(VOS_TRACE_LEVEL_WARN,
4133 "%s: MAX TM Level Scan not allowed", __func__);
4134 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4135 return -EBUSY;
4136 }
4137 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4138
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004139 /* Check if scan is allowed at this point of time.
4140 */
4141 if (!hdd_isScanAllowed(pHddCtx))
4142 {
4143 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4144 return -EBUSY;
4145 }
4146
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4148
4149 if (NULL != request)
4150 {
4151 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4152 (int)request->n_ssids);
4153
4154 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4155 * Becasue of this, driver is assuming that this is not wildcard scan and so
4156 * is not aging out the scan results.
4157 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004158 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004159 {
4160 request->n_ssids = 0;
4161 }
4162
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004163 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004164 {
4165 tCsrSSIDInfo *SsidInfo;
4166 int j;
4167 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4168 /* Allocate num_ssid tCsrSSIDInfo structure */
4169 SsidInfo = scanRequest.SSIDs.SSIDList =
4170 ( tCsrSSIDInfo *)vos_mem_malloc(
4171 request->n_ssids*sizeof(tCsrSSIDInfo));
4172
4173 if(NULL == scanRequest.SSIDs.SSIDList)
4174 {
4175 hddLog(VOS_TRACE_LEVEL_ERROR,
4176 "memory alloc failed SSIDInfo buffer");
4177 return -ENOMEM;
4178 }
4179
4180 /* copy all the ssid's and their length */
4181 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4182 {
4183 /* get the ssid length */
4184 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4185 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4186 SsidInfo->SSID.length);
4187 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4188 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4189 j, SsidInfo->SSID.ssId);
4190 }
4191 /* set the scan type to active */
4192 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4193 }
4194 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4195 {
4196 /* set the scan type to active */
4197 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4198 }
4199 else
4200 {
4201 /*Set the scan type to default type, in this case it is ACTIVE*/
4202 scanRequest.scanType = pScanInfo->scan_mode;
4203 }
4204 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4205 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4206 }
4207 else
4208 {
4209 /* set the scan type to active */
4210 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4211 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4212
4213 /* set min and max channel time to zero */
4214 scanRequest.minChnTime = 0;
4215 scanRequest.maxChnTime = 0;
4216 }
4217
4218 /* set BSSType to default type */
4219 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4220
4221 /*TODO: scan the requested channels only*/
4222
4223 /*Right now scanning all the channels */
4224 if( request )
4225 {
4226 if( request->n_channels )
4227 {
4228 channelList = vos_mem_malloc( request->n_channels );
4229 if( NULL == channelList )
4230 {
4231 status = -ENOMEM;
4232 goto free_mem;
4233 }
4234
4235 for( i = 0 ; i < request->n_channels ; i++ )
4236 channelList[i] = request->channels[i]->hw_value;
4237 }
4238
4239 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4240 scanRequest.ChannelInfo.ChannelList = channelList;
4241
4242 /* set requestType to full scan */
4243 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004244
4245 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4246 * search (Flush on both full scan and social scan but not on single
4247 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4248 */
4249
4250 /* Supplicant does single channel scan after 8-way handshake
4251 * and in that case driver shoudnt flush scan results. If
4252 * driver flushes the scan results here and unfortunately if
4253 * the AP doesnt respond to our probe req then association
4254 * fails which is not desired
4255 */
4256
4257 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4258 {
4259 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4260 pAdapter->sessionId );
4261 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004262
4263 if( request->ie_len )
4264 {
4265 /* save this for future association (join requires this) */
4266 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4267 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4268 pScanInfo->scanAddIE.length = request->ie_len;
4269
4270 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004271 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4272 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004273 )
4274 {
4275 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4276 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4277 }
4278
4279 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4280 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4281
4282#ifdef WLAN_FEATURE_P2P
4283 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4284 request->ie_len);
4285 if (pP2pIe != NULL)
4286 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004287#ifdef WLAN_FEATURE_P2P_DEBUG
4288 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4289 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4290 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4291 {
4292 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4293 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4294 "Go nego completed to Connection is started");
4295 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4296 "for 8way Handshake");
4297 }
4298 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4299 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4300 {
4301 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4302 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4303 "Disconnected state to Connection is started");
4304 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4305 "for 4way Handshake");
4306 }
4307#endif
4308
Jeff Johnsone7245742012-09-05 17:12:55 -07004309 /* no_cck will be set during p2p find to disable 11b rates */
4310 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004311 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004312 hddLog(VOS_TRACE_LEVEL_INFO,
4313 "%s: This is a P2P Search", __func__);
4314 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004315
Jeff Johnsone7245742012-09-05 17:12:55 -07004316 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4317 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004318 /* set requestType to P2P Discovery */
4319 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004320 }
4321
4322 /*
4323 Skip Dfs Channel in case of P2P Search
4324 if it is set in ini file
4325 */
4326 if(cfg_param->skipDfsChnlInP2pSearch)
4327 {
4328 scanRequest.skipDfsChnlInP2pSearch = 1;
4329 }
4330 else
4331 {
4332 scanRequest.skipDfsChnlInP2pSearch = 0;
4333 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004334
Jeff Johnson295189b2012-06-20 16:38:30 -07004335 }
4336 }
4337#endif
4338 }
4339 }
4340
4341 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4342
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004343 /* acquire the wakelock to avoid the apps suspend during the scan. To
4344 * address the following issues.
4345 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4346 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4347 * for long time, this result in apps running at full power for long time.
4348 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4349 * be stuck in full power because of resume BMPS
4350 */
4351 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004352
4353 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004354 pAdapter->sessionId, &scanRequest, &scanId,
4355 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004356
Jeff Johnson295189b2012-06-20 16:38:30 -07004357 if (eHAL_STATUS_SUCCESS != status)
4358 {
4359 hddLog(VOS_TRACE_LEVEL_ERROR,
4360 "%s: sme_ScanRequest returned error %d", __func__, status);
4361 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004362 if(eHAL_STATUS_RESOURCES == status)
4363 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004364 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 -07004365 status = -EBUSY;
4366 } else {
4367 status = -EIO;
4368 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004369 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 goto free_mem;
4371 }
4372
4373 pScanInfo->mScanPending = TRUE;
4374 pAdapter->request = request;
4375 pScanInfo->scanId = scanId;
4376
4377 complete(&pScanInfo->scan_req_completion_event);
4378
4379free_mem:
4380 if( scanRequest.SSIDs.SSIDList )
4381 {
4382 vos_mem_free(scanRequest.SSIDs.SSIDList);
4383 }
4384
4385 if( channelList )
4386 vos_mem_free( channelList );
4387
4388 EXIT();
4389
4390 return status;
4391}
4392
4393/*
4394 * FUNCTION: wlan_hdd_cfg80211_connect_start
4395 * This function is used to start the association process
4396 */
4397int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004398 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004399{
4400 int status = 0;
4401 hdd_wext_state_t *pWextState;
4402 v_U32_t roamId;
4403 tCsrRoamProfile *pRoamProfile;
4404 eMib_dot11DesiredBssType connectedBssType;
4405 eCsrAuthType RSNAuthType;
4406
4407 ENTER();
4408
4409 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4410
4411 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4412 {
4413 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4414 return -EINVAL;
4415 }
4416
4417 pRoamProfile = &pWextState->roamProfile;
4418
4419 if (pRoamProfile)
4420 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004421 int ret = 0;
4422 hdd_station_ctx_t *pHddStaCtx;
4423 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4424 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4425
4426 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4427 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4428 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004429 {
4430 /* Issue disconnect to CSR */
4431 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4432 if( eHAL_STATUS_SUCCESS ==
4433 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4434 pAdapter->sessionId,
4435 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4436 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004437 ret = wait_for_completion_interruptible_timeout(
4438 &pAdapter->disconnect_comp_var,
4439 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4440 if (0 == ret)
4441 {
4442 VOS_ASSERT(0);
4443 }
4444 }
4445 }
4446 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4447 {
4448 ret = wait_for_completion_interruptible_timeout(
4449 &pAdapter->disconnect_comp_var,
4450 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4451 if (0 == ret)
4452 {
4453 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004454 }
4455 }
4456
4457 if (HDD_WMM_USER_MODE_NO_QOS ==
4458 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4459 {
4460 /*QoS not enabled in cfg file*/
4461 pRoamProfile->uapsd_mask = 0;
4462 }
4463 else
4464 {
4465 /*QoS enabled, update uapsd mask from cfg file*/
4466 pRoamProfile->uapsd_mask =
4467 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4468 }
4469
4470 pRoamProfile->SSIDs.numOfSSIDs = 1;
4471 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4472 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4473 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4474 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4475 ssid, ssid_len);
4476
4477 if (bssid)
4478 {
4479 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4480 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4481 WNI_CFG_BSSID_LEN);
4482 /* Save BSSID in seperate variable as well, as RoamProfile
4483 BSSID is getting zeroed out in the association process. And in
4484 case of join failure we should send valid BSSID to supplicant
4485 */
4486 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4487 WNI_CFG_BSSID_LEN);
4488 }
4489
4490 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4491 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4492 {
4493 /*set gen ie*/
4494 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4495 /*set auth*/
4496 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4497 }
4498 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4499 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4500 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4501 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4502 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4503 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4504 )
4505 {
4506 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4507 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4508 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4509 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4510 eCSR_AUTH_TYPE_AUTOSWITCH;
4511 pWextState->roamProfile.AuthType.authType[0] =
4512 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4513 }
4514#ifdef FEATURE_WLAN_WAPI
4515 if (pAdapter->wapi_info.nWapiMode)
4516 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004517 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004518 switch (pAdapter->wapi_info.wapiAuthMode)
4519 {
4520 case WAPI_AUTH_MODE_PSK:
4521 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004522 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004523 pAdapter->wapi_info.wapiAuthMode);
4524 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4525 break;
4526 }
4527 case WAPI_AUTH_MODE_CERT:
4528 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004529 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004530 pAdapter->wapi_info.wapiAuthMode);
4531 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4532 break;
4533 }
4534 } // End of switch
4535 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4536 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4537 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004538 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004539 pRoamProfile->AuthType.numEntries = 1;
4540 pRoamProfile->EncryptionType.numEntries = 1;
4541 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4542 pRoamProfile->mcEncryptionType.numEntries = 1;
4543 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4544 }
4545 }
4546#endif /* FEATURE_WLAN_WAPI */
4547 pRoamProfile->csrPersona = pAdapter->device_mode;
4548
Jeff Johnson32d95a32012-09-10 13:15:23 -07004549 if( operatingChannel )
4550 {
4551 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4552 pRoamProfile->ChannelInfo.numOfChannels = 1;
4553 }
4554
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004555 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4556 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4557 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4558 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004559 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4560 */
4561 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4562 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4563 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004564
Jeff Johnson295189b2012-06-20 16:38:30 -07004565 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4566 pAdapter->sessionId, pRoamProfile, &roamId);
4567
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004568 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304569 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4570
4571 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004572 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4573 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4574 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304575 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004576 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304577 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004578
4579 pRoamProfile->ChannelInfo.ChannelList = NULL;
4580 pRoamProfile->ChannelInfo.numOfChannels = 0;
4581
Jeff Johnson295189b2012-06-20 16:38:30 -07004582 }
4583 else
4584 {
4585 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4586 return -EINVAL;
4587 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004588 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004589 return status;
4590}
4591
4592/*
4593 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4594 * This function is used to set the authentication type (OPEN/SHARED).
4595 *
4596 */
4597static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4598 enum nl80211_auth_type auth_type)
4599{
4600 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4601 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4602
4603 ENTER();
4604
4605 /*set authentication type*/
4606 switch (auth_type)
4607 {
4608 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4609 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004610#ifdef WLAN_FEATURE_VOWIFI_11R
4611 case NL80211_AUTHTYPE_FT:
4612#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 hddLog(VOS_TRACE_LEVEL_INFO,
4614 "%s: set authentication type to OPEN", __func__);
4615 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4616 break;
4617
4618 case NL80211_AUTHTYPE_SHARED_KEY:
4619 hddLog(VOS_TRACE_LEVEL_INFO,
4620 "%s: set authentication type to SHARED", __func__);
4621 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4622 break;
4623#ifdef FEATURE_WLAN_CCX
4624 case NL80211_AUTHTYPE_NETWORK_EAP:
4625 hddLog(VOS_TRACE_LEVEL_INFO,
4626 "%s: set authentication type to CCKM WPA", __func__);
4627 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4628 break;
4629#endif
4630
4631
4632 default:
4633 hddLog(VOS_TRACE_LEVEL_ERROR,
4634 "%s: Unsupported authentication type %d", __func__,
4635 auth_type);
4636 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4637 return -EINVAL;
4638 }
4639
4640 pWextState->roamProfile.AuthType.authType[0] =
4641 pHddStaCtx->conn_info.authType;
4642 return 0;
4643}
4644
4645/*
4646 * FUNCTION: wlan_hdd_set_akm_suite
4647 * This function is used to set the key mgmt type(PSK/8021x).
4648 *
4649 */
4650static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4651 u32 key_mgmt
4652 )
4653{
4654 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4655 ENTER();
4656
4657 /*set key mgmt type*/
4658 switch(key_mgmt)
4659 {
4660 case WLAN_AKM_SUITE_PSK:
4661 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4662 __func__);
4663 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4664 break;
4665
4666 case WLAN_AKM_SUITE_8021X:
4667 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4668 __func__);
4669 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4670 break;
4671#ifdef FEATURE_WLAN_CCX
4672#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4673#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4674 case WLAN_AKM_SUITE_CCKM:
4675 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4676 __func__);
4677 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4678 break;
4679#endif
4680
4681 default:
4682 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4683 __func__, key_mgmt);
4684 return -EINVAL;
4685
4686 }
4687 return 0;
4688}
4689
4690/*
4691 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4692 * This function is used to set the encryption type
4693 * (NONE/WEP40/WEP104/TKIP/CCMP).
4694 */
4695static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4696 u32 cipher,
4697 bool ucast
4698 )
4699{
4700 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4701 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4702 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4703
4704 ENTER();
4705
4706 if (!cipher)
4707 {
4708 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4709 __func__, cipher);
4710 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4711 }
4712 else
4713 {
4714
4715 /*set encryption method*/
4716 switch (cipher)
4717 {
4718 case IW_AUTH_CIPHER_NONE:
4719 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4720 break;
4721
4722 case WLAN_CIPHER_SUITE_WEP40:
4723 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4724 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4725 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4726 else
4727 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4728 break;
4729
4730 case WLAN_CIPHER_SUITE_WEP104:
4731 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4732 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4733 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4734 else
4735 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4736 break;
4737
4738 case WLAN_CIPHER_SUITE_TKIP:
4739 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4740 break;
4741
4742 case WLAN_CIPHER_SUITE_CCMP:
4743 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4744 break;
4745#ifdef FEATURE_WLAN_WAPI
4746 case WLAN_CIPHER_SUITE_SMS4:
4747 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4748 break;
4749#endif
4750
4751#ifdef FEATURE_WLAN_CCX
4752 case WLAN_CIPHER_SUITE_KRK:
4753 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4754 break;
4755#endif
4756 default:
4757 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4758 __func__, cipher);
4759 return -EOPNOTSUPP;
4760 }
4761 }
4762
4763 if (ucast)
4764 {
4765 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4766 __func__, encryptionType);
4767 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4768 pWextState->roamProfile.EncryptionType.numEntries = 1;
4769 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4770 encryptionType;
4771 }
4772 else
4773 {
4774 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4775 __func__, encryptionType);
4776 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4777 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4778 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4779 }
4780
4781 return 0;
4782}
4783
4784
4785/*
4786 * FUNCTION: wlan_hdd_cfg80211_set_ie
4787 * This function is used to parse WPA/RSN IE's.
4788 */
4789int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4790 u8 *ie,
4791 size_t ie_len
4792 )
4793{
4794 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4795 u8 *genie = ie;
4796 v_U16_t remLen = ie_len;
4797#ifdef FEATURE_WLAN_WAPI
4798 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4799 u16 *tmp;
4800 v_U16_t akmsuiteCount;
4801 int *akmlist;
4802#endif
4803 ENTER();
4804
4805 /* clear previous assocAddIE */
4806 pWextState->assocAddIE.length = 0;
4807 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4808
4809 while (remLen >= 2)
4810 {
4811 v_U16_t eLen = 0;
4812 v_U8_t elementId;
4813 elementId = *genie++;
4814 eLen = *genie++;
4815 remLen -= 2;
4816
4817 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4818 __func__, elementId, eLen);
4819
4820 switch ( elementId )
4821 {
4822 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004823 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 -07004824 {
4825 hddLog(VOS_TRACE_LEVEL_ERROR,
4826 "%s: Invalid WPA IE", __func__);
4827 return -EINVAL;
4828 }
4829 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4830 {
4831 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4832 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4833 __func__, eLen + 2);
4834
4835 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4836 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004837 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4838 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004839 VOS_ASSERT(0);
4840 return -ENOMEM;
4841 }
4842 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4843 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4844 pWextState->assocAddIE.length += eLen + 2;
4845
4846 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4847 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4848 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4849 }
4850 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4851 {
4852 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4853 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4854 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4855 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4856 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4857 }
4858#ifdef WLAN_FEATURE_P2P
4859 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4860 P2P_OUI_TYPE_SIZE))
4861 /*Consider P2P IE, only for P2P Client */
4862 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4863 {
4864 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4865 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4866 __func__, eLen + 2);
4867
4868 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4869 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004870 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4871 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004872 VOS_ASSERT(0);
4873 return -ENOMEM;
4874 }
4875 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4876 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4877 pWextState->assocAddIE.length += eLen + 2;
4878
4879 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4880 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4881 }
4882#endif
4883#ifdef WLAN_FEATURE_WFD
4884 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4885 WFD_OUI_TYPE_SIZE))
4886 /*Consider WFD IE, only for P2P Client */
4887 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4888 {
4889 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4890 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4891 __func__, eLen + 2);
4892
4893 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4894 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004895 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4896 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004897 VOS_ASSERT(0);
4898 return -ENOMEM;
4899 }
4900 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4901 // WPS IE + P2P IE + WFD IE
4902 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4903 pWextState->assocAddIE.length += eLen + 2;
4904
4905 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4906 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4907 }
4908#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004909 /* Appending HS 2.0 Indication Element in Assiciation Request */
4910 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004911 HS20_OUI_TYPE_SIZE)) )
4912 {
4913 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4914 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4915 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004916
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004917 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4918 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004919 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4920 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004921 VOS_ASSERT(0);
4922 return -ENOMEM;
4923 }
4924 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4925 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004926
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004927 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4928 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4929 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004930
Jeff Johnson295189b2012-06-20 16:38:30 -07004931 break;
4932 case DOT11F_EID_RSN:
4933 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4934 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4935 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4936 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4937 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4938 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004939 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4940 case DOT11F_EID_EXTCAP:
4941 {
4942 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4943 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4944 __func__, eLen + 2);
4945
4946 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4947 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004948 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4949 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004950 VOS_ASSERT(0);
4951 return -ENOMEM;
4952 }
4953 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4954 pWextState->assocAddIE.length += eLen + 2;
4955
4956 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4957 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4958 break;
4959 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004960#ifdef FEATURE_WLAN_WAPI
4961 case WLAN_EID_WAPI:
4962 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4963 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4964 pAdapter->wapi_info.nWapiMode);
4965 tmp = (u16 *)ie;
4966 tmp = tmp + 2; // Skip element Id and Len, Version
4967 akmsuiteCount = WPA_GET_LE16(tmp);
4968 tmp = tmp + 1;
4969 akmlist = (int *)(tmp);
4970 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4971 {
4972 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4973 }
4974 else
4975 {
4976 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4977 VOS_ASSERT(0);
4978 return -EINVAL;
4979 }
4980
4981 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4982 {
4983 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004984 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4986 }
4987 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4988 {
4989 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004990 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004991 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4992 }
4993 break;
4994#endif
4995 default:
4996 hddLog (VOS_TRACE_LEVEL_ERROR,
4997 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004998 /* when Unknown IE is received we should break and continue
4999 * to the next IE in the buffer instead we were returning
5000 * so changing this to break */
5001 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005002 }
5003 genie += eLen;
5004 remLen -= eLen;
5005 }
5006 EXIT();
5007 return 0;
5008}
5009
5010/*
5011 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5012 * This function is used to initialize the security
5013 * parameters during connect operation.
5014 */
5015int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5016 struct cfg80211_connect_params *req
5017 )
5018{
5019 int status = 0;
5020 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5021 ENTER();
5022
5023 /*set wpa version*/
5024 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5025
5026 if (req->crypto.wpa_versions)
5027 {
5028 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5029 && ( (req->ie_len)
5030 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5031 // Make sure that it is including a WPA IE.
5032 /* Currently NL is putting WPA version 1 even for open,
5033 * since p2p ie is also put in same buffer.
5034 * */
5035 {
5036 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5037 }
5038 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5039 {
5040 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5041 }
5042 }
5043
5044 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5045 pWextState->wpaVersion);
5046
5047 /*set authentication type*/
5048 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5049
5050 if (0 > status)
5051 {
5052 hddLog(VOS_TRACE_LEVEL_ERROR,
5053 "%s: failed to set authentication type ", __func__);
5054 return status;
5055 }
5056
5057 /*set key mgmt type*/
5058 if (req->crypto.n_akm_suites)
5059 {
5060 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5061 if (0 > status)
5062 {
5063 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5064 __func__);
5065 return status;
5066 }
5067 }
5068
5069 /*set pairwise cipher type*/
5070 if (req->crypto.n_ciphers_pairwise)
5071 {
5072 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5073 req->crypto.ciphers_pairwise[0], true);
5074 if (0 > status)
5075 {
5076 hddLog(VOS_TRACE_LEVEL_ERROR,
5077 "%s: failed to set unicast cipher type", __func__);
5078 return status;
5079 }
5080 }
5081 else
5082 {
5083 /*Reset previous cipher suite to none*/
5084 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5085 if (0 > status)
5086 {
5087 hddLog(VOS_TRACE_LEVEL_ERROR,
5088 "%s: failed to set unicast cipher type", __func__);
5089 return status;
5090 }
5091 }
5092
5093 /*set group cipher type*/
5094 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5095 false);
5096
5097 if (0 > status)
5098 {
5099 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5100 __func__);
5101 return status;
5102 }
5103
5104 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5105 if (req->ie_len)
5106 {
5107 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5108 if ( 0 > status)
5109 {
5110 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5111 __func__);
5112 return status;
5113 }
5114 }
5115
5116 /*incase of WEP set default key information*/
5117 if (req->key && req->key_len)
5118 {
5119 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5120 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5121 )
5122 {
5123 if ( IW_AUTH_KEY_MGMT_802_1X
5124 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5125 {
5126 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5127 __func__);
5128 return -EOPNOTSUPP;
5129 }
5130 else
5131 {
5132 u8 key_len = req->key_len;
5133 u8 key_idx = req->key_idx;
5134
5135 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5136 && (CSR_MAX_NUM_KEY > key_idx)
5137 )
5138 {
5139 hddLog(VOS_TRACE_LEVEL_INFO,
5140 "%s: setting default wep key, key_idx = %hu key_len %hu",
5141 __func__, key_idx, key_len);
5142 vos_mem_copy(
5143 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5144 req->key, key_len);
5145 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5146 (u8)key_len;
5147 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5148 }
5149 }
5150 }
5151 }
5152
5153 return status;
5154}
5155
5156/*
5157 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5158 * This function is used to initialize the security
5159 * parameters during connect operation.
5160 */
5161static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5162 struct net_device *ndev,
5163 struct cfg80211_connect_params *req
5164 )
5165{
5166 int status = 0;
5167 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5168 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5169 hdd_context_t *pHddCtx = NULL;
5170
5171 ENTER();
5172
5173 hddLog(VOS_TRACE_LEVEL_INFO,
5174 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5175
5176 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5177 {
5178 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5179 "%s:LOGP in Progress. Ignore!!!", __func__);
5180 return -EAGAIN;
5181 }
5182
5183#ifdef WLAN_BTAMP_FEATURE
5184 //Infra connect not supported when AMP traffic is on.
5185 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5186 {
5187 hddLog(VOS_TRACE_LEVEL_ERROR,
5188 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005189 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005190 }
5191#endif
5192 /*initialise security parameters*/
5193 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5194
5195 if ( 0 > status)
5196 {
5197 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5198 __func__);
5199 return status;
5200 }
5201
5202 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005203 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005204 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5205 (vos_concurrent_sessions_running()))
5206 {
5207 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5208
5209 if (NULL != pVosContext)
5210 {
5211 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5212 if(NULL != pHddCtx)
5213 {
5214 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5215 }
5216 }
5217 }
5218
Mohit Khanna765234a2012-09-11 15:08:35 -07005219 if ( req->channel )
5220 {
5221 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5222 req->ssid_len, req->bssid,
5223 req->channel->hw_value);
5224 }
5225 else
5226 {
5227 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5228 req->ssid_len, req->bssid,
5229 0);
5230 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005231
5232 if (0 > status)
5233 {
5234 //ReEnable BMPS if disabled
5235 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5236 (NULL != pHddCtx))
5237 {
5238 //ReEnable Bmps and Imps back
5239 hdd_enable_bmps_imps(pHddCtx);
5240 }
5241
5242 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5243 return status;
5244 }
5245 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5246 EXIT();
5247 return status;
5248}
5249
5250
5251/*
5252 * FUNCTION: wlan_hdd_cfg80211_disconnect
5253 * This function is used to issue a disconnect request to SME
5254 */
5255static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5256 struct net_device *dev,
5257 u16 reason
5258 )
5259{
5260 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5261 tCsrRoamProfile *pRoamProfile =
5262 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5263 int status = 0;
5264 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5265
5266 ENTER();
5267
5268 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5269 __func__,pAdapter->device_mode);
5270
5271 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5272 __func__, reason);
5273
5274 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5275 {
5276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5277 "%s:LOGP in Progress. Ignore!!!",__func__);
5278 return -EAGAIN;
5279 }
5280 if (NULL != pRoamProfile)
5281 {
5282 /*issue disconnect request to SME, if station is in connected state*/
5283 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5284 {
5285 eCsrRoamDisconnectReason reasonCode =
5286 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5287 switch(reason)
5288 {
5289 case WLAN_REASON_MIC_FAILURE:
5290 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5291 break;
5292
5293 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5294 case WLAN_REASON_DISASSOC_AP_BUSY:
5295 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5296 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5297 break;
5298
5299 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5300 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5301 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5302 break;
5303
5304 case WLAN_REASON_DEAUTH_LEAVING:
5305 default:
5306 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5307 break;
5308 }
5309 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5310 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5311 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5312
5313 /*issue disconnect*/
5314 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5315 pAdapter->sessionId, reasonCode);
5316
5317 if ( 0 != status)
5318 {
5319 hddLog(VOS_TRACE_LEVEL_ERROR,
5320 "%s csrRoamDisconnect failure, returned %d \n",
5321 __func__, (int)status );
5322 return -EINVAL;
5323 }
5324
5325 wait_for_completion_interruptible_timeout(
5326 &pAdapter->disconnect_comp_var,
5327 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5328
5329
5330 /*stop tx queues*/
5331 netif_tx_disable(dev);
5332 netif_carrier_off(dev);
5333 }
5334 }
5335 else
5336 {
5337 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5338 }
5339
5340 return status;
5341}
5342
5343/*
5344 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5345 * This function is used to initialize the security
5346 * settings in IBSS mode.
5347 */
5348static int wlan_hdd_cfg80211_set_privacy_ibss(
5349 hdd_adapter_t *pAdapter,
5350 struct cfg80211_ibss_params *params
5351 )
5352{
5353 int status = 0;
5354 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5355 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5356 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5357
5358 ENTER();
5359
5360 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5361
5362 if (params->ie_len && ( NULL != params->ie) )
5363 {
5364 if (WLAN_EID_RSN == params->ie[0])
5365 {
5366 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5367 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5368 }
5369 else
5370 {
5371 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5372 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5373 }
5374 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5375
5376 if (0 > status)
5377 {
5378 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5379 __func__);
5380 return status;
5381 }
5382 }
5383
5384 pWextState->roamProfile.AuthType.authType[0] =
5385 pHddStaCtx->conn_info.authType =
5386 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5387
5388 if (params->privacy)
5389 {
5390 /* Security enabled IBSS, At this time there is no information available
5391 * about the security paramters, so initialise the encryption type to
5392 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5393 * The correct security parameters will be updated later in
5394 * wlan_hdd_cfg80211_add_key */
5395 /* Hal expects encryption type to be set inorder
5396 *enable privacy bit in beacons */
5397
5398 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5399 }
5400
5401 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5402 pWextState->roamProfile.EncryptionType.numEntries = 1;
5403 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5404
5405 return status;
5406}
5407
5408/*
5409 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5410 * This function is used to create/join an IBSS
5411 */
5412static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5413 struct net_device *dev,
5414 struct cfg80211_ibss_params *params
5415 )
5416{
5417 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5418 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5419 tCsrRoamProfile *pRoamProfile;
5420 int status;
5421 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5422
5423 ENTER();
5424
5425 hddLog(VOS_TRACE_LEVEL_INFO,
5426 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5427
5428 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5429 {
5430 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5431 "%s:LOGP in Progress. Ignore!!!", __func__);
5432 return -EAGAIN;
5433 }
5434
5435 if (NULL == pWextState)
5436 {
5437 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5438 __func__);
5439 return -EIO;
5440 }
5441
5442 pRoamProfile = &pWextState->roamProfile;
5443
5444 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5445 {
5446 hddLog (VOS_TRACE_LEVEL_ERROR,
5447 "%s Interface type is not set to IBSS \n", __func__);
5448 return -EINVAL;
5449 }
5450
5451 /* Set Channel */
5452 if (NULL != params->channel)
5453 {
5454 u8 channelNum;
5455 if (IEEE80211_BAND_5GHZ == params->channel->band)
5456 {
5457 hddLog(VOS_TRACE_LEVEL_ERROR,
5458 "%s: IBSS join is called with unsupported band %d",
5459 __func__, params->channel->band);
5460 return -EOPNOTSUPP;
5461 }
5462
5463 /* Get channel number */
5464 channelNum =
5465 ieee80211_frequency_to_channel(params->channel->center_freq);
5466
5467 /*TODO: use macro*/
5468 if (14 >= channelNum)
5469 {
5470 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5471 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5472 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5473 int indx;
5474
5475 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5476 validChan, &numChans))
5477 {
5478 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5479 __func__);
5480 return -EOPNOTSUPP;
5481 }
5482
5483 for (indx = 0; indx < numChans; indx++)
5484 {
5485 if (channelNum == validChan[indx])
5486 {
5487 break;
5488 }
5489 }
5490 if (indx >= numChans)
5491 {
5492 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5493 __func__, channelNum);
5494 return -EINVAL;
5495 }
5496 /* Set the Operational Channel */
5497 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5498 channelNum);
5499 pRoamProfile->ChannelInfo.numOfChannels = 1;
5500 pHddStaCtx->conn_info.operationChannel = channelNum;
5501 pRoamProfile->ChannelInfo.ChannelList =
5502 &pHddStaCtx->conn_info.operationChannel;
5503 }
5504 else
5505 {
5506 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5507 __func__, channelNum);
5508 return -EINVAL;
5509 }
5510 }
5511
5512 /* Initialize security parameters */
5513 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5514 if (status < 0)
5515 {
5516 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5517 __func__);
5518 return status;
5519 }
5520
5521 /* Issue connect start */
5522 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005523 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005524
5525 if (0 > status)
5526 {
5527 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5528 return status;
5529 }
5530
5531 return 0;
5532}
5533
5534/*
5535 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5536 * This function is used to leave an IBSS
5537 */
5538static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5539 struct net_device *dev
5540 )
5541{
5542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5543 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5544 tCsrRoamProfile *pRoamProfile;
5545
5546 ENTER();
5547
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005548 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5549 {
5550 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5551 "%s:LOGP in Progress. Ignore!!!", __func__);
5552 return -EAGAIN;
5553 }
5554
Jeff Johnson295189b2012-06-20 16:38:30 -07005555 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5556 if (NULL == pWextState)
5557 {
5558 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5559 __func__);
5560 return -EIO;
5561 }
5562
5563 pRoamProfile = &pWextState->roamProfile;
5564
5565 /* Issue disconnect only if interface type is set to IBSS */
5566 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5567 {
5568 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5569 __func__);
5570 return -EINVAL;
5571 }
5572
5573 /* Issue Disconnect request */
5574 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5575 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5576 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5577
5578 return 0;
5579}
5580
5581/*
5582 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5583 * This function is used to set the phy parameters
5584 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5585 */
5586static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5587 u32 changed)
5588{
5589 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5590 tHalHandle hHal = pHddCtx->hHal;
5591
5592 ENTER();
5593
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005594 if ( pHddCtx->isLogpInProgress )
5595 {
5596 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5597 "%s:LOGP in Progress. Ignore!!!", __func__);
5598 return -EAGAIN;
5599 }
5600
Jeff Johnson295189b2012-06-20 16:38:30 -07005601 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5602 {
5603 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5604 WNI_CFG_RTS_THRESHOLD_STAMAX :
5605 wiphy->rts_threshold;
5606
5607 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5608 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5609 {
5610 hddLog(VOS_TRACE_LEVEL_ERROR,
5611 "%s: Invalid RTS Threshold value %hu",
5612 __func__, rts_threshold);
5613 return -EINVAL;
5614 }
5615
5616 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5617 rts_threshold, ccmCfgSetCallback,
5618 eANI_BOOLEAN_TRUE))
5619 {
5620 hddLog(VOS_TRACE_LEVEL_ERROR,
5621 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5622 __func__, rts_threshold);
5623 return -EIO;
5624 }
5625
5626 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5627 rts_threshold);
5628 }
5629
5630 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5631 {
5632 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5633 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5634 wiphy->frag_threshold;
5635
5636 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5637 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5638 {
5639 hddLog(VOS_TRACE_LEVEL_ERROR,
5640 "%s: Invalid frag_threshold value %hu", __func__,
5641 frag_threshold);
5642 return -EINVAL;
5643 }
5644
5645 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5646 frag_threshold, ccmCfgSetCallback,
5647 eANI_BOOLEAN_TRUE))
5648 {
5649 hddLog(VOS_TRACE_LEVEL_ERROR,
5650 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5651 __func__, frag_threshold);
5652 return -EIO;
5653 }
5654
5655 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5656 frag_threshold);
5657 }
5658
5659 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5660 || (changed & WIPHY_PARAM_RETRY_LONG))
5661 {
5662 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5663 wiphy->retry_short :
5664 wiphy->retry_long;
5665
5666 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5667 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5668 {
5669 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5670 __func__, retry_value);
5671 return -EINVAL;
5672 }
5673
5674 if (changed & WIPHY_PARAM_RETRY_SHORT)
5675 {
5676 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5677 retry_value, ccmCfgSetCallback,
5678 eANI_BOOLEAN_TRUE))
5679 {
5680 hddLog(VOS_TRACE_LEVEL_ERROR,
5681 "%s: ccmCfgSetInt failed for long retry count %hu",
5682 __func__, retry_value);
5683 return -EIO;
5684 }
5685 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5686 __func__, retry_value);
5687 }
5688 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5689 {
5690 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5691 retry_value, ccmCfgSetCallback,
5692 eANI_BOOLEAN_TRUE))
5693 {
5694 hddLog(VOS_TRACE_LEVEL_ERROR,
5695 "%s: ccmCfgSetInt failed for short retry count %hu",
5696 __func__, retry_value);
5697 return -EIO;
5698 }
5699 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5700 __func__, retry_value);
5701 }
5702 }
5703
5704 return 0;
5705}
5706
5707/*
5708 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5709 * This function is used to set the txpower
5710 */
5711static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5712#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5713 enum tx_power_setting type,
5714#else
5715 enum nl80211_tx_power_setting type,
5716#endif
5717 int dbm)
5718{
5719 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5720 tHalHandle hHal = pHddCtx->hHal;
5721 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5722 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5723
5724 ENTER();
5725
5726 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5727 dbm, ccmCfgSetCallback,
5728 eANI_BOOLEAN_TRUE))
5729 {
5730 hddLog(VOS_TRACE_LEVEL_ERROR,
5731 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5732 return -EIO;
5733 }
5734
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005735 if ( pHddCtx->isLogpInProgress )
5736 {
5737 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5738 "%s:LOGP in Progress. Ignore!!!", __func__);
5739 return -EAGAIN;
5740 }
5741
Jeff Johnson295189b2012-06-20 16:38:30 -07005742 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5743 dbm);
5744
5745 switch(type)
5746 {
5747 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5748 /* Fall through */
5749 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5750 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5751 {
5752 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5753 __func__);
5754 return -EIO;
5755 }
5756 break;
5757 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5758 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5759 __func__);
5760 return -EOPNOTSUPP;
5761 break;
5762 default:
5763 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5764 __func__, type);
5765 return -EIO;
5766 }
5767
5768 return 0;
5769}
5770
5771/*
5772 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5773 * This function is used to read the txpower
5774 */
5775static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5776{
5777
5778 hdd_adapter_t *pAdapter;
5779 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5780
Jeff Johnsone7245742012-09-05 17:12:55 -07005781 ENTER();
5782
Jeff Johnson295189b2012-06-20 16:38:30 -07005783 if (NULL == pHddCtx)
5784 {
5785 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5786 *dbm = 0;
5787 return -ENOENT;
5788 }
5789
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005790 if ( pHddCtx->isLogpInProgress )
5791 {
5792 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5793 "%s:LOGP in Progress. Ignore!!!", __func__);
5794 return -EAGAIN;
5795 }
5796
Jeff Johnson295189b2012-06-20 16:38:30 -07005797 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5798 if (NULL == pAdapter)
5799 {
5800 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5801 return -ENOENT;
5802 }
5803
5804 wlan_hdd_get_classAstats(pAdapter);
5805 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5806
Jeff Johnsone7245742012-09-05 17:12:55 -07005807 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005808 return 0;
5809}
5810
5811static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5812 u8* mac, struct station_info *sinfo)
5813{
5814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5815 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5816 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5817 tANI_U8 rate_flags;
5818
5819 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5820 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5821 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5822
5823 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5824 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5825 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5826 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5827 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5828 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5829 tANI_U16 maxRate = 0;
5830 tANI_U16 myRate;
5831 tANI_U16 currentRate = 0;
5832 tANI_U8 maxSpeedMCS = 0;
5833 tANI_U8 maxMCSIdx = 0;
5834 tANI_U8 rateFlag = 1;
5835 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005836 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005837
Jeff Johnsone7245742012-09-05 17:12:55 -07005838 ENTER();
5839
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5841 (0 == ssidlen))
5842 {
5843 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5844 " Invalid ssidlen, %d", __func__, ssidlen);
5845 /*To keep GUI happy*/
5846 return 0;
5847 }
5848
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005849 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5850 {
5851 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5852 "%s:LOGP in Progress. Ignore!!!", __func__);
5853 return -EAGAIN;
5854 }
5855
Jeff Johnson295189b2012-06-20 16:38:30 -07005856 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5857 sinfo->filled |= STATION_INFO_SIGNAL;
5858
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005859 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5861
5862 //convert to the UI units of 100kbps
5863 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5864
5865#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005866 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 -07005867 sinfo->signal,
5868 pCfg->reportMaxLinkSpeed,
5869 myRate,
5870 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005871 (int) pCfg->linkSpeedRssiMid,
5872 (int) pCfg->linkSpeedRssiLow,
5873 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005874#endif //LINKSPEED_DEBUG_ENABLED
5875
5876 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5877 {
5878 // we do not want to necessarily report the current speed
5879 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5880 {
5881 // report the max possible speed
5882 rssidx = 0;
5883 }
5884 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5885 {
5886 // report the max possible speed with RSSI scaling
5887 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5888 {
5889 // report the max possible speed
5890 rssidx = 0;
5891 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005892 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005893 {
5894 // report middle speed
5895 rssidx = 1;
5896 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005897 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5898 {
5899 // report middle speed
5900 rssidx = 2;
5901 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 else
5903 {
5904 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005905 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 }
5907 }
5908 else
5909 {
5910 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5911 hddLog(VOS_TRACE_LEVEL_ERROR,
5912 "%s: Invalid value for reportMaxLinkSpeed: %u",
5913 __func__, pCfg->reportMaxLinkSpeed);
5914 rssidx = 0;
5915 }
5916
5917 maxRate = 0;
5918
5919 /* Get Basic Rate Set */
5920 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5921 for (i = 0; i < ORLeng; i++)
5922 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005923 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005924 {
5925 /* Validate Rate Set */
5926 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5927 {
5928 currentRate = supported_data_rate[j].supported_rate[rssidx];
5929 break;
5930 }
5931 }
5932 /* Update MAX rate */
5933 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5934 }
5935
5936 /* Get Extended Rate Set */
5937 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5938 for (i = 0; i < ERLeng; i++)
5939 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005940 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005941 {
5942 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5943 {
5944 currentRate = supported_data_rate[j].supported_rate[rssidx];
5945 break;
5946 }
5947 }
5948 /* Update MAX rate */
5949 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5950 }
5951
5952 /* Get MCS Rate Set -- but only if we are connected at MCS
5953 rates or if we are always reporting max speed or if we have
5954 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005955 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005956 {
5957 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5958 rateFlag = 0;
5959 if (rate_flags & eHAL_TX_RATE_HT40)
5960 {
5961 rateFlag |= 1;
5962 }
5963 if (rate_flags & eHAL_TX_RATE_SGI)
5964 {
5965 rateFlag |= 2;
5966 }
5967
5968 for (i = 0; i < MCSLeng; i++)
5969 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005970 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5971 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005972 {
5973 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5974 {
5975 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5976 break;
5977 }
5978 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005979 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 {
5981 maxRate = currentRate;
5982 maxSpeedMCS = 1;
5983 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5984 }
5985 }
5986 }
5987
5988 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005989 if (((maxRate < myRate) && (0 == rssidx)) ||
5990 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005991 {
5992 maxRate = myRate;
5993 if (rate_flags & eHAL_TX_RATE_LEGACY)
5994 {
5995 maxSpeedMCS = 0;
5996 }
5997 else
5998 {
5999 maxSpeedMCS = 1;
6000 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6001 }
6002 }
6003
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006004 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 {
6006 sinfo->txrate.legacy = maxRate;
6007#ifdef LINKSPEED_DEBUG_ENABLED
6008 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6009#endif //LINKSPEED_DEBUG_ENABLED
6010 }
6011 else
6012 {
6013 sinfo->txrate.mcs = maxMCSIdx;
6014 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6015 if (rate_flags & eHAL_TX_RATE_SGI)
6016 {
6017 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6018 }
6019 if (rate_flags & eHAL_TX_RATE_HT40)
6020 {
6021 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6022 }
6023#ifdef LINKSPEED_DEBUG_ENABLED
6024 pr_info("Reporting MCS rate %d flags %x\n",
6025 sinfo->txrate.mcs,
6026 sinfo->txrate.flags );
6027#endif //LINKSPEED_DEBUG_ENABLED
6028 }
6029 }
6030 else
6031 {
6032 // report current rate instead of max rate
6033
6034 if (rate_flags & eHAL_TX_RATE_LEGACY)
6035 {
6036 //provide to the UI in units of 100kbps
6037 sinfo->txrate.legacy = myRate;
6038#ifdef LINKSPEED_DEBUG_ENABLED
6039 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6040#endif //LINKSPEED_DEBUG_ENABLED
6041 }
6042 else
6043 {
6044 //must be MCS
6045 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6046 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6047 if (rate_flags & eHAL_TX_RATE_SGI)
6048 {
6049 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6050 }
6051 if (rate_flags & eHAL_TX_RATE_HT40)
6052 {
6053 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6054 }
6055#ifdef LINKSPEED_DEBUG_ENABLED
6056 pr_info("Reporting actual MCS rate %d flags %x\n",
6057 sinfo->txrate.mcs,
6058 sinfo->txrate.flags );
6059#endif //LINKSPEED_DEBUG_ENABLED
6060 }
6061 }
6062 sinfo->filled |= STATION_INFO_TX_BITRATE;
6063
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006064 sinfo->tx_packets =
6065 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6066 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6067 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6068 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6069
6070 sinfo->tx_retries =
6071 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6072 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6073 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6074 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6075
6076 sinfo->tx_failed =
6077 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6078 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6079 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6080 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6081
6082 sinfo->filled |=
6083 STATION_INFO_TX_PACKETS |
6084 STATION_INFO_TX_RETRIES |
6085 STATION_INFO_TX_FAILED;
6086
6087 EXIT();
6088 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006089}
6090
6091static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6092 struct net_device *dev, bool mode, v_SINT_t timeout)
6093{
6094 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6095 VOS_STATUS vos_status;
6096
Jeff Johnsone7245742012-09-05 17:12:55 -07006097 ENTER();
6098
Jeff Johnson295189b2012-06-20 16:38:30 -07006099 if (NULL == pAdapter)
6100 {
6101 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6102 return -ENODEV;
6103 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006104 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6105 {
6106 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6107 "%s:LOGP in Progress. Ignore!!!", __func__);
6108 return -EAGAIN;
6109 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006110
6111 /**The get power cmd from the supplicant gets updated by the nl only
6112 *on successful execution of the function call
6113 *we are oppositely mapped w.r.t mode in the driver
6114 **/
6115 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6116
Jeff Johnsone7245742012-09-05 17:12:55 -07006117 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006118 if (VOS_STATUS_E_FAILURE == vos_status)
6119 {
6120 return -EINVAL;
6121 }
6122 return 0;
6123}
6124
6125
6126#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6127static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6128 struct net_device *netdev,
6129 u8 key_index)
6130{
Jeff Johnsone7245742012-09-05 17:12:55 -07006131 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006132 return 0;
6133}
6134#endif //LINUX_VERSION_CODE
6135
6136#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6137static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6138 struct net_device *dev,
6139 struct ieee80211_txq_params *params)
6140{
Jeff Johnsone7245742012-09-05 17:12:55 -07006141 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006142 return 0;
6143}
6144#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6145static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6146 struct ieee80211_txq_params *params)
6147{
Jeff Johnsone7245742012-09-05 17:12:55 -07006148 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006149 return 0;
6150}
6151#endif //LINUX_VERSION_CODE
6152
6153static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6154 struct net_device *dev, u8 *mac)
6155{
6156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006157 VOS_STATUS vos_status;
6158 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006159
Jeff Johnsone7245742012-09-05 17:12:55 -07006160 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006161 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6162 {
6163 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6164 return -EINVAL;
6165 }
6166
6167 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6168 {
6169 hddLog( LOGE,
6170 "%s: Wlan Load/Unload is in progress", __func__);
6171 return -EBUSY;
6172 }
6173
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006174 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6175 {
6176 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6177 "%s:LOGP in Progress. Ignore!!!", __func__);
6178 return -EAGAIN;
6179 }
6180
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6182#ifdef WLAN_FEATURE_P2P
6183 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6184#endif
6185 )
6186 {
6187 if( NULL == mac )
6188 {
6189 v_U16_t i;
6190 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6191 {
6192 if(pAdapter->aStaInfo[i].isUsed)
6193 {
6194 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6195 hddLog(VOS_TRACE_LEVEL_INFO,
6196 "%s: Delete STA with MAC::"
6197 "%02x:%02x:%02x:%02x:%02x:%02x",
6198 __func__,
6199 macAddr[0], macAddr[1], macAddr[2],
6200 macAddr[3], macAddr[4], macAddr[5]);
6201 hdd_softap_sta_deauth(pAdapter, macAddr);
6202 }
6203 }
6204 }
6205 else
6206 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006207
6208 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6209 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6210 {
6211 hddLog(VOS_TRACE_LEVEL_INFO,
6212 "%s: Skip this DEL STA as this is not used::"
6213 "%02x:%02x:%02x:%02x:%02x:%02x",
6214 __func__,
6215 mac[0], mac[1], mac[2],
6216 mac[3], mac[4], mac[5]);
6217 return -ENOENT;
6218 }
6219
6220 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6221 {
6222 hddLog(VOS_TRACE_LEVEL_INFO,
6223 "%s: Skip this DEL STA as deauth is in progress::"
6224 "%02x:%02x:%02x:%02x:%02x:%02x",
6225 __func__,
6226 mac[0], mac[1], mac[2],
6227 mac[3], mac[4], mac[5]);
6228 return -ENOENT;
6229 }
6230
6231 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6232
Jeff Johnson295189b2012-06-20 16:38:30 -07006233 hddLog(VOS_TRACE_LEVEL_INFO,
6234 "%s: Delete STA with MAC::"
6235 "%02x:%02x:%02x:%02x:%02x:%02x",
6236 __func__,
6237 mac[0], mac[1], mac[2],
6238 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006239
6240 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6241 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6242 {
6243 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6244 hddLog(VOS_TRACE_LEVEL_INFO,
6245 "%s: STA removal failed for ::"
6246 "%02x:%02x:%02x:%02x:%02x:%02x",
6247 __func__,
6248 mac[0], mac[1], mac[2],
6249 mac[3], mac[4], mac[5]);
6250 return -ENOENT;
6251 }
6252
Jeff Johnson295189b2012-06-20 16:38:30 -07006253 }
6254 }
6255
6256 EXIT();
6257
6258 return 0;
6259}
6260
6261static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6262 struct net_device *dev, u8 *mac, struct station_parameters *params)
6263{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006264#ifdef FEATURE_WLAN_TDLS
6265 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6266 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6267 u32 mask, set;
6268 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006269 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006270
6271 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6272 {
6273 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6274 "Invalid arguments");
6275 return -EINVAL;
6276 }
6277
6278 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6279 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6280 {
6281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6282 "TDLS Disabled in INI OR not enabled in FW.\
6283 Cannot process TDLS commands \n");
6284 return -ENOTSUPP;
6285 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006286 /* first to check if we reached to maximum supported TDLS peer.
6287 TODO: for now, return -EPERM looks working fine,
6288 but need to check if any other errno fit into this category.*/
6289 if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
6290 {
6291 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6292 "%s: TDLS Max peer already connected. Request declined. \n",
6293 __func__);
6294 return -EPERM;
6295 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006296
6297 mask = params->sta_flags_mask;
6298
6299 set = params->sta_flags_set;
6300
6301
Lee Hoonkic1262f22013-01-24 21:59:00 -08006302 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6303 "%s: mask 0x%x set 0x%x\n",__func__, mask, set);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006304
6305 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6306 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6308 "Add TDLS peer");
6309
6310
6311 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6312 pAdapter->sessionId, mac);
6313
6314 if (VOS_STATUS_SUCCESS != status) {
6315 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6316 "%s: sme_AddTdlsPeerSta failed!", __func__);
6317 }
6318 }
6319 }
6320#endif
6321
Jeff Johnson295189b2012-06-20 16:38:30 -07006322 return 0;
6323}
6324
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006325
6326#ifdef FEATURE_WLAN_LFR
6327static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006328 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006329{
6330#define MAX_PMKSAIDS_IN_CACHE 8
6331 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006332 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006333 tANI_U32 j=0;
6334 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6335 tHalHandle halHandle;
6336 eHalStatus result;
6337 tANI_U8 BSSIDMatched = 0;
6338
Jeff Johnsone7245742012-09-05 17:12:55 -07006339 ENTER();
6340
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006341 // Validate pAdapter
6342 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6343 {
6344 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6345 return -EINVAL;
6346 }
6347
6348 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6349 {
6350 hddLog( LOGE,
6351 "%s: Wlan Load/Unload is in progress", __func__);
6352 return -EBUSY;
6353 }
6354
6355 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6356 {
6357 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6358 "%s:LOGP in Progress. Ignore!!!", __func__);
6359 return -EAGAIN;
6360 }
6361
6362 // Retrieve halHandle
6363 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6364
6365 for (j = 0; j < i; j++)
6366 {
6367 if(vos_mem_compare(PMKIDCache[j].BSSID,
6368 pmksa->bssid, WNI_CFG_BSSID_LEN))
6369 {
6370 /* BSSID matched previous entry. Overwrite it. */
6371 BSSIDMatched = 1;
6372 vos_mem_copy(PMKIDCache[j].BSSID,
6373 pmksa->bssid, WNI_CFG_BSSID_LEN);
6374 vos_mem_copy(PMKIDCache[j].PMKID,
6375 pmksa->pmkid,
6376 CSR_RSN_PMKID_SIZE);
6377 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006378 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006379 dump_bssid(pmksa->bssid);
6380 dump_pmkid(halHandle, pmksa->pmkid);
6381 break;
6382 }
6383 }
6384
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006385 /* Check we compared all entries,if then take the first slot now */
6386 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6387
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006388 if (!BSSIDMatched)
6389 {
6390 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6391 vos_mem_copy(PMKIDCache[i].BSSID,
6392 pmksa->bssid, ETHER_ADDR_LEN);
6393 vos_mem_copy(PMKIDCache[i].PMKID,
6394 pmksa->pmkid,
6395 CSR_RSN_PMKID_SIZE);
6396 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006397 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006398 dump_bssid(pmksa->bssid);
6399 dump_pmkid(halHandle, pmksa->pmkid);
6400 // Increment the HDD Local Cache index
6401 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6402 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6403 }
6404
6405
6406 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6407 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006408 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006409 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006410 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006411 // Finally set the PMKSA ID Cache in CSR
6412 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6413 PMKIDCache,
6414 i );
6415 return 0;
6416}
6417
6418
6419static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006420 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006421{
Jeff Johnsone7245742012-09-05 17:12:55 -07006422 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006423 // TODO: Implement this later.
6424 return 0;
6425}
6426
6427static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6428{
Jeff Johnsone7245742012-09-05 17:12:55 -07006429 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006430 // TODO: Implement this later.
6431 return 0;
6432}
6433#endif
6434
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006435#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6436static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6437 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6438{
6439 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6440 hdd_station_ctx_t *pHddStaCtx;
6441
6442 if (NULL == pAdapter)
6443 {
6444 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6445 return -ENODEV;
6446 }
6447
6448 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6449
6450 // Added for debug on reception of Re-assoc Req.
6451 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6452 {
6453 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6454 ftie->ie_len);
6455 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6456 }
6457
6458#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6459 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6460 ftie->ie_len);
6461#endif
6462
6463 // Pass the received FT IEs to SME
6464 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6465 ftie->ie_len);
6466 return 0;
6467}
6468#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006469
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006470#ifdef FEATURE_WLAN_TDLS
6471static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6472 u8 *peer, u8 action_code, u8 dialog_token,
6473 u16 status_code, const u8 *buf, size_t len)
6474{
6475
6476 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6477 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6478 u8 *buf_1;
6479 size_t len_1 = len;
6480 u8 peerMac[6];
6481 VOS_STATUS status;
6482
6483 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6484 {
6485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6486 "Invalid arguments");
6487 return -EINVAL;
6488 }
6489
6490 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6491 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6492 {
6493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6494 "TDLS Disabled in INI OR not enabled in FW.\
6495 Cannot process TDLS commands \n");
6496 return -ENOTSUPP;
6497 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006498
6499 if(SIR_MAC_TDLS_SETUP_REQ == action_code ||
6500 SIR_MAC_TDLS_SETUP_RSP == action_code )
6501 {
6502 if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
6503 {
6504 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6505 we return error code at 'add_station()'. Hence we have this
6506 check again in addtion to add_station().
6507 Anyway, there is no hard to double-check. */
6508 if(SIR_MAC_TDLS_SETUP_REQ == action_code)
6509 {
6510 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6511 "%s: TDLS Max peer already connected. Request declined. \n",
6512 __func__);
6513 return -EPERM;
6514 }
6515 else
6516 {
6517 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
6518 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6519 "%s: TDLS Max peer already connected send response status %d \n",
6520 __func__,status_code);
6521 }
6522 }
6523 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006524 vos_mem_copy( peerMac, peer, 6);
6525
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006526#ifdef WLAN_FEATURE_TDLS_DEBUG
6527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6528 "%s: %02x:%02x:%02x:%02x:%02x:%02x) action %d, dialog_token %d status %d, len = %d",
6529 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6530 action_code, dialog_token, status_code, len);
6531#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006532
6533 buf_1 = vos_mem_malloc(len);
6534 if(buf_1 == NULL) {
6535 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6536 "%s: malloc failed!", __func__);
6537 return -ENOMEM;
6538 }
6539 vos_mem_copy(buf_1, buf, len);
6540
6541 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6542 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6543
6544 if (VOS_STATUS_SUCCESS != status) {
6545 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6546 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6547 }
6548
6549 vos_mem_free(buf_1);
6550
6551 return 0;
6552}
6553
6554static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6555 u8 *peer, enum nl80211_tdls_operation oper)
6556{
6557 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6558 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006559#ifdef WLAN_FEATURE_TDLS_DEBUG
6560 const char *tdls_oper_str[]= {
6561 "NL80211_TDLS_DISCOVERY_REQ",
6562 "NL80211_TDLS_SETUP",
6563 "NL80211_TDLS_TEARDOWN",
6564 "NL80211_TDLS_ENABLE_LINK",
6565 "NL80211_TDLS_DISABLE_LINK",
6566 "NL80211_TDLS_UNKONW_OPER"};
6567#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006568
6569 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6570 {
6571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6572 "Invalid arguments");
6573 return -EINVAL;
6574 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006575
6576#ifdef WLAN_FEATURE_TDLS_DEBUG
6577 if((int)oper > 4)
6578 oper = 5;
6579
6580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6581 "%s: %02x:%02x:%02x:%02x:%02x:%02x: %d (%s) ", "tdls_oper",
6582 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5], (int)oper,
6583 tdls_oper_str[(int)oper]);
6584#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006585
6586 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006587 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006588 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006590 "TDLS Disabled in INI OR not enabled in FW.\
6591 Cannot process TDLS commands \n");
6592 return -ENOTSUPP;
6593 }
6594
6595 switch (oper) {
6596 case NL80211_TDLS_ENABLE_LINK:
6597 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006598 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006599 v_U8_t my_peer[6];
6600 v_U8_t ucSTAId;
6601 VOS_STATUS status;
6602
6603 if (peer) {
6604 vos_mem_copy(my_peer, peer, 6);
6605 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6606
6607 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6608 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6609 __func__, peer[0], peer[1],
6610 peer[2], peer[3],
6611 peer[4], peer[5] );
6612
6613 if (-1 == ucSTAId ) {
6614 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
Hoonki Leef63df0d2013-01-16 19:29:14 -08006615 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006616 }
6617
6618 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6619 WLANTL_STA_AUTHENTICATED );
6620
Hoonki Leef63df0d2013-01-16 19:29:14 -08006621 //This can fail only if the staId is not registered yet with TL
6622 //return -EINVAL in such case.
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006623 if (0 != status) {
6624 hddLog(VOS_TRACE_LEVEL_ERROR,
6625 "%s: WLANTL_ChangeSTAState failed, returned %d",
6626 __func__, status);
Hoonki Leef63df0d2013-01-16 19:29:14 -08006627 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006628 }
Hoonki Leef63df0d2013-01-16 19:29:14 -08006629
Chilam NG571c65a2013-01-19 12:27:36 +05306630 wlan_hdd_tdls_set_link_status(peer, eTDLS_LINK_CONNECTED);
6631
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006632 } else {
6633 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6634 }
6635 }
6636 break;
6637 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08006638 {
6639 if(-1 != wlan_hdd_findTdlsPeer(peer))
6640 {
6641 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6642 pAdapter->sessionId, peer );
6643 }
6644 else
6645 {
6646 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6647 "%s: TDLS Peer Station doesn't exist \n",__func__);
6648 }
6649 return 0;
6650 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006651 case NL80211_TDLS_TEARDOWN:
6652 case NL80211_TDLS_SETUP:
6653 case NL80211_TDLS_DISCOVERY_REQ:
6654 /* We don't support in-driver setup/teardown/discovery */
6655 return -ENOTSUPP;
6656 default:
6657 return -ENOTSUPP;
6658 }
6659 return 0;
6660}
Chilam NG571c65a2013-01-19 12:27:36 +05306661
6662int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
6663 struct net_device *dev, u8 *peer)
6664{
6665 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
6666 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6667
6668 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
6669 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
6670}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006671#endif
6672
Jeff Johnson295189b2012-06-20 16:38:30 -07006673/* cfg80211_ops */
6674static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6675{
6676 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6677 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6678 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6679 .change_station = wlan_hdd_change_station,
6680#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6681 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6682 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6683 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006684#else
6685 .start_ap = wlan_hdd_cfg80211_start_ap,
6686 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6687 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006688#endif
6689 .change_bss = wlan_hdd_cfg80211_change_bss,
6690 .add_key = wlan_hdd_cfg80211_add_key,
6691 .get_key = wlan_hdd_cfg80211_get_key,
6692 .del_key = wlan_hdd_cfg80211_del_key,
6693 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006694#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07006695 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006696#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006697 .scan = wlan_hdd_cfg80211_scan,
6698 .connect = wlan_hdd_cfg80211_connect,
6699 .disconnect = wlan_hdd_cfg80211_disconnect,
6700 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6701 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6702 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6703 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6704 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6705#ifdef WLAN_FEATURE_P2P
6706 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6707 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6708 .mgmt_tx = wlan_hdd_action,
6709#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6710 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6711 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6712 .set_txq_params = wlan_hdd_set_txq_params,
6713#endif
6714#endif
6715 .get_station = wlan_hdd_cfg80211_get_station,
6716 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6717 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006718 .add_station = wlan_hdd_cfg80211_add_station,
6719#ifdef FEATURE_WLAN_LFR
6720 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6721 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6722 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6723#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006724#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6725 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6726#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006727#ifdef FEATURE_WLAN_TDLS
6728 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6729 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6730#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006731};
6732
6733#endif // CONFIG_CFG80211