blob: bbf9590fc45914a09e1f06fdccd115601d58c796 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala9c070ad2013-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 Khannac0b992f2012-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 Hoonkif1431702013-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 Johnsoncab8ddc2013-01-18 17:05:29 -0800357#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700358};
359
Sudhir Sattayappa Kohalli0c7606f2013-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 {
Sunil Ravice1c00c2013-01-31 06:12:22 -0800365 /* max = 3 ; Our driver create two interfaces during driver init
366 * wlan0 and p2p0 interfaces. p2p0 is considered as station
367 * interface until a group is formed. In JB architecture, once the
368 * group is formed, interface type of p2p0 is changed to P2P GO or
369 * Client.
370 * When supplicant remove the group, it first issue a set interface
371 * cmd to change the mode back to Station. In JB this works fine as
372 * we advertize two station type interface during driver init.
373 * Some vendors create separate interface for P2P GO/Client,
374 * after group formation(Third one). But while group remove
375 * supplicant first tries to change the mode(3rd interface) to STATION
376 * But as we advertized only two sta type interfaces nl80211 was
377 * returning error for the third one which was leading to failure in
378 * delete interface. Ideally while removing the group, supplicant
379 * should not try to change the 3rd interface mode to Station type.
380 * Till we get a fix in wpa_supplicant, we advertize max STA
381 * interface type to 3
382 */
383 .max = 3,
Sudhir Sattayappa Kohalli0c7606f2013-01-16 17:35:13 -0800384 .types = BIT(NL80211_IFTYPE_STATION),
385 },
386 {
387 .max = 1,
388 .types = BIT(NL80211_IFTYPE_AP),
389 },
390 {
391 .max = 1,
392 .types = BIT(NL80211_IFTYPE_P2P_GO) |
393 BIT(NL80211_IFTYPE_P2P_CLIENT),
394 },
395};
396
397/* By default, only single channel concurrency is allowed */
398static struct ieee80211_iface_combination
399wlan_hdd_iface_combination = {
400 .limits = wlan_hdd_iface_limit,
401 .num_different_channels = 1,
Sunil Ravice1c00c2013-01-31 06:12:22 -0800402 /*
403 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
404 * and p2p0 interfaces during driver init
405 * Some vendors create separate interface for P2P operations.
406 * wlan0: STA interface
407 * p2p0: P2P Device interface, action frames goes
408 * through this interface.
409 * p2p-xx: P2P interface, After GO negotiation this interface is
410 * created for p2p operations(GO/CLIENT interface).
411 */
412 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli0c7606f2013-01-16 17:35:13 -0800413 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
414 .beacon_int_infra_match = false,
415};
416#endif
417#endif
418
Jeff Johnson295189b2012-06-20 16:38:30 -0700419static struct cfg80211_ops wlan_hdd_cfg80211_ops;
420
421/* Data rate 100KBPS based on IE Index */
422struct index_data_rate_type
423{
424 v_U8_t beacon_rate_index;
425 v_U16_t supported_rate[4];
426};
427
428/* 11B, 11G Rate table include Basic rate and Extended rate
429 The IDX field is the rate index
430 The HI field is the rate when RSSI is strong or being ignored
431 (in this case we report actual rate)
432 The MID field is the rate when RSSI is moderate
433 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
434 The LO field is the rate when RSSI is low
435 (in this case we don't report rates, actual current rate used)
436 */
437static const struct
438{
439 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700440 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700441} supported_data_rate[] =
442{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700443/* IDX HI HM LM LO (RSSI-based index */
444 {2, { 10, 10, 10, 0}},
445 {4, { 20, 20, 10, 0}},
446 {11, { 55, 20, 10, 0}},
447 {12, { 60, 55, 20, 0}},
448 {18, { 90, 55, 20, 0}},
449 {22, {110, 55, 20, 0}},
450 {24, {120, 90, 60, 0}},
451 {36, {180, 120, 60, 0}},
452 {44, {220, 180, 60, 0}},
453 {48, {240, 180, 90, 0}},
454 {66, {330, 180, 90, 0}},
455 {72, {360, 240, 90, 0}},
456 {96, {480, 240, 120, 0}},
457 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700458};
459
460/* MCS Based rate table */
461static struct index_data_rate_type supported_mcs_rate[] =
462{
463/* MCS L20 L40 S20 S40 */
464 {0, {65, 135, 72, 150}},
465 {1, {130, 270, 144, 300}},
466 {2, {195, 405, 217, 450}},
467 {3, {260, 540, 289, 600}},
468 {4, {390, 810, 433, 900}},
469 {5, {520, 1080, 578, 1200}},
470 {6, {585, 1215, 650, 1350}},
471 {7, {650, 1350, 722, 1500}}
472};
473
474extern struct net_device_ops net_ops_struct;
475
476/*
477 * FUNCTION: wlan_hdd_cfg80211_init
478 * This function is called by hdd_wlan_startup()
479 * during initialization.
480 * This function is used to initialize and register wiphy structure.
481 */
482struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
483{
484 struct wiphy *wiphy;
485 ENTER();
486
487 /*
488 * Create wiphy device
489 */
490 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
491
492 if (!wiphy)
493 {
494 /* Print error and jump into err label and free the memory */
495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
496 return NULL;
497 }
498
499 return wiphy;
500}
501
502/*
503 * FUNCTION: wlan_hdd_cfg80211_update_band
504 * This function is called from the supplicant through a
505 * private ioctl to change the band value
506 */
507int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
508{
Jeff Johnsone7245742012-09-05 17:12:55 -0700509 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700510 switch(eBand)
511 {
512 case eCSR_BAND_24:
513 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
514 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
515 break;
516 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700517#ifdef WLAN_FEATURE_P2P
518 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
519#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700520 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700521#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700522 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
523 break;
524 case eCSR_BAND_ALL:
525 default:
526 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
527 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
528 }
529 return 0;
530}
531/*
532 * FUNCTION: wlan_hdd_cfg80211_init
533 * This function is called by hdd_wlan_startup()
534 * during initialization.
535 * This function is used to initialize and register wiphy structure.
536 */
537int wlan_hdd_cfg80211_register(struct device *dev,
538 struct wiphy *wiphy,
539 hdd_config_t *pCfg
540 )
541{
Jeff Johnsone7245742012-09-05 17:12:55 -0700542 ENTER();
543
Jeff Johnson295189b2012-06-20 16:38:30 -0700544 /* Now bind the underlying wlan device with wiphy */
545 set_wiphy_dev(wiphy, dev);
546
547 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
548
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700549 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700550
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700551#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700552 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
553 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
554 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700555 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700556#endif
James Zmuda1b617722013-01-29 08:00:17 -0800557#ifdef FEATURE_WLAN_LFR
558 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
559#endif
Mohit Khannac0b992f2012-12-04 15:08:18 -0800560#ifdef FEATURE_WLAN_TDLS
561 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
562 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
563#endif
564
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700565 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
566 driver can still register regulatory callback and
567 it will get CRDA setting in wiphy->band[], but
568 driver need to determine what to do with both
569 regulatory settings */
570 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700571
Jeff Johnson295189b2012-06-20 16:38:30 -0700572 wiphy->max_scan_ssids = MAX_SCAN_SSID;
573
574 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
575
576 /* Supports STATION & AD-HOC modes right now */
577 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
578 | BIT(NL80211_IFTYPE_ADHOC)
579#ifdef WLAN_FEATURE_P2P
580 | BIT(NL80211_IFTYPE_P2P_CLIENT)
581 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnsoncab8ddc2013-01-18 17:05:29 -0800582#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700583 | BIT(NL80211_IFTYPE_AP);
584
Sudhir Sattayappa Kohalli0c7606f2013-01-16 17:35:13 -0800585#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
586#ifdef WLAN_FEATURE_P2P
587 if( pCfg->enableMCC )
588 {
589 /* Currently, supports up to two channels */
590 wlan_hdd_iface_combination.num_different_channels = 2;
591
592 if( !pCfg->allowMCCGODiffBI )
593 wlan_hdd_iface_combination.beacon_int_infra_match = true;
594
595 }
596 wiphy->iface_combinations = &wlan_hdd_iface_combination;
597 wiphy->n_iface_combinations = 1;
598#endif
599#endif
600
Jeff Johnson295189b2012-06-20 16:38:30 -0700601 /* Before registering we need to update the ht capabilitied based
602 * on ini values*/
603 if( !pCfg->ShortGI20MhzEnable )
604 {
605 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
606 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
607 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
608 }
609
610 if( !pCfg->ShortGI40MhzEnable )
611 {
612 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
613 }
614
615 if( !pCfg->nChannelBondingMode5GHz )
616 {
617 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
618 }
619
620 /*Initialize band capability*/
621 switch(pCfg->nBandCapability)
622 {
623 case eCSR_BAND_24:
624 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
625 break;
626 case eCSR_BAND_5G:
627#ifdef WLAN_FEATURE_P2P
628 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
629#endif
630 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
631 break;
632 case eCSR_BAND_ALL:
633 default:
634 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
635 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
636 }
637 /*Initialise the supported cipher suite details*/
638 wiphy->cipher_suites = hdd_cipher_suites;
639 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
640
641 /*signal strength in mBm (100*dBm) */
642 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
643
644#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
645#ifdef WLAN_FEATURE_P2P
646 wiphy->max_remain_on_channel_duration = 1000;
647#endif
648#endif
649
650 /* Register our wiphy dev with cfg80211 */
651 if (0 > wiphy_register(wiphy))
652 {
653 /* print eror */
654 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
655 return -EIO;
656 }
657
658 EXIT();
659 return 0;
660}
661
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700662/* In this function we will try to get default country code from crda.
663 If the gCrdaDefaultCountryCode is configured in ini file,
664 we will try to call user space crda to get the regulatory settings for
665 that country. We will timeout if we can't get it from crda.
666 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
667*/
668int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
669{
670 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
671 if (memcmp(pCfg->crdaDefaultCountryCode,
672 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
673 {
674 init_completion(&pHddCtx->driver_crda_req);
675 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
676 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
677 CRDA_WAIT_TIME);
678 }
679 return 0;
680}
681
Jeff Johnson295189b2012-06-20 16:38:30 -0700682/* In this function we will do all post VOS start initialization.
683 In this function we will register for all frame in which supplicant
684 is interested.
685*/
686void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
687{
688#ifdef WLAN_FEATURE_P2P
689 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
690 /* Register for all P2P action, public action etc frames */
691 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
692
Jeff Johnsone7245742012-09-05 17:12:55 -0700693 ENTER();
694
Jeff Johnson295189b2012-06-20 16:38:30 -0700695 /* Right now we are registering these frame when driver is getting
696 initialized. Once we will move to 2.6.37 kernel, in which we have
697 frame register ops, we will move this code as a part of that */
698 /* GAS Initial Request */
699 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
700 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
701
702 /* GAS Initial Response */
703 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
704 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
705
706 /* GAS Comeback Request */
707 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
708 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
709
710 /* GAS Comeback Response */
711 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
712 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
713
714 /* P2P Public Action */
715 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
716 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
717 P2P_PUBLIC_ACTION_FRAME_SIZE );
718
719 /* P2P Action */
720 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
721 (v_U8_t*)P2P_ACTION_FRAME,
722 P2P_ACTION_FRAME_SIZE );
723#endif /* WLAN_FEATURE_P2P */
724}
725
726void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
727{
728#ifdef WLAN_FEATURE_P2P
729 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
730 /* Register for all P2P action, public action etc frames */
731 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
732
Jeff Johnsone7245742012-09-05 17:12:55 -0700733 ENTER();
734
Jeff Johnson295189b2012-06-20 16:38:30 -0700735 /* Right now we are registering these frame when driver is getting
736 initialized. Once we will move to 2.6.37 kernel, in which we have
737 frame register ops, we will move this code as a part of that */
738 /* GAS Initial Request */
739
740 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
741 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
742
743 /* GAS Initial Response */
744 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
745 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
746
747 /* GAS Comeback Request */
748 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
749 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
750
751 /* GAS Comeback Response */
752 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
753 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
754
755 /* P2P Public Action */
756 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
757 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
758 P2P_PUBLIC_ACTION_FRAME_SIZE );
759
760 /* P2P Action */
761 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
762 (v_U8_t*)P2P_ACTION_FRAME,
763 P2P_ACTION_FRAME_SIZE );
764#endif /* WLAN_FEATURE_P2P */
765}
766
767#ifdef FEATURE_WLAN_WAPI
768void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
769 const u8 *mac_addr, u8 *key , int key_Len)
770{
771 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
772 tCsrRoamSetKey setKey;
773 v_BOOL_t isConnected = TRUE;
774 int status = 0;
775 v_U32_t roamId= 0xFF;
776 tANI_U8 *pKeyPtr = NULL;
777 int n = 0;
778
779 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
780 __func__,pAdapter->device_mode);
781
782 setKey.keyId = key_index; // Store Key ID
783 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
784 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
785 setKey.paeRole = 0 ; // the PAE role
786 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
787 {
788 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
789 }
790 else
791 {
792 isConnected = hdd_connIsConnected(pHddStaCtx);
793 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
794 }
795 setKey.keyLength = key_Len;
796 pKeyPtr = setKey.Key;
797 memcpy( pKeyPtr, key, key_Len);
798
799 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
800 __func__, key_Len);
801 for (n = 0 ; n < key_Len; n++)
802 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
803 __func__,n,setKey.Key[n]);
804
805 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
806 if ( isConnected )
807 {
808 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
809 pAdapter->sessionId, &setKey, &roamId );
810 }
811 if ( status != 0 )
812 {
813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
814 "[%4d] sme_RoamSetKey returned ERROR status= %d",
815 __LINE__, status );
816 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
817 }
818}
819#endif /* FEATURE_WLAN_WAPI*/
820
821#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
822int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
823 beacon_data_t **ppBeacon,
824 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700825#else
826int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
827 beacon_data_t **ppBeacon,
828 struct cfg80211_beacon_data *params,
829 int dtim_period)
830#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700831{
832 int size;
833 beacon_data_t *beacon = NULL;
834 beacon_data_t *old = NULL;
835 int head_len,tail_len;
836
Jeff Johnsone7245742012-09-05 17:12:55 -0700837 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700838 if (params->head && !params->head_len)
839 return -EINVAL;
840
841 old = pAdapter->sessionCtx.ap.beacon;
842
843 if (!params->head && !old)
844 return -EINVAL;
845
846 if (params->tail && !params->tail_len)
847 return -EINVAL;
848
849#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
850 /* Kernel 3.0 is not updating dtim_period for set beacon */
851 if (!params->dtim_period)
852 return -EINVAL;
853#endif
854
855 if(params->head)
856 head_len = params->head_len;
857 else
858 head_len = old->head_len;
859
860 if(params->tail || !old)
861 tail_len = params->tail_len;
862 else
863 tail_len = old->tail_len;
864
865 size = sizeof(beacon_data_t) + head_len + tail_len;
866
867 beacon = kzalloc(size, GFP_KERNEL);
868
869 if( beacon == NULL )
870 return -ENOMEM;
871
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700872#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700873 if(params->dtim_period || !old )
874 beacon->dtim_period = params->dtim_period;
875 else
876 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700877#else
878 if(dtim_period || !old )
879 beacon->dtim_period = dtim_period;
880 else
881 beacon->dtim_period = old->dtim_period;
882#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700883
884 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
885 beacon->tail = beacon->head + head_len;
886 beacon->head_len = head_len;
887 beacon->tail_len = tail_len;
888
889 if(params->head) {
890 memcpy (beacon->head,params->head,beacon->head_len);
891 }
892 else {
893 if(old)
894 memcpy (beacon->head,old->head,beacon->head_len);
895 }
896
897 if(params->tail) {
898 memcpy (beacon->tail,params->tail,beacon->tail_len);
899 }
900 else {
901 if(old)
902 memcpy (beacon->tail,old->tail,beacon->tail_len);
903 }
904
905 *ppBeacon = beacon;
906
907 kfree(old);
908
909 return 0;
910
911}
Jeff Johnson295189b2012-06-20 16:38:30 -0700912
913v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
914{
915 int left = length;
916 v_U8_t *ptr = pIes;
917 v_U8_t elem_id,elem_len;
918
919 while(left >= 2)
920 {
921 elem_id = ptr[0];
922 elem_len = ptr[1];
923 left -= 2;
924 if(elem_len > left)
925 {
926 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700927 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700928 eid,elem_len,left);
929 return NULL;
930 }
931 if (elem_id == eid)
932 {
933 return ptr;
934 }
935
936 left -= elem_len;
937 ptr += (elem_len + 2);
938 }
939 return NULL;
940}
941
Jeff Johnson295189b2012-06-20 16:38:30 -0700942/* Check if rate is 11g rate or not */
943static int wlan_hdd_rate_is_11g(u8 rate)
944{
945 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
946 u8 i;
947 for (i = 0; i < 8; i++)
948 {
949 if(rate == gRateArray[i])
950 return TRUE;
951 }
952 return FALSE;
953}
954
955/* Check for 11g rate and set proper 11g only mode */
956static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
957 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
958{
959 u8 i, num_rates = pIe[0];
960
961 pIe += 1;
962 for ( i = 0; i < num_rates; i++)
963 {
964 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
965 {
966 /* If rate set have 11g rate than change the mode to 11G */
967 *pSapHw_mode = eSAP_DOT11_MODE_11g;
968 if (pIe[i] & BASIC_RATE_MASK)
969 {
970 /* If we have 11g rate as basic rate, it means mode
971 is 11g only mode.
972 */
973 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
974 *pCheckRatesfor11g = FALSE;
975 }
976 }
977 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
978 {
979 *require_ht = TRUE;
980 }
981 }
982 return;
983}
984
985static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
986{
987 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
988 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
989 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
990 u8 checkRatesfor11g = TRUE;
991 u8 require_ht = FALSE;
992 u8 *pIe=NULL;
993
994 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
995
996 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
997 pBeacon->head_len, WLAN_EID_SUPP_RATES);
998 if (pIe != NULL)
999 {
1000 pIe += 1;
1001 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1002 &pConfig->SapHw_mode);
1003 }
1004
1005 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1006 WLAN_EID_EXT_SUPP_RATES);
1007 if (pIe != NULL)
1008 {
1009
1010 pIe += 1;
1011 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
1012 &pConfig->SapHw_mode);
1013 }
1014
1015 if( pConfig->channel > 14 )
1016 {
1017 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
1018 }
1019
1020 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1021 WLAN_EID_HT_CAPABILITY);
1022
1023 if(pIe)
1024 {
1025 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1026 if(require_ht)
1027 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1028 }
1029}
1030
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001031#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001032static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1033 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001034#else
1035static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1036 struct cfg80211_beacon_data *params)
1037#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001038{
1039 v_U8_t *genie;
1040 v_U8_t total_ielen = 0, ielen = 0;
1041 v_U8_t *pIe = NULL;
1042 v_U8_t addIE[1] = {0};
1043 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -07001044 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001045
1046 genie = vos_mem_malloc(MAX_GENIE_LEN);
1047
1048 if(genie == NULL) {
1049
1050 return -ENOMEM;
1051 }
1052
1053 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1054
1055 if(pIe)
1056 {
1057 /*Copy the wps IE*/
1058 ielen = pIe[1] + 2;
1059 if( ielen <=MAX_GENIE_LEN)
1060 {
1061 vos_mem_copy(genie, pIe, ielen);
1062 }
1063 else
1064 {
1065 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001066 ret = -EINVAL;
1067 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001068 }
1069 total_ielen = ielen;
1070 }
1071
1072#ifdef WLAN_FEATURE_WFD
1073 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1074
1075 if(pIe)
1076 {
1077 ielen = pIe[1] + 2;
1078 if(total_ielen + ielen <= MAX_GENIE_LEN) {
1079 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
1080 }
1081 else {
1082 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001083 ret = -EINVAL;
1084 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001085 }
1086 total_ielen += ielen;
1087 }
1088#endif
1089
1090#ifdef WLAN_FEATURE_P2P
1091 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1092
1093 if(pIe)
1094 {
1095 ielen = pIe[1] + 2;
1096 if(total_ielen + ielen <= MAX_GENIE_LEN)
1097 {
1098 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1099 }
1100 else
1101 {
1102 hddLog( VOS_TRACE_LEVEL_ERROR,
1103 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001104 ret = -EINVAL;
1105 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 }
1107 total_ielen += ielen;
1108 }
1109#endif
1110
1111 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1112 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1113 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1114 {
1115 hddLog(LOGE,
1116 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001117 ret = -EINVAL;
1118 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001119 }
1120
1121 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1122 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1123 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1124 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1125 ==eHAL_STATUS_FAILURE)
1126 {
1127 hddLog(LOGE,
1128 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001129 ret = -EINVAL;
1130 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001131 }
1132
1133 // Added for ProResp IE
1134 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1135 {
1136 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1137 u8 probe_rsp_ie_len[3] = {0};
1138 u8 counter = 0;
1139 /* Check Probe Resp Length if it is greater then 255 then Store
1140 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1141 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1142 Store More then 255 bytes into One Variable.
1143 */
1144 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1145 {
1146 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1147 {
1148 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1149 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1150 }
1151 else
1152 {
1153 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1154 rem_probe_resp_ie_len = 0;
1155 }
1156 }
1157
1158 rem_probe_resp_ie_len = 0;
1159
1160 if (probe_rsp_ie_len[0] > 0)
1161 {
1162 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1163 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1164 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1165 probe_rsp_ie_len[0], NULL,
1166 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1167 {
1168 hddLog(LOGE,
1169 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001170 ret = -EINVAL;
1171 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001172 }
1173 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1174 }
1175
1176 if (probe_rsp_ie_len[1] > 0)
1177 {
1178 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1179 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1180 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1181 probe_rsp_ie_len[1], NULL,
1182 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1183 {
1184 hddLog(LOGE,
1185 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001186 ret = -EINVAL;
1187 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001188 }
1189 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1190 }
1191
1192 if (probe_rsp_ie_len[2] > 0)
1193 {
1194 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1195 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1196 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1197 probe_rsp_ie_len[2], NULL,
1198 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1199 {
1200 hddLog(LOGE,
1201 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001202 ret = -EINVAL;
1203 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001204 }
1205 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1206 }
1207
1208 if (probe_rsp_ie_len[1] == 0 )
1209 {
1210 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1211 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1212 eANI_BOOLEAN_FALSE) )
1213 {
1214 hddLog(LOGE,
1215 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1216 }
1217 }
1218
1219 if (probe_rsp_ie_len[2] == 0 )
1220 {
1221 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1222 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1223 eANI_BOOLEAN_FALSE) )
1224 {
1225 hddLog(LOGE,
1226 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1227 }
1228 }
1229
1230 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1231 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1232 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1233 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1234 == eHAL_STATUS_FAILURE)
1235 {
1236 hddLog(LOGE,
1237 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001238 ret = -EINVAL;
1239 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001240 }
1241 }
1242 else
1243 {
1244 // Reset WNI_CFG_PROBE_RSP Flags
1245 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1246
1247 hddLog(VOS_TRACE_LEVEL_INFO,
1248 "%s: No Probe Response IE received in set beacon",
1249 __func__);
1250 }
1251
1252 // Added for AssocResp IE
1253 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1254 {
1255 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1256 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1257 params->assocresp_ies_len, NULL,
1258 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1259 {
1260 hddLog(LOGE,
1261 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001262 ret = -EINVAL;
1263 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001264 }
1265
1266 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1267 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1268 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1269 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1270 == eHAL_STATUS_FAILURE)
1271 {
1272 hddLog(LOGE,
1273 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001274 ret = -EINVAL;
1275 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 }
1277 }
1278 else
1279 {
1280 hddLog(VOS_TRACE_LEVEL_INFO,
1281 "%s: No Assoc Response IE received in set beacon",
1282 __func__);
1283
1284 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1285 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1286 eANI_BOOLEAN_FALSE) )
1287 {
1288 hddLog(LOGE,
1289 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1290 }
1291 }
1292
Jeff Johnsone7245742012-09-05 17:12:55 -07001293done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001294 vos_mem_free(genie);
1295 return 0;
1296}
Jeff Johnson295189b2012-06-20 16:38:30 -07001297
1298/*
1299 * FUNCTION: wlan_hdd_validate_operation_channel
1300 * called by wlan_hdd_cfg80211_start_bss() and
1301 * wlan_hdd_cfg80211_set_channel()
1302 * This function validates whether given channel is part of valid
1303 * channel list.
1304 */
1305static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1306{
1307
1308 v_U32_t num_ch = 0;
1309 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1310 u32 indx = 0;
1311 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1312
1313 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1314
1315 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1316 valid_ch, &num_ch))
1317 {
1318 hddLog(VOS_TRACE_LEVEL_ERROR,
1319 "%s: failed to get valid channel list\n", __func__);
1320 return VOS_STATUS_E_FAILURE;
1321 }
1322
1323 for (indx = 0; indx < num_ch; indx++)
1324 {
1325 if (channel == valid_ch[indx])
1326 {
1327 break;
1328 }
1329 }
1330
1331 if (indx >= num_ch)
1332 {
1333 hddLog(VOS_TRACE_LEVEL_ERROR,
1334 "%s: Invalid Channel [%d] \n", __func__, channel);
1335 return VOS_STATUS_E_FAILURE;
1336 }
1337 return VOS_STATUS_SUCCESS;
1338
1339}
1340
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301341/*
1342 * FUNCTION: wlan_hdd_select_cbmode
1343 * called by wlan_hdd_cfg80211_start_bss() and
1344 * This function selects the cbmode based on primary channel
1345 */
Madan Mohan Koyyalamudicca761b2012-12-04 16:41:16 -08001346VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301347{
1348 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudicca761b2012-12-04 16:41:16 -08001349 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1350 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1351
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301352 if(
1353#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudicca761b2012-12-04 16:41:16 -08001354 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1355 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301356#endif
Madan Mohan Koyyalamudicca761b2012-12-04 16:41:16 -08001357 SapHw_mode != eSAP_DOT11_MODE_11n &&
1358 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301359 )
1360 {
1361 return VOS_STATUS_SUCCESS;
1362 }
1363
1364 if (!pConfigIni->nChannelBondingMode5GHz) {
1365 return VOS_STATUS_SUCCESS;
1366 }
1367
Madan Mohan Koyyalamudicca761b2012-12-04 16:41:16 -08001368 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301369 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1370
1371 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1372
1373#ifdef WLAN_FEATURE_11AC
1374
Madan Mohan Koyyalamudicca761b2012-12-04 16:41:16 -08001375 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1376 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301377 {
1378 if ( channel== 36 || channel == 52 || channel == 100 ||
1379 channel == 116 || channel == 149 )
1380 {
1381 smeConfig.csrConfig.channelBondingMode5GHz =
1382 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1383 }
1384 else if ( channel == 40 || channel == 56 || channel == 104 ||
1385 channel == 120 || channel == 153 )
1386 {
1387 smeConfig.csrConfig.channelBondingMode5GHz =
1388 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1389 }
1390 else if ( channel == 44 || channel == 60 || channel == 108 ||
1391 channel == 124 || channel == 157 )
1392 {
1393 smeConfig.csrConfig.channelBondingMode5GHz =
1394 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1395 }
1396 else if ( channel == 48 || channel == 64 || channel == 112 ||
1397 channel == 128 || channel == 161 )
1398 {
1399 smeConfig.csrConfig.channelBondingMode5GHz =
1400 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1401 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301402 }
1403#endif
Madan Mohan Koyyalamudicca761b2012-12-04 16:41:16 -08001404 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1405 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301406 {
1407 if ( channel== 40 || channel == 48 || channel == 56 ||
1408 channel == 64 || channel == 104 || channel == 112 ||
1409 channel == 120 || channel == 128 || channel == 136 ||
1410 channel == 144 || channel == 153 || channel == 161 )
1411 {
1412 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1413 }
1414 else if ( channel== 36 || channel == 44 || channel == 52 ||
1415 channel == 60 || channel == 100 || channel == 108 ||
1416 channel == 116 || channel == 124 || channel == 132 ||
1417 channel == 140 || channel == 149 || channel == 157 )
1418 {
1419 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1420 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301421 }
1422 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1423
1424 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1425 return VOS_STATUS_SUCCESS;
1426}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001427
Jeff Johnson295189b2012-06-20 16:38:30 -07001428#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1429static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1430 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001431#else
1432static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1433 struct cfg80211_beacon_data *params,
1434 const u8 *ssid, size_t ssid_len,
1435 enum nl80211_hidden_ssid hidden_ssid)
1436#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001437{
1438 tsap_Config_t *pConfig;
1439 beacon_data_t *pBeacon = NULL;
1440 struct ieee80211_mgmt *pMgmt_frame;
1441 v_U8_t *pIe=NULL;
1442 v_U16_t capab_info;
1443 eCsrAuthType RSNAuthType;
1444 eCsrEncryptionType RSNEncryptType;
1445 eCsrEncryptionType mcRSNEncryptType;
1446 int status = VOS_STATUS_SUCCESS;
1447 tpWLAN_SAPEventCB pSapEventCallback;
1448 hdd_hostapd_state_t *pHostapdState;
1449 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1450 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1451 struct qc_mac_acl_entry *acl_entry = NULL;
1452 v_SINT_t i;
Madan Mohan Koyyalamudi8bca2fd2012-12-05 16:40:18 -08001453 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001454
1455 ENTER();
1456
1457 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1458
1459 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1460
1461 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1462
1463 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1464
1465 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1466
1467 //channel is already set in the set_channel Call back
1468 //pConfig->channel = pCommitConfig->channel;
1469
1470 /*Protection parameter to enable or disable*/
1471 pConfig->protEnabled =
1472 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1473
1474 pConfig->dtim_period = pBeacon->dtim_period;
1475
1476 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1477 pConfig->dtim_period);
1478
1479
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001480 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001481 {
1482 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001483 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001484 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001485 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001486 tANI_BOOLEAN restartNeeded;
1487 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1488 pConfig->ieee80211d = 1;
1489 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1490 sme_setRegInfo(hHal, pConfig->countryCode);
1491 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1492 /*
1493 * If auto channel is configured i.e. channel is 0,
1494 * so skip channel validation.
1495 */
1496 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001497 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001498 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1499 {
1500 hddLog(VOS_TRACE_LEVEL_ERROR,
1501 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1502 return -EINVAL;
1503 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001504 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001505 /*
1506 * Validate the given channel range for the given country code
1507 */
1508 else
1509 {
Gopichand Nakkalac7b57c82013-01-07 14:52:52 -08001510 if(1 != pHddCtx->is_dynamic_channel_range_set)
Madan Mohan Koyyalamudi9ea58272012-12-27 17:26:52 -08001511 {
Madan Mohan Koyyalamudi8bca2fd2012-12-05 16:40:18 -08001512 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
Gopichand Nakkalac7b57c82013-01-07 14:52:52 -08001513 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
Madan Mohan Koyyalamudi9ea58272012-12-27 17:26:52 -08001514 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
Madan Mohan Koyyalamudi8bca2fd2012-12-05 16:40:18 -08001515 }
Gopichand Nakkalac7b57c82013-01-07 14:52:52 -08001516
Madan Mohan Koyyalamudi9ea58272012-12-27 17:26:52 -08001517 pHddCtx->is_dynamic_channel_range_set = 0;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001518 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001519 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001520 else
1521 {
1522 pConfig->ieee80211d = 0;
1523 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001524 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001525 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001526 {
1527 pConfig->ieee80211d = 0;
1528 }
1529 pConfig->authType = eSAP_AUTO_SWITCH;
1530
1531 capab_info = pMgmt_frame->u.beacon.capab_info;
1532
1533 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1534 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1535
1536 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1537
1538 /*Set wps station to configured*/
1539 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1540
1541 if(pIe)
1542 {
1543 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1544 {
1545 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1546 return -EINVAL;
1547 }
1548 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1549 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001550 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 /* Check 15 bit of WPS IE as it contain information for wps state
1552 * WPS state
1553 */
1554 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1555 {
1556 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1557 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1558 {
1559 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1560 }
1561 }
1562 }
1563 else
1564 {
1565 pConfig->wps_state = SAP_WPS_DISABLED;
1566 }
1567 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1568
1569 pConfig->RSNWPAReqIELength = 0;
1570 pConfig->pRSNWPAReqIE = NULL;
1571 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1572 WLAN_EID_RSN);
1573 if(pIe && pIe[1])
1574 {
1575 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1576 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1577 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1578 /* The actual processing may eventually be more extensive than
1579 * this. Right now, just consume any PMKIDs that are sent in
1580 * by the app.
1581 * */
1582 status = hdd_softap_unpackIE(
1583 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1584 &RSNEncryptType,
1585 &mcRSNEncryptType,
1586 &RSNAuthType,
1587 pConfig->pRSNWPAReqIE[1]+2,
1588 pConfig->pRSNWPAReqIE );
1589
1590 if( VOS_STATUS_SUCCESS == status )
1591 {
1592 /* Now copy over all the security attributes you have
1593 * parsed out
1594 * */
1595 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1596 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1597 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1598 = RSNEncryptType;
1599 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1600 "EncryptionType = %d mcEncryptionType = %d\n"),
1601 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1602 }
1603 }
1604
1605 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1606 pBeacon->tail, pBeacon->tail_len);
1607
1608 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1609 {
1610 if (pConfig->pRSNWPAReqIE)
1611 {
1612 /*Mixed mode WPA/WPA2*/
1613 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1614 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1615 }
1616 else
1617 {
1618 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1619 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1620 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1621 status = hdd_softap_unpackIE(
1622 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1623 &RSNEncryptType,
1624 &mcRSNEncryptType,
1625 &RSNAuthType,
1626 pConfig->pRSNWPAReqIE[1]+2,
1627 pConfig->pRSNWPAReqIE );
1628
1629 if( VOS_STATUS_SUCCESS == status )
1630 {
1631 /* Now copy over all the security attributes you have
1632 * parsed out
1633 * */
1634 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1635 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1636 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1637 = RSNEncryptType;
1638 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1639 "EncryptionType = %d mcEncryptionType = %d\n"),
1640 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1641 }
1642 }
1643 }
1644
1645 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1646
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001647#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001648 if (params->ssid != NULL)
1649 {
1650 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1651 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1652 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1653 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1654 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001655#else
1656 if (ssid != NULL)
1657 {
1658 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1659 pConfig->SSIDinfo.ssid.length = ssid_len;
1660 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1661 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1662 }
1663#endif
1664
Jeff Johnson295189b2012-06-20 16:38:30 -07001665 vos_mem_copy(pConfig->self_macaddr.bytes,
1666 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1667
1668 /* default value */
1669 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1670 pConfig->num_accept_mac = 0;
1671 pConfig->num_deny_mac = 0;
1672
1673 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1674 pBeacon->tail, pBeacon->tail_len);
1675
1676 /* pIe for black list is following form:
1677 type : 1 byte
1678 length : 1 byte
1679 OUI : 4 bytes
1680 acl type : 1 byte
1681 no of mac addr in black list: 1 byte
1682 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1683 */
1684 if ((pIe != NULL) && (pIe[1] != 0))
1685 {
1686 pConfig->SapMacaddr_acl = pIe[6];
1687 pConfig->num_deny_mac = pIe[7];
1688 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1689 pIe[6], pIe[7]);
1690 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1691 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1692 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1693 for (i = 0; i < pConfig->num_deny_mac; i++)
1694 {
1695 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1696 acl_entry++;
1697 }
1698 }
1699 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1700 pBeacon->tail, pBeacon->tail_len);
1701
1702 /* pIe for white list is following form:
1703 type : 1 byte
1704 length : 1 byte
1705 OUI : 4 bytes
1706 acl type : 1 byte
1707 no of mac addr in white list: 1 byte
1708 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1709 */
1710 if ((pIe != NULL) && (pIe[1] != 0))
1711 {
1712 pConfig->SapMacaddr_acl = pIe[6];
1713 pConfig->num_accept_mac = pIe[7];
1714 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1715 pIe[6], pIe[7]);
1716 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1717 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1718 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1719 for (i = 0; i < pConfig->num_accept_mac; i++)
1720 {
1721 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1722 acl_entry++;
1723 }
1724 }
1725 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1726
Jeff Johnsone7245742012-09-05 17:12:55 -07001727#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnav40e89bd2013-01-15 17:09:48 -08001728 /* Overwrite the hostapd setting for HW mode only for 11ac.
1729 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1730 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1731 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1732 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1733 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1734 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1735 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001736 {
1737 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1738 }
1739#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301740
Madan Mohan Koyyalamudicca761b2012-12-04 16:41:16 -08001741 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1742 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001743 // ht_capab is not what the name conveys,this is used for protection bitmap
1744 pConfig->ht_capab =
1745 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1746
1747 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1748 {
1749 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1750 return -EINVAL;
1751 }
1752
1753 //Uapsd Enabled Bit
1754 pConfig->UapsdEnable =
1755 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1756 //Enable OBSS protection
1757 pConfig->obssProtEnabled =
1758 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1759
1760 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1761 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1762 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1763 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1764 (int)pConfig->channel);
1765 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1766 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1767 pConfig->authType);
1768 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1769 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1770 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1771 pConfig->protEnabled, pConfig->obssProtEnabled);
1772
1773 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1774 {
1775 //Bss already started. just return.
1776 //TODO Probably it should update some beacon params.
1777 hddLog( LOGE, "Bss Already started...Ignore the request");
1778 EXIT();
1779 return 0;
1780 }
1781
1782 pConfig->persona = pHostapdAdapter->device_mode;
1783
1784 pSapEventCallback = hdd_hostapd_SAPEventCB;
1785 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1786 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1787 {
1788 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1789 return -EINVAL;
1790 }
1791
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001792 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001793 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1794
1795 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1796
1797 if (!VOS_IS_STATUS_SUCCESS(status))
1798 {
1799 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1800 ("ERROR: HDD vos wait for single_event failed!!\n"));
1801 VOS_ASSERT(0);
1802 }
1803
1804 //Succesfully started Bss update the state bit.
1805 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1806
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001807#ifdef WLAN_FEATURE_P2P_DEBUG
1808 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1809 {
1810 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1811 {
1812 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1813 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson3d710ea2012-12-10 14:31:52 -08001814 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001815 }
1816 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1817 {
1818 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1819 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson3d710ea2012-12-10 14:31:52 -08001820 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001821 }
1822 }
1823#endif
1824
Jeff Johnson295189b2012-06-20 16:38:30 -07001825 pHostapdState->bCommit = TRUE;
1826 EXIT();
1827
1828 return 0;
1829}
1830
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001831#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001832static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1833 struct net_device *dev,
1834 struct beacon_parameters *params)
1835{
1836 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1837 int status=VOS_STATUS_SUCCESS;
1838
1839 ENTER();
1840
1841 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1842
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001843 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1844 {
1845 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1846 "%s:LOGP in Progress. Ignore!!!", __func__);
1847 return -EAGAIN;
1848 }
1849
Jeff Johnson295189b2012-06-20 16:38:30 -07001850 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1851#ifdef WLAN_FEATURE_P2P
1852 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1853#endif
1854 )
1855 {
1856 beacon_data_t *old,*new;
1857
1858 old = pAdapter->sessionCtx.ap.beacon;
1859
1860 if (old)
1861 return -EALREADY;
1862
1863 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1864
1865 if(status != VOS_STATUS_SUCCESS)
1866 {
1867 hddLog(VOS_TRACE_LEVEL_FATAL,
1868 "%s:Error!!! Allocating the new beacon\n",__func__);
1869 return -EINVAL;
1870 }
1871
1872 pAdapter->sessionCtx.ap.beacon = new;
1873
1874 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1875 }
1876
1877 EXIT();
1878 return status;
1879}
1880
1881static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1882 struct net_device *dev,
1883 struct beacon_parameters *params)
1884{
1885 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1886 int status=VOS_STATUS_SUCCESS;
1887
1888 ENTER();
1889
1890 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1891 __func__,pAdapter->device_mode);
1892
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001893 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1894 {
1895 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1896 "%s:LOGP in Progress. Ignore!!!", __func__);
1897 return -EAGAIN;
1898 }
1899
Jeff Johnson295189b2012-06-20 16:38:30 -07001900 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1901#ifdef WLAN_FEATURE_P2P
1902 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1903#endif
1904 )
1905 {
1906 beacon_data_t *old,*new;
1907
1908 old = pAdapter->sessionCtx.ap.beacon;
1909
1910 if (!old)
1911 return -ENOENT;
1912
1913 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1914
1915 if(status != VOS_STATUS_SUCCESS) {
1916 hddLog(VOS_TRACE_LEVEL_FATAL,
1917 "%s: Error!!! Allocating the new beacon\n",__func__);
1918 return -EINVAL;
1919 }
1920
1921 pAdapter->sessionCtx.ap.beacon = new;
1922
1923 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1924 }
1925
1926 EXIT();
1927 return status;
1928}
1929
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001930#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1931
1932#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001933static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1934 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001935#else
1936static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1937 struct net_device *dev)
1938#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001939{
1940 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001941 hdd_context_t *pHddCtx = NULL;
1942 hdd_scaninfo_t *pScanInfo = NULL;
1943 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001944 VOS_STATUS status = 0;
1945
1946 ENTER();
1947
1948 if (NULL == pAdapter)
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__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001952 return -ENODEV;
1953 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001954 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1955 {
1956 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1957 "%s:LOGP in Progress. Ignore!!!", __func__);
1958 return -EAGAIN;
1959 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001960
1961 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1962 if (NULL == pHddCtx)
1963 {
1964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001965 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001966 return -ENODEV;
1967 }
1968
1969 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1970 if (NULL == staAdapter)
1971 {
1972 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1973 if (NULL == staAdapter)
1974 {
1975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001976 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001977 return -ENODEV;
1978 }
1979 }
1980
1981 pScanInfo = &pHddCtx->scan_info;
1982
Jeff Johnson295189b2012-06-20 16:38:30 -07001983 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1984 {
1985 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1986 return -EAGAIN;
1987 }
1988
1989 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1990
1991 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1992 __func__,pAdapter->device_mode);
1993
Jeff Johnsone7245742012-09-05 17:12:55 -07001994 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1995 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001996 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001997 hdd_abort_mac_scan(staAdapter->pHddCtx);
1998 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001999 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07002000 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
2001 if (!status)
2002 {
2003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1920a722012-12-10 14:28:09 -08002004 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002005 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07002006 VOS_ASSERT(pScanInfo->mScanPending);
2007 return 0;
2008 }
2009 }
2010
Jeff Johnson295189b2012-06-20 16:38:30 -07002011 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2012#ifdef WLAN_FEATURE_P2P
2013 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2014#endif
2015 )
2016 {
2017 beacon_data_t *old;
2018
2019 old = pAdapter->sessionCtx.ap.beacon;
2020
2021 if (!old)
2022 return -ENOENT;
2023
2024#ifdef CONFIG_CFG80211
2025 hdd_cleanup_actionframe(pHddCtx, pAdapter);
2026#endif
2027
2028 mutex_lock(&pHddCtx->sap_lock);
2029 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2030 {
2031 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2032 {
2033 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2034
2035 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2036
2037 if (!VOS_IS_STATUS_SUCCESS(status))
2038 {
2039 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2040 ("ERROR: HDD vos wait for single_event failed!!\n"));
2041 VOS_ASSERT(0);
2042 }
2043 }
2044 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2045 }
2046 mutex_unlock(&pHddCtx->sap_lock);
2047
2048 if(status != VOS_STATUS_SUCCESS)
2049 {
2050 hddLog(VOS_TRACE_LEVEL_FATAL,
2051 "%s:Error!!! Stopping the BSS\n",__func__);
2052 return -EINVAL;
2053 }
2054
2055 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2056 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2057 ==eHAL_STATUS_FAILURE)
2058 {
2059 hddLog(LOGE,
2060 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2061 }
2062
2063 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2064 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2065 eANI_BOOLEAN_FALSE) )
2066 {
2067 hddLog(LOGE,
2068 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2069 }
2070
2071 // Reset WNI_CFG_PROBE_RSP Flags
2072 wlan_hdd_reset_prob_rspies(pAdapter);
2073
2074 pAdapter->sessionCtx.ap.beacon = NULL;
2075 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002076#ifdef WLAN_FEATURE_P2P_DEBUG
2077 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2078 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2079 {
2080 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2081 "GO got removed");
2082 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2083 }
2084#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002085 }
2086 EXIT();
2087 return status;
2088}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002089
2090#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2091
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302092static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2093 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002094 struct cfg80211_ap_settings *params)
2095{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302096 hdd_adapter_t *pAdapter;
2097 hdd_context_t *pHddCtx;
2098 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002099
2100 ENTER();
2101
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302102 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002103 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302104 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2105 "%s: Device is Null", __func__);
2106 return -ENODEV;
2107 }
2108
2109 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2110 if (NULL == pAdapter)
2111 {
2112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2113 "%s: HDD adapter is Null", __func__);
2114 return -ENODEV;
2115 }
2116
2117 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2118 {
2119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2120 "%s: HDD adapter magic is invalid", __func__);
2121 return -ENODEV;
2122 }
2123
2124 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2125 if (NULL == pHddCtx)
2126 {
2127 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2128 "%s: HDD context is Null", __func__);
2129 return -ENODEV;
2130 }
2131
2132 if (pHddCtx->isLogpInProgress)
2133 {
2134 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2135 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002136 return -EAGAIN;
2137 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302138
2139 if (pHddCtx->isLoadUnloadInProgress)
2140 {
2141 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2142 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2143 return -EAGAIN;
2144 }
2145
2146 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2147 __func__, pAdapter->device_mode);
2148
2149 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002150#ifdef WLAN_FEATURE_P2P
2151 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2152#endif
2153 )
2154 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302155 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002156
2157 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302158
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002159 if (old)
2160 return -EALREADY;
2161
2162 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2163
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302164 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002165 {
2166 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302167 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002168 return -EINVAL;
2169 }
2170 pAdapter->sessionCtx.ap.beacon = new;
2171 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2172 params->ssid_len, params->hidden_ssid);
2173 }
2174
2175 EXIT();
2176 return status;
2177}
2178
2179
2180static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2181 struct net_device *dev,
2182 struct cfg80211_beacon_data *params)
2183{
2184 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2185 int status=VOS_STATUS_SUCCESS;
2186
2187 ENTER();
2188
2189 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2190 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002191 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2192 {
2193 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2194 return -EAGAIN;
2195 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002196
2197 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2198#ifdef WLAN_FEATURE_P2P
2199 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2200#endif
2201 )
2202 {
2203 beacon_data_t *old,*new;
2204
2205 old = pAdapter->sessionCtx.ap.beacon;
2206
2207 if (!old)
2208 return -ENOENT;
2209
2210 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2211
2212 if(status != VOS_STATUS_SUCCESS) {
2213 hddLog(VOS_TRACE_LEVEL_FATAL,
2214 "%s: Error!!! Allocating the new beacon\n",__func__);
2215 return -EINVAL;
2216 }
2217
2218 pAdapter->sessionCtx.ap.beacon = new;
2219
2220 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2221 }
2222
2223 EXIT();
2224 return status;
2225}
2226
2227#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2228
Jeff Johnson295189b2012-06-20 16:38:30 -07002229
2230static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2231 struct net_device *dev,
2232 struct bss_parameters *params)
2233{
2234 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2235
2236 ENTER();
2237
2238 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2239 __func__,pAdapter->device_mode);
2240
2241 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2242#ifdef WLAN_FEATURE_P2P
2243 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2244#endif
2245 )
2246 {
2247 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2248 * want to update this parameter */
2249 if (-1 != params->ap_isolate)
2250 {
2251 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2252 }
2253 }
2254
2255 EXIT();
2256 return 0;
2257}
2258
2259/*
2260 * FUNCTION: wlan_hdd_cfg80211_change_iface
2261 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2262 */
2263int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2264 struct net_device *ndev,
2265 enum nl80211_iftype type,
2266 u32 *flags,
2267 struct vif_params *params
2268 )
2269{
2270 struct wireless_dev *wdev;
2271 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2272 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002273 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002274 tCsrRoamProfile *pRoamProfile = NULL;
2275 eCsrRoamBssType LastBSSType;
2276 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2277 eMib_dot11DesiredBssType connectedBssType;
2278 VOS_STATUS status;
2279
2280 ENTER();
2281
2282 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2283 {
2284 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2285 return -EAGAIN;
2286 }
2287
2288 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2289 __func__, pAdapter->device_mode);
2290
2291 wdev = ndev->ieee80211_ptr;
2292
2293#ifdef WLAN_BTAMP_FEATURE
2294 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2295 (NL80211_IFTYPE_ADHOC == type)||
2296 (NL80211_IFTYPE_AP == type)||
2297 (NL80211_IFTYPE_P2P_GO == type))
2298 {
2299 pHddCtx->isAmpAllowed = VOS_FALSE;
2300 // stop AMP traffic
2301 status = WLANBAP_StopAmp();
2302 if(VOS_STATUS_SUCCESS != status )
2303 {
2304 pHddCtx->isAmpAllowed = VOS_TRUE;
2305 hddLog(VOS_TRACE_LEVEL_FATAL,
2306 "%s: Failed to stop AMP", __func__);
2307 return -EINVAL;
2308 }
2309 }
2310#endif //WLAN_BTAMP_FEATURE
2311 /* Reset the current device mode bit mask*/
2312 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2313
2314 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2315#ifdef WLAN_FEATURE_P2P
2316 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002317 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002318#endif
2319 )
2320 {
2321 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2322 pRoamProfile = &pWextState->roamProfile;
2323 LastBSSType = pRoamProfile->BSSType;
2324
2325 switch (type)
2326 {
2327 case NL80211_IFTYPE_STATION:
2328#ifdef WLAN_FEATURE_P2P
2329 case NL80211_IFTYPE_P2P_CLIENT:
2330#endif
2331 hddLog(VOS_TRACE_LEVEL_INFO,
2332 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2333 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002334#ifdef WLAN_FEATURE_11AC
2335 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2336 {
2337 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2338 }
2339#endif
2340 pRoamProfile->phyMode =
2341 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002342 wdev->iftype = type;
2343#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala310362f2012-12-31 16:35:10 -08002344 //Check for sub-string p2p to confirm its a p2p interface
2345 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkalaad9ed1a2012-12-31 16:08:51 -08002346 {
2347 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2348 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2349 }
2350 else
2351 {
2352 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002353 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkalaad9ed1a2012-12-31 16:08:51 -08002354 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002355#endif
2356 break;
2357 case NL80211_IFTYPE_ADHOC:
2358 hddLog(VOS_TRACE_LEVEL_INFO,
2359 "%s: setting interface Type to ADHOC", __func__);
2360 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2361 pRoamProfile->phyMode =
2362 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2363 wdev->iftype = type;
2364 break;
2365
2366 case NL80211_IFTYPE_AP:
2367#ifdef WLAN_FEATURE_P2P
2368 case NL80211_IFTYPE_P2P_GO:
2369#endif
2370 {
2371 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2372 "%s: setting interface Type to %s", __func__,
2373 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2374
Gopichand Nakkala310362f2012-12-31 16:35:10 -08002375 //Cancel any remain on channel for GO mode
2376 if (NL80211_IFTYPE_P2P_GO == type)
2377 {
2378 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2379 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002380 if (NL80211_IFTYPE_AP == type)
2381 {
2382 /* As Loading WLAN Driver one interface being created for p2p device
2383 * address. This will take one HW STA and the max number of clients
2384 * that can connect to softAP will be reduced by one. so while changing
2385 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2386 * interface as it is not required in SoftAP mode.
2387 */
2388
2389 // Get P2P Adapter
2390 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2391
2392 if (pP2pAdapter)
2393 {
2394 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2395 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2396 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2397 }
2398 }
2399
Jeff Johnson295189b2012-06-20 16:38:30 -07002400 //De-init the adapter.
2401 hdd_stop_adapter( pHddCtx, pAdapter );
2402 hdd_deinit_adapter( pHddCtx, pAdapter );
2403 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2404#ifdef WLAN_SOFTAP_FEATURE
2405#ifdef WLAN_FEATURE_P2P
2406 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2407 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2408#else
2409 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2410#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002411
2412 //Disable BMPS and IMPS if enabled
2413 //before starting Go
2414 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2415 {
2416 if(VOS_STATUS_E_FAILURE ==
2417 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2418 {
2419 //Fail to Exit BMPS
2420 VOS_ASSERT(0);
2421 }
2422 }
2423
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002424 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2425 (pConfig->apRandomBssidEnabled))
2426 {
2427 /* To meet Android requirements create a randomized
2428 MAC address of the form 02:1A:11:Fx:xx:xx */
2429 get_random_bytes(&ndev->dev_addr[3], 3);
2430 ndev->dev_addr[0] = 0x02;
2431 ndev->dev_addr[1] = 0x1A;
2432 ndev->dev_addr[2] = 0x11;
2433 ndev->dev_addr[3] |= 0xF0;
2434 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2435 VOS_MAC_ADDR_SIZE);
2436 pr_info("wlan: Generated HotSpot BSSID "
2437 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2438 ndev->dev_addr[0],
2439 ndev->dev_addr[1],
2440 ndev->dev_addr[2],
2441 ndev->dev_addr[3],
2442 ndev->dev_addr[4],
2443 ndev->dev_addr[5]);
2444 }
2445
Jeff Johnson295189b2012-06-20 16:38:30 -07002446 hdd_set_ap_ops( pAdapter->dev );
2447
2448 status = hdd_init_ap_mode(pAdapter);
2449 if(status != VOS_STATUS_SUCCESS)
2450 {
2451 hddLog(VOS_TRACE_LEVEL_FATAL,
2452 "%s: Error initializing the ap mode", __func__);
2453 return -EINVAL;
2454 }
2455 hdd_set_conparam(1);
2456
2457#endif
2458 /*interface type changed update in wiphy structure*/
2459 if(wdev)
2460 {
2461 wdev->iftype = type;
2462 pHddCtx->change_iface = type;
2463 }
2464 else
2465 {
2466 hddLog(VOS_TRACE_LEVEL_ERROR,
2467 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2468 return -EINVAL;
2469 }
2470 goto done;
2471 }
2472
2473 default:
2474 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2475 __func__);
2476 return -EOPNOTSUPP;
2477 }
2478 }
2479 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2480#ifdef WLAN_FEATURE_P2P
2481 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2482#endif
2483 )
2484 {
2485 switch(type)
2486 {
2487 case NL80211_IFTYPE_STATION:
2488#ifdef WLAN_FEATURE_P2P
2489 case NL80211_IFTYPE_P2P_CLIENT:
2490#endif
2491 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002492 hdd_stop_adapter( pHddCtx, pAdapter );
2493 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002494 wdev->iftype = type;
2495#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala310362f2012-12-31 16:35:10 -08002496 //Check for sub-string p2p to confirm its a p2p interface
2497 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkalaad9ed1a2012-12-31 16:08:51 -08002498 {
2499 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2500 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2501 }
2502 else
2503 {
2504 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002505 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkalaad9ed1a2012-12-31 16:08:51 -08002506 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002507#endif
2508 hdd_set_conparam(0);
2509 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002510 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2511 hdd_set_station_ops( pAdapter->dev );
2512 status = hdd_init_station_mode( pAdapter );
2513 if( VOS_STATUS_SUCCESS != status )
2514 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002515 /* In case of JB, for P2P-GO, only change interface will be called,
2516 * This is the right place to enable back bmps_imps()
2517 */
2518 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002519 goto done;
2520 case NL80211_IFTYPE_AP:
2521#ifdef WLAN_FEATURE_P2P
2522 case NL80211_IFTYPE_P2P_GO:
2523#endif
2524 wdev->iftype = type;
2525#ifdef WLAN_FEATURE_P2P
2526 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2527 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2528#endif
2529 goto done;
2530 default:
2531 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2532 __func__);
2533 return -EOPNOTSUPP;
2534
2535 }
2536
2537 }
2538 else
2539 {
2540 return -EOPNOTSUPP;
2541 }
2542
2543
2544 if(pRoamProfile)
2545 {
2546 if ( LastBSSType != pRoamProfile->BSSType )
2547 {
2548 /*interface type changed update in wiphy structure*/
2549 wdev->iftype = type;
2550
2551 /*the BSS mode changed, We need to issue disconnect
2552 if connected or in IBSS disconnect state*/
2553 if ( hdd_connGetConnectedBssType(
2554 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2555 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2556 {
2557 /*need to issue a disconnect to CSR.*/
2558 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2559 if( eHAL_STATUS_SUCCESS ==
2560 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2561 pAdapter->sessionId,
2562 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2563 {
2564 wait_for_completion_interruptible_timeout(
2565 &pAdapter->disconnect_comp_var,
2566 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2567 }
2568 }
2569 }
2570 }
2571
2572done:
2573 /*set bitmask based on updated value*/
2574 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2575#ifdef WLAN_BTAMP_FEATURE
2576 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2577 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2578 {
2579 //we are ok to do AMP
2580 pHddCtx->isAmpAllowed = VOS_TRUE;
2581 }
2582#endif //WLAN_BTAMP_FEATURE
2583 EXIT();
2584 return 0;
2585}
2586
2587static int wlan_hdd_change_station(struct wiphy *wiphy,
2588 struct net_device *dev,
2589 u8 *mac,
2590 struct station_parameters *params)
2591{
2592 VOS_STATUS status = VOS_STATUS_SUCCESS;
2593 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2594 v_MACADDR_t STAMacAddress;
2595
Jeff Johnsone7245742012-09-05 17:12:55 -07002596 ENTER();
2597
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002598 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2599 {
2600 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2601 "%s:LOGP in Progress. Ignore!!!", __func__);
2602 return -EAGAIN;
2603 }
2604
Jeff Johnson295189b2012-06-20 16:38:30 -07002605 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2606
2607 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2608#ifdef WLAN_FEATURE_P2P
2609 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2610#endif
2611 )
2612 {
2613 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2614 {
2615 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2616 WLANTL_STA_AUTHENTICATED);
2617
2618 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002619 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002620 return -EINVAL;
2621 }
2622 }
2623
Jeff Johnsone7245742012-09-05 17:12:55 -07002624 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002625 return status;
2626}
2627
2628/*
2629 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2630 * This function is used to get peer station index in IBSS mode
2631 */
2632static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2633{
2634 u8 idx = 0;
2635 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2636 ENTER();
2637 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2638 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2639 {
2640 if ( (0 !=
2641 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2642 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2643 temp, VOS_MAC_ADDR_SIZE)
2644 )
2645 {
2646 return idx;
2647 }
2648 }
2649 return idx;
2650}
2651
2652
2653/*
2654 * FUNCTION: wlan_hdd_cfg80211_add_key
2655 * This function is used to initialize the key information
2656 */
2657#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2658static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2659 struct net_device *ndev,
2660 u8 key_index, bool pairwise,
2661 const u8 *mac_addr,
2662 struct key_params *params
2663 )
2664#else
2665static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2666 struct net_device *ndev,
2667 u8 key_index, const u8 *mac_addr,
2668 struct key_params *params
2669 )
2670#endif
2671{
2672 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2673 tCsrRoamSetKey setKey;
2674 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2675 int status = 0;
2676 v_U32_t roamId= 0xFF;
2677 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2678 hdd_hostapd_state_t *pHostapdState;
2679 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002680 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002681
2682 ENTER();
2683
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002684 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2685 {
2686 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2687 "%s:LOGP in Progress. Ignore!!!", __func__);
2688 return -EAGAIN;
2689 }
2690
Jeff Johnson295189b2012-06-20 16:38:30 -07002691 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2692 __func__,pAdapter->device_mode);
2693
2694 if (CSR_MAX_NUM_KEY <= key_index)
2695 {
2696 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2697 key_index);
2698
2699 return -EINVAL;
2700 }
2701
2702 hddLog(VOS_TRACE_LEVEL_INFO,
2703 "%s: called with key index = %d & key length %d",
2704 __func__, key_index, params->key_len);
2705
2706 /*extract key idx, key len and key*/
2707 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2708 setKey.keyId = key_index;
2709 setKey.keyLength = params->key_len;
2710 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2711
2712 switch (params->cipher)
2713 {
2714 case WLAN_CIPHER_SUITE_WEP40:
2715 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2716 break;
2717
2718 case WLAN_CIPHER_SUITE_WEP104:
2719 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2720 break;
2721
2722 case WLAN_CIPHER_SUITE_TKIP:
2723 {
2724 u8 *pKey = &setKey.Key[0];
2725 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2726
2727 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2728
2729 /*Supplicant sends the 32bytes key in this order
2730
2731 |--------------|----------|----------|
2732 | Tk1 |TX-MIC | RX Mic |
2733 |--------------|----------|----------|
2734 <---16bytes---><--8bytes--><--8bytes-->
2735
2736 */
2737 /*Sme expects the 32 bytes key to be in the below order
2738
2739 |--------------|----------|----------|
2740 | Tk1 |RX-MIC | TX Mic |
2741 |--------------|----------|----------|
2742 <---16bytes---><--8bytes--><--8bytes-->
2743 */
2744 /* Copy the Temporal Key 1 (TK1) */
2745 vos_mem_copy(pKey, params->key,16);
2746
2747 /*Copy the rx mic first*/
2748 vos_mem_copy(&pKey[16],&params->key[24],8);
2749
2750 /*Copy the tx mic */
2751 vos_mem_copy(&pKey[24],&params->key[16],8);
2752
2753
2754 break;
2755 }
2756
2757 case WLAN_CIPHER_SUITE_CCMP:
2758 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2759 break;
2760
2761#ifdef FEATURE_WLAN_WAPI
2762 case WLAN_CIPHER_SUITE_SMS4:
2763 {
2764 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2765 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2766 params->key, params->key_len);
2767 return 0;
2768 }
2769#endif
2770#ifdef FEATURE_WLAN_CCX
2771 case WLAN_CIPHER_SUITE_KRK:
2772 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2773 break;
2774#endif
2775 default:
2776 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2777 __func__, params->cipher);
2778 return -EOPNOTSUPP;
2779 }
2780
2781 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2782 __func__, setKey.encType);
2783
2784
2785
2786 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2787#ifdef WLAN_FEATURE_P2P
2788 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2789#endif
2790 )
2791 {
2792
2793
2794 if (
2795#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2796 (!pairwise)
2797#else
2798 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2799#endif
2800 )
2801 {
2802 /* set group key*/
2803 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson3d710ea2012-12-10 14:31:52 -08002804 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002805 __func__, __LINE__);
2806 setKey.keyDirection = eSIR_RX_ONLY;
2807 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2808 }
2809 else
2810 {
2811 /* set pairwise key*/
2812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2813 "%s- %d: setting pairwise key",
2814 __func__, __LINE__);
2815 setKey.keyDirection = eSIR_TX_RX;
2816 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2817 }
2818
2819 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2820 if( pHostapdState->bssState == BSS_START )
2821 {
2822 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2823
2824 if ( status != eHAL_STATUS_SUCCESS )
2825 {
2826 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2827 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2828 __LINE__, status );
2829 }
2830 }
2831
2832 /* Saving WEP keys */
2833 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2834 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2835 {
2836 //Save the wep key in ap context. Issue setkey after the BSS is started.
2837 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2838 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2839 }
2840 else
2841 {
2842 //Save the key in ap context. Issue setkey after the BSS is started.
2843 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2844 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2845 }
2846 }
2847 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2848#ifdef WLAN_FEATURE_P2P
2849 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2850#endif
2851 )
2852 {
2853 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2854 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2855
2856 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2857
Venkata Prathyusha Kuntupalli584507e2013-01-17 14:09:24 -08002858 pWextState->roamProfile.Keys.defaultIndex = key_index;
2859
2860
Jeff Johnson295189b2012-06-20 16:38:30 -07002861 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2862 params->key, params->key_len);
2863
2864 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2865
2866 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2867 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2868 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2869 )
2870 &&
2871 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2872 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2873 )
2874 )
2875 {
2876 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2877 * interface, copy bssid for pairwise key and group macaddr for
2878 * group key initialization*/
2879
2880 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2881
2882 pWextState->roamProfile.negotiatedUCEncryptionType =
2883 pHddStaCtx->conn_info.ucEncryptionType =
2884 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2885 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2886 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2887
2888
2889 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2890 "%s: Negotiated encryption type %d", __func__,
2891 pWextState->roamProfile.negotiatedUCEncryptionType);
2892
2893 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2894 &pWextState->roamProfile, true);
2895 setKey.keyLength = 0;
2896 setKey.keyDirection = eSIR_TX_RX;
2897
2898#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2899 if (pairwise)
2900 {
2901#endif
2902 if (mac_addr)
2903 {
2904 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2905 }
2906 else
2907 {
2908 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2909 * and peerMacAddress in case of IBSS*/
2910 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2911 {
2912 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2913 if (HDD_MAX_NUM_IBSS_STA != staidx)
2914 {
2915 vos_mem_copy(setKey.peerMac,
2916 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2917 WNI_CFG_BSSID_LEN);
2918
2919 }
2920 else
2921 {
2922 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2923 __func__);
2924 return -EOPNOTSUPP;
2925 }
2926 }
2927 else
2928 {
2929 vos_mem_copy(setKey.peerMac,
2930 &pHddStaCtx->conn_info.bssId[0],
2931 WNI_CFG_BSSID_LEN);
2932 }
2933 }
2934#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2935 }
2936 else
2937 {
2938 /* set group key*/
2939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2940 "%s- %d: setting Group key",
2941 __func__, __LINE__);
2942 setKey.keyDirection = eSIR_RX_ONLY;
2943 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2944 }
2945#endif
2946 }
2947 else if (
2948#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2949 (!pairwise)
2950#else
2951 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2952#endif
2953 )
2954 {
2955 /* set group key*/
2956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2957 "%s- %d: setting Group key",
2958 __func__, __LINE__);
2959 setKey.keyDirection = eSIR_RX_ONLY;
2960 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2961 }
2962 else
2963 {
2964 /* set pairwise key*/
2965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2966 "%s- %d: setting pairwise key",
2967 __func__, __LINE__);
2968 setKey.keyDirection = eSIR_TX_RX;
2969 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2970 }
2971
2972 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2973 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2974 __func__, setKey.peerMac[0], setKey.peerMac[1],
2975 setKey.peerMac[2], setKey.peerMac[3],
2976 setKey.peerMac[4], setKey.peerMac[5],
2977 setKey.keyDirection);
2978
2979 vos_status = wlan_hdd_check_ula_done(pAdapter);
2980
2981 if ( vos_status != VOS_STATUS_SUCCESS )
2982 {
2983 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2984 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2985 __LINE__, vos_status );
2986
2987 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2988
2989 return -EINVAL;
2990
2991 }
2992
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002993#ifdef WLAN_FEATURE_VOWIFI_11R
2994 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2995 Save the key in the UMAC and include it in the ADD BSS request */
2996 /*TODO 11r - is this used?? */
2997 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2998 if( halStatus == eHAL_STATUS_SUCCESS )
2999 {
3000 return halStatus;
3001 }
3002#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07003003
3004 /* issue set key request to SME*/
3005 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3006 pAdapter->sessionId, &setKey, &roamId );
3007
3008 if ( 0 != status )
3009 {
3010 hddLog(VOS_TRACE_LEVEL_ERROR,
3011 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
3012 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3013 return -EINVAL;
3014 }
3015
3016
3017 /* in case of IBSS as there was no information available about WEP keys during
3018 * IBSS join, group key intialized with NULL key, so re-initialize group key
3019 * with correct value*/
3020 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
3021 !( ( IW_AUTH_KEY_MGMT_802_1X
3022 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
3023 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
3024 )
3025 &&
3026 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3027 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3028 )
3029 )
3030 {
3031 setKey.keyDirection = eSIR_RX_ONLY;
3032 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3033
3034 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3035 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3036 __func__, setKey.peerMac[0], setKey.peerMac[1],
3037 setKey.peerMac[2], setKey.peerMac[3],
3038 setKey.peerMac[4], setKey.peerMac[5],
3039 setKey.keyDirection);
3040
3041 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3042 pAdapter->sessionId, &setKey, &roamId );
3043
3044 if ( 0 != status )
3045 {
3046 hddLog(VOS_TRACE_LEVEL_ERROR,
3047 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3048 __func__, status);
3049 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3050 return -EINVAL;
3051 }
3052 }
3053 }
3054
3055 return 0;
3056}
3057
3058/*
3059 * FUNCTION: wlan_hdd_cfg80211_get_key
3060 * This function is used to get the key information
3061 */
3062#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3063static int wlan_hdd_cfg80211_get_key(
3064 struct wiphy *wiphy,
3065 struct net_device *ndev,
3066 u8 key_index, bool pairwise,
3067 const u8 *mac_addr, void *cookie,
3068 void (*callback)(void *cookie, struct key_params*)
3069 )
3070#else
3071static int wlan_hdd_cfg80211_get_key(
3072 struct wiphy *wiphy,
3073 struct net_device *ndev,
3074 u8 key_index, const u8 *mac_addr, void *cookie,
3075 void (*callback)(void *cookie, struct key_params*)
3076 )
3077#endif
3078{
3079 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3080 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3081 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3082 struct key_params params;
3083
3084 ENTER();
3085
3086 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3087 __func__,pAdapter->device_mode);
3088
3089 memset(&params, 0, sizeof(params));
3090
3091 if (CSR_MAX_NUM_KEY <= key_index)
3092 {
3093 return -EINVAL;
3094 }
3095
3096 switch(pRoamProfile->EncryptionType.encryptionType[0])
3097 {
3098 case eCSR_ENCRYPT_TYPE_NONE:
3099 params.cipher = IW_AUTH_CIPHER_NONE;
3100 break;
3101
3102 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3103 case eCSR_ENCRYPT_TYPE_WEP40:
3104 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3105 break;
3106
3107 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3108 case eCSR_ENCRYPT_TYPE_WEP104:
3109 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3110 break;
3111
3112 case eCSR_ENCRYPT_TYPE_TKIP:
3113 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3114 break;
3115
3116 case eCSR_ENCRYPT_TYPE_AES:
3117 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3118 break;
3119
3120 default:
3121 params.cipher = IW_AUTH_CIPHER_NONE;
3122 break;
3123 }
3124
3125 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3126 params.seq_len = 0;
3127 params.seq = NULL;
3128 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3129 callback(cookie, &params);
3130 return 0;
3131}
3132
3133/*
3134 * FUNCTION: wlan_hdd_cfg80211_del_key
3135 * This function is used to delete the key information
3136 */
3137#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3138static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3139 struct net_device *ndev,
3140 u8 key_index,
3141 bool pairwise,
3142 const u8 *mac_addr
3143 )
3144#else
3145static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3146 struct net_device *ndev,
3147 u8 key_index,
3148 const u8 *mac_addr
3149 )
3150#endif
3151{
3152 int status = 0;
3153
3154 //This code needs to be revisited. There is sme_removeKey API, we should
3155 //plan to use that. After the change to use correct index in setkey,
3156 //it is observed that this is invalidating peer
3157 //key index whenever re-key is done. This is affecting data link.
3158 //It should be ok to ignore del_key.
3159#if 0
3160 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3161 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3162 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3163 tCsrRoamSetKey setKey;
3164 v_U32_t roamId= 0xFF;
3165
3166 ENTER();
3167
3168 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3169 __func__,pAdapter->device_mode);
3170
3171 if (CSR_MAX_NUM_KEY <= key_index)
3172 {
3173 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3174 key_index);
3175
3176 return -EINVAL;
3177 }
3178
3179 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3180 setKey.keyId = key_index;
3181
3182 if (mac_addr)
3183 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3184 else
3185 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3186
3187 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3188
3189 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3190#ifdef WLAN_FEATURE_P2P
3191 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3192#endif
3193 )
3194 {
3195
3196 hdd_hostapd_state_t *pHostapdState =
3197 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3198 if( pHostapdState->bssState == BSS_START)
3199 {
3200 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3201
3202 if ( status != eHAL_STATUS_SUCCESS )
3203 {
3204 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3205 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3206 __LINE__, status );
3207 }
3208 }
3209 }
3210 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3211#ifdef WLAN_FEATURE_P2P
3212 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3213#endif
3214 )
3215 {
3216 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3217
3218 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3219
3220 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3221 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3222 __func__, setKey.peerMac[0], setKey.peerMac[1],
3223 setKey.peerMac[2], setKey.peerMac[3],
3224 setKey.peerMac[4], setKey.peerMac[5]);
3225 if(pAdapter->sessionCtx.station.conn_info.connState ==
3226 eConnectionState_Associated)
3227 {
3228 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3229 pAdapter->sessionId, &setKey, &roamId );
3230
3231 if ( 0 != status )
3232 {
3233 hddLog(VOS_TRACE_LEVEL_ERROR,
3234 "%s: sme_RoamSetKey failure, returned %d",
3235 __func__, status);
3236 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3237 return -EINVAL;
3238 }
3239 }
3240 }
3241#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003242 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003243 return status;
3244}
3245
3246/*
3247 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3248 * This function is used to set the default tx key index
3249 */
3250#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3251static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3252 struct net_device *ndev,
3253 u8 key_index,
3254 bool unicast, bool multicast)
3255#else
3256static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3257 struct net_device *ndev,
3258 u8 key_index)
3259#endif
3260{
3261 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3262 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3263 int status = 0;
3264 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3265
3266 ENTER();
3267
3268 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3269 __func__,pAdapter->device_mode, key_index);
3270
3271 if (CSR_MAX_NUM_KEY <= key_index)
3272 {
3273 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3274 key_index);
3275
3276 return -EINVAL;
3277 }
3278
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003279 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3280 {
3281 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3282 "%s:LOGP in Progress. Ignore!!!", __func__);
3283 return -EAGAIN;
3284 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003285
3286 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3287#ifdef WLAN_FEATURE_P2P
3288 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3289#endif
3290 )
3291 {
3292 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3293 (eCSR_ENCRYPT_TYPE_TKIP !=
3294 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3295 (eCSR_ENCRYPT_TYPE_AES !=
3296 pWextState->roamProfile.EncryptionType.encryptionType[0])
3297 )
3298 {
3299 /* if default key index is not same as previous one,
3300 * then update the default key index */
3301
3302 tCsrRoamSetKey setKey;
3303 v_U32_t roamId= 0xFF;
3304 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3305
3306 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3307 __func__, key_index);
3308
3309 Keys->defaultIndex = (u8)key_index;
3310 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3311 setKey.keyId = key_index;
3312 setKey.keyLength = Keys->KeyLength[key_index];
3313
3314 vos_mem_copy(&setKey.Key[0],
3315 &Keys->KeyMaterial[key_index][0],
3316 Keys->KeyLength[key_index]);
3317
3318 setKey.keyDirection = eSIR_TX_ONLY;
3319
3320 vos_mem_copy(setKey.peerMac,
3321 &pHddStaCtx->conn_info.bssId[0],
3322 WNI_CFG_BSSID_LEN);
3323
3324 setKey.encType =
3325 pWextState->roamProfile.EncryptionType.encryptionType[0];
3326
3327 /* issue set key request */
3328 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3329 pAdapter->sessionId, &setKey, &roamId );
3330
3331 if ( 0 != status )
3332 {
3333 hddLog(VOS_TRACE_LEVEL_ERROR,
3334 "%s: sme_RoamSetKey failed, returned %d", __func__,
3335 status);
3336 return -EINVAL;
3337 }
3338 }
3339 }
3340
3341 /* In SoftAp mode setting key direction for default mode */
3342 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3343 {
3344 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3345 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3346 (eCSR_ENCRYPT_TYPE_AES !=
3347 pWextState->roamProfile.EncryptionType.encryptionType[0])
3348 )
3349 {
3350 /* Saving key direction for default key index to TX default */
3351 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3352 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3353 }
3354 }
3355
3356 return status;
3357}
3358
Jeff Johnsoncab8ddc2013-01-18 17:05:29 -08003359#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07003360/**
3361 * FUNCTION: wlan_hdd_cfg80211_set_channel
3362 * This function is used to set the channel number
3363 */
3364int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3365 struct ieee80211_channel *chan,
3366 enum nl80211_channel_type channel_type
3367 )
3368{
3369 v_U32_t num_ch = 0;
3370 u32 channel = 0;
Madan Mohan Koyyalamudife3f0572012-11-30 17:21:40 -08003371 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003372 int freq = chan->center_freq; /* freq is in MHZ */
3373
3374 ENTER();
Madan Mohan Koyyalamudife3f0572012-11-30 17:21:40 -08003375
3376 if( NULL == dev )
3377 {
3378 hddLog(VOS_TRACE_LEVEL_ERROR,
3379 "%s: Called with dev = NULL.\n", __func__);
3380 return -ENODEV;
3381 }
3382 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003383
3384 hddLog(VOS_TRACE_LEVEL_INFO,
3385 "%s: device_mode = %d freq = %d \n",__func__,
3386 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003387 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3388 {
3389 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3390 return -EAGAIN;
3391 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003392
3393 /*
3394 * Do freq to chan conversion
3395 * TODO: for 11a
3396 */
3397
3398 channel = ieee80211_frequency_to_channel(freq);
3399
3400 /* Check freq range */
3401 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3402 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3403 {
3404 hddLog(VOS_TRACE_LEVEL_ERROR,
3405 "%s: Channel [%d] is outside valid range from %d to %d\n",
3406 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3407 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3408 return -EINVAL;
3409 }
3410
3411 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3412
3413 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3414#ifdef WLAN_FEATURE_P2P
3415 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3416#endif
3417 )
3418 {
3419 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3420 {
3421 hddLog(VOS_TRACE_LEVEL_ERROR,
3422 "%s: Invalid Channel [%d] \n", __func__, channel);
3423 return -EINVAL;
3424 }
3425 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3426 "%s: set channel to [%d] for device mode =%d",
3427 __func__, channel,pAdapter->device_mode);
3428 }
3429 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3430#ifdef WLAN_FEATURE_P2P
3431 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3432#endif
3433 )
3434 {
3435 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3436 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3437 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3438
3439 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3440 {
3441 /* Link is up then return cant set channel*/
3442 hddLog( VOS_TRACE_LEVEL_ERROR,
3443 "%s: IBSS Associated, can't set the channel\n", __func__);
3444 return -EINVAL;
3445 }
3446
3447 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3448 pHddStaCtx->conn_info.operationChannel = channel;
3449 pRoamProfile->ChannelInfo.ChannelList =
3450 &pHddStaCtx->conn_info.operationChannel;
3451 }
3452 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3453#ifdef WLAN_FEATURE_P2P
3454 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3455#endif
3456 )
3457 {
3458 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3459
3460 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3461 {
3462 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3463
3464 /* If auto channel selection is configured as enable/ 1 then ignore
3465 channel set by supplicant
3466 */
3467 if ( cfg_param->apAutoChannelSelection )
3468 {
3469 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3470
3471 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3472 "%s: set channel to auto channel (0) for device mode =%d",
3473 __func__, pAdapter->device_mode);
3474 }
3475 }
3476 }
3477 else
3478 {
3479 hddLog(VOS_TRACE_LEVEL_FATAL,
3480 "%s: Invalid device mode failed to set valid channel", __func__);
3481 return -EINVAL;
3482 }
3483 EXIT();
3484 return 0;
3485}
Jeff Johnsoncab8ddc2013-01-18 17:05:29 -08003486#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003487
3488
3489
3490/*
3491 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3492 * This function is used to inform the BSS details to nl80211 interface.
3493 */
3494static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3495 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3496{
3497 struct net_device *dev = pAdapter->dev;
3498 struct wireless_dev *wdev = dev->ieee80211_ptr;
3499 struct wiphy *wiphy = wdev->wiphy;
3500 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3501 int chan_no;
3502 int ie_length;
3503 const char *ie;
3504 unsigned int freq;
3505 struct ieee80211_channel *chan;
3506 int rssi = 0;
3507 struct cfg80211_bss *bss = NULL;
3508
3509 ENTER();
3510
3511 if( NULL == pBssDesc )
3512 {
3513 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3514 return bss;
3515 }
3516
3517 chan_no = pBssDesc->channelId;
3518 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3519 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3520
3521 if( NULL == ie )
3522 {
3523 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3524 return bss;
3525 }
3526
3527#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3528 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3529 {
3530 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3531 }
3532 else
3533 {
3534 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3535 }
3536#else
3537 freq = ieee80211_channel_to_frequency(chan_no);
3538#endif
3539
3540 chan = __ieee80211_get_channel(wiphy, freq);
3541
3542 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3543 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3544 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3545 if (bss == NULL)
3546 {
3547 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3548
3549 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3550 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3551 pBssDesc->capabilityInfo,
3552 pBssDesc->beaconInterval, ie, ie_length,
3553 rssi, GFP_KERNEL ));
3554}
3555 else
3556 {
3557 return bss;
3558 }
3559}
3560
3561
3562
3563/*
3564 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3565 * This function is used to inform the BSS details to nl80211 interface.
3566 */
3567struct cfg80211_bss*
3568wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3569 tSirBssDescription *bss_desc
3570 )
3571{
3572 /*
3573 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3574 already exists in bss data base of cfg80211 for that particular BSS ID.
3575 Using cfg80211_inform_bss_frame to update the bss entry instead of
3576 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3577 now there is no possibility to get the mgmt(probe response) frame from PE,
3578 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3579 cfg80211_inform_bss_frame.
3580 */
3581 struct net_device *dev = pAdapter->dev;
3582 struct wireless_dev *wdev = dev->ieee80211_ptr;
3583 struct wiphy *wiphy = wdev->wiphy;
3584 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003585#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3586 qcom_ie_age *qie_age = NULL;
3587 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3588#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003589 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003590#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003591 const char *ie =
3592 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3593 unsigned int freq;
3594 struct ieee80211_channel *chan;
3595 struct ieee80211_mgmt *mgmt =
3596 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3597 struct cfg80211_bss *bss_status = NULL;
3598 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3599 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003600#ifdef WLAN_OPEN_SOURCE
3601 struct timespec ts;
3602#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003603
3604 ENTER();
3605
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003606 if (!mgmt)
3607 return NULL;
3608
Jeff Johnson295189b2012-06-20 16:38:30 -07003609 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003610
3611#ifdef WLAN_OPEN_SOURCE
3612 /* Android does not want the timestamp from the frame.
3613 Instead it wants a monotonic increasing value */
3614 get_monotonic_boottime(&ts);
3615 mgmt->u.probe_resp.timestamp =
3616 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3617#else
3618 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003619 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3620 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003621
3622#endif
3623
Jeff Johnson295189b2012-06-20 16:38:30 -07003624 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3625 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003626
3627#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3628 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3629 /* Assuming this is the last IE, copy at the end */
3630 ie_length -=sizeof(qcom_ie_age);
3631 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3632 qie_age->element_id = QCOM_VENDOR_IE_ID;
3633 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3634 qie_age->oui_1 = QCOM_OUI1;
3635 qie_age->oui_2 = QCOM_OUI2;
3636 qie_age->oui_3 = QCOM_OUI3;
3637 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3638 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3639#endif
3640
Jeff Johnson295189b2012-06-20 16:38:30 -07003641 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3642
3643 mgmt->frame_control |=
3644 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3645
3646#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3647 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3648 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3649 {
3650 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3651 }
3652 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3653 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3654
3655 {
3656 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3657 }
3658 else
3659 {
3660 kfree(mgmt);
3661 return NULL;
3662 }
3663#else
3664 freq = ieee80211_channel_to_frequency(chan_no);
3665#endif
3666 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy47f0ff22013-01-24 18:33:30 -08003667 /*when the band is changed on the fly using the GUI, three things are done
3668 * 1. scan abort 2.flush scan results from cache 3.update the band with the new band user specified(refer to the hdd_setBand_helper function)
3669 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3670 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3671 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3672 * and discards the channels correponding to previous band and calls back with zero bss results.
3673 * but if the time between band update and scan done callback is very small then band change will not reflect in SME and SME reports to HDD
3674 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3675 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3676 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3677 * So drop the bss and continue to next bss.
3678 */
3679 if(chan == NULL)
3680 {
3681 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3682 return NULL;
3683 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003684 /*To keep the rssi icon of the connected AP in the scan window
3685 *and the rssi icon of the wireless networks in sync
3686 * */
3687 if (( eConnectionState_Associated ==
3688 pAdapter->sessionCtx.station.conn_info.connState ) &&
3689 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3690 pAdapter->sessionCtx.station.conn_info.bssId,
3691 WNI_CFG_BSSID_LEN)))
3692 {
3693 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3694 rssi = (pAdapter->rssi * 100);
3695 }
3696 else
3697 {
3698 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3699 }
3700
3701 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3702 frame_len, rssi, GFP_KERNEL);
3703 kfree(mgmt);
3704 return bss_status;
3705}
3706
3707/*
3708 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3709 * This function is used to update the BSS data base of CFG8011
3710 */
3711struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3712 tCsrRoamInfo *pRoamInfo
3713 )
3714{
3715 tCsrRoamConnectedProfile roamProfile;
3716 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3717 struct cfg80211_bss *bss = NULL;
3718
3719 ENTER();
3720
3721 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3722 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3723
3724 if (NULL != roamProfile.pBssDesc)
3725 {
3726 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3727 &roamProfile);
3728
3729 if (NULL == bss)
3730 {
3731 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3732 __func__);
3733 }
3734
3735 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3736 }
3737 else
3738 {
3739 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3740 __func__);
3741 }
3742 return bss;
3743}
3744
3745/*
3746 * FUNCTION: wlan_hdd_cfg80211_update_bss
3747 */
3748static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3749 hdd_adapter_t *pAdapter
3750 )
3751{
3752 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3753 tCsrScanResultInfo *pScanResult;
3754 eHalStatus status = 0;
3755 tScanResultHandle pResult;
3756 struct cfg80211_bss *bss_status = NULL;
3757
3758 ENTER();
3759
3760 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3761 {
3762 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3763 return -EAGAIN;
3764 }
3765
3766 /*
3767 * start getting scan results and populate cgf80211 BSS database
3768 */
3769 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3770
3771 /* no scan results */
3772 if (NULL == pResult)
3773 {
3774 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3775 return status;
3776 }
3777
3778 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3779
3780 while (pScanResult)
3781 {
3782 /*
3783 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3784 * entry already exists in bss data base of cfg80211 for that
3785 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3786 * bss entry instead of cfg80211_inform_bss, But this call expects
3787 * mgmt packet as input. As of now there is no possibility to get
3788 * the mgmt(probe response) frame from PE, converting bss_desc to
3789 * ieee80211_mgmt(probe response) and passing to c
3790 * fg80211_inform_bss_frame.
3791 * */
3792
3793 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3794 &pScanResult->BssDescriptor);
3795
3796
3797 if (NULL == bss_status)
3798 {
3799 hddLog(VOS_TRACE_LEVEL_INFO,
3800 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3801 }
3802 else
3803 {
3804 cfg80211_put_bss(bss_status);
3805 }
3806
3807 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3808 }
3809
3810 sme_ScanResultPurge(hHal, pResult);
3811
3812 return 0;
3813}
3814
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003815void
3816hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3817{
3818 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003819 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3820 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3821 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003822} /****** end hddPrintMacAddr() ******/
3823
3824void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003825hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003826{
3827 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003828 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3829 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3830 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3831 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003832} /****** end hddPrintPmkId() ******/
3833
3834//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3835//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3836
3837//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3838//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3839
3840#define dump_bssid(bssid) \
3841 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003842 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3843 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3844 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003845 }
3846
3847#define dump_pmkid(pMac, pmkid) \
3848 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003849 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3850 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3851 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003852 }
3853
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003854#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003855/*
3856 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3857 * This function is used to notify the supplicant of a new PMKSA candidate.
3858 */
3859int wlan_hdd_cfg80211_pmksa_candidate_notify(
3860 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3861 int index, bool preauth )
3862{
Jeff Johnsone7245742012-09-05 17:12:55 -07003863#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003864 struct net_device *dev = pAdapter->dev;
3865
3866 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003867 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003868
3869 if( NULL == pRoamInfo )
3870 {
3871 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3872 return -EINVAL;
3873 }
3874
3875 dump_bssid(pRoamInfo->bssid);
3876 cfg80211_pmksa_candidate_notify(dev, index,
3877 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003878#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003879 return 0;
3880}
3881#endif //FEATURE_WLAN_LFR
3882
Jeff Johnson295189b2012-06-20 16:38:30 -07003883/*
3884 * FUNCTION: hdd_cfg80211_scan_done_callback
3885 * scanning callback function, called after finishing scan
3886 *
3887 */
3888static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3889 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3890{
3891 struct net_device *dev = (struct net_device *) pContext;
3892 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3893 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003894 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3895 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003896 struct cfg80211_scan_request *req = NULL;
3897 int ret = 0;
3898
3899 ENTER();
3900
3901 hddLog(VOS_TRACE_LEVEL_INFO,
3902 "%s called with halHandle = %p, pContext = %p,"
3903 "scanID = %d, returned status = %d\n",
3904 __func__, halHandle, pContext, (int) scanId, (int) status);
3905
3906 //Block on scan req completion variable. Can't wait forever though.
3907 ret = wait_for_completion_interruptible_timeout(
3908 &pScanInfo->scan_req_completion_event,
3909 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3910 if (!ret)
3911 {
3912 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003913 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003914 }
3915
3916 if(pScanInfo->mScanPending != VOS_TRUE)
3917 {
3918 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003919 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003920 }
3921
3922 /* Check the scanId */
3923 if (pScanInfo->scanId != scanId)
3924 {
3925 hddLog(VOS_TRACE_LEVEL_INFO,
3926 "%s called with mismatched scanId pScanInfo->scanId = %d "
3927 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3928 (int) scanId);
3929 }
3930
Jeff Johnson295189b2012-06-20 16:38:30 -07003931 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3932 pAdapter);
3933
3934 if (0 > ret)
3935 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3936
3937
3938 /* If any client wait scan result through WEXT
3939 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003940 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003941 {
3942 /* The other scan request waiting for current scan finish
3943 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003944 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003945 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003946 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003947 }
3948 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003949 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003950 {
3951 struct net_device *dev = pAdapter->dev;
3952 union iwreq_data wrqu;
3953 int we_event;
3954 char *msg;
3955
3956 memset(&wrqu, '\0', sizeof(wrqu));
3957 we_event = SIOCGIWSCAN;
3958 msg = NULL;
3959 wireless_send_event(dev, we_event, &wrqu, msg);
3960 }
3961 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003962 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003963
3964 /* Get the Scan Req */
3965 req = pAdapter->request;
3966
3967 if (!req)
3968 {
3969 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003970 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003971 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003972 }
3973
3974 /*
3975 * setting up 0, just in case.
3976 */
3977 req->n_ssids = 0;
3978 req->n_channels = 0;
3979 req->ie = 0;
3980
Jeff Johnson295189b2012-06-20 16:38:30 -07003981 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003982 /* Scan is no longer pending */
3983 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003984
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003985 /*
3986 * cfg80211_scan_done informing NL80211 about completion
3987 * of scanning
3988 */
3989 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003990 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003991
Jeff Johnsone7245742012-09-05 17:12:55 -07003992allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003993 /* release the wake lock at the end of the scan*/
3994 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003995
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003996 /* Acquire wakelock to handle the case where APP's tries to suspend
3997 * immediatly after the driver gets connect request(i.e after scan)
3998 * from supplicant, this result in app's is suspending and not able
3999 * to process the connect request to AP */
4000 hdd_allow_suspend_timeout(100);
4001
Jeff Johnson295189b2012-06-20 16:38:30 -07004002 EXIT();
4003 return 0;
4004}
4005
4006/*
Madan Mohan Koyyalamudi023964b2013-01-11 15:29:03 -08004007 * FUNCTION: hdd_isScanAllowed
4008 * Go through each adapter and check if scan allowed
4009 *
4010 */
4011v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
4012{
4013 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4014 hdd_station_ctx_t *pHddStaCtx = NULL;
4015 hdd_adapter_t *pAdapter = NULL;
4016 VOS_STATUS status = 0;
4017 v_U8_t staId = 0;
4018 v_U8_t *staMac = NULL;
4019
4020 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4021
4022 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4023 {
4024 pAdapter = pAdapterNode->pAdapter;
4025
4026 if( pAdapter )
4027 {
4028 hddLog(VOS_TRACE_LEVEL_INFO,
4029 "%s: Adapter with device mode %d exists",
4030 __func__, pAdapter->device_mode);
4031 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4032 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4033 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4034 {
4035 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4036 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4037 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4038 {
4039 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4040 hddLog(VOS_TRACE_LEVEL_ERROR,
4041 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4042 "middle of WPS/EAPOL exchange.", __func__,
4043 staMac[0], staMac[1], staMac[2],
4044 staMac[3], staMac[4], staMac[5]);
4045 return VOS_FALSE;
4046 }
4047 }
4048 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4049 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4050 {
4051 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4052 {
4053 if ((pAdapter->aStaInfo[staId].isUsed) &&
4054 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4055 {
4056 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4057
4058 hddLog(VOS_TRACE_LEVEL_ERROR,
4059 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4060 "middle of WPS/EAPOL exchange.", __func__,
4061 staMac[0], staMac[1], staMac[2],
4062 staMac[3], staMac[4], staMac[5]);
4063 return VOS_FALSE;
4064 }
4065 }
4066 }
4067 }
4068 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4069 pAdapterNode = pNext;
4070 }
4071 hddLog(VOS_TRACE_LEVEL_INFO,
4072 "%s: Scan allowed", __func__);
4073 return VOS_TRUE;
4074}
4075
4076/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004077 * FUNCTION: wlan_hdd_cfg80211_scan
4078 * this scan respond to scan trigger and update cfg80211 scan database
4079 * later, scan dump command can be used to recieve scan results
4080 */
Jeff Johnsoncab8ddc2013-01-18 17:05:29 -08004081int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4082#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4083 struct net_device *dev,
4084#endif
4085 struct cfg80211_scan_request *request)
4086{
4087#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4088 struct net_device *dev = request->wdev->netdev;
4089#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004090 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4091 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4092 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4093 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4094 tCsrScanRequest scanRequest;
4095 tANI_U8 *channelList = NULL, i;
4096 v_U32_t scanId = 0;
4097 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004098 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004099#ifdef WLAN_FEATURE_P2P
4100 v_U8_t* pP2pIe = NULL;
4101#endif
4102
4103 ENTER();
4104
4105 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4106 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004107
4108 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4109 (eConnectionState_Connecting ==
4110 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4111 {
4112 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi6bd84fa2012-12-03 16:34:04 -08004113 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4114 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004115 return -EBUSY;
4116 }
4117
Jeff Johnson295189b2012-06-20 16:38:30 -07004118#ifdef WLAN_BTAMP_FEATURE
4119 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004120 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004121 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004122 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004123 "%s: No scanning when AMP is on", __func__);
4124 return -EOPNOTSUPP;
4125 }
4126#endif
4127 //Scan on any other interface is not supported.
4128 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4129 {
4130 hddLog(VOS_TRACE_LEVEL_ERROR,
4131 "%s: Not scanning on device_mode = %d",
4132 __func__, pAdapter->device_mode);
4133 return -EOPNOTSUPP;
4134 }
4135
4136 if (TRUE == pScanInfo->mScanPending)
4137 {
4138 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4139 return -EBUSY;
4140 }
4141
4142 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4143 {
4144 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4145 "%s:LOGP in Progress. Ignore!!!", __func__);
4146 return -EAGAIN;
4147 }
4148
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004149 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4150 {
4151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4152 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4153 return -EAGAIN;
4154 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004155 //Don't Allow Scan and return busy if Remain On
4156 //Channel and action frame is pending
4157 //Otherwise Cancel Remain On Channel and allow Scan
4158 //If no action frame pending
4159 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4160 {
4161 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4162 return -EBUSY;
4163 }
4164
Jeff Johnson295189b2012-06-20 16:38:30 -07004165 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4166 {
4167 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson3d710ea2012-12-10 14:31:52 -08004168 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004169 return -EAGAIN;
4170 }
4171 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4172 {
4173 hddLog(VOS_TRACE_LEVEL_WARN,
4174 "%s: MAX TM Level Scan not allowed", __func__);
4175 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4176 return -EBUSY;
4177 }
4178 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4179
Madan Mohan Koyyalamudi023964b2013-01-11 15:29:03 -08004180 /* Check if scan is allowed at this point of time.
4181 */
4182 if (!hdd_isScanAllowed(pHddCtx))
4183 {
4184 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4185 return -EBUSY;
4186 }
4187
Jeff Johnson295189b2012-06-20 16:38:30 -07004188 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4189
4190 if (NULL != request)
4191 {
4192 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4193 (int)request->n_ssids);
4194
4195 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4196 * Becasue of this, driver is assuming that this is not wildcard scan and so
4197 * is not aging out the scan results.
4198 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004199 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004200 {
4201 request->n_ssids = 0;
4202 }
4203
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004204 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004205 {
4206 tCsrSSIDInfo *SsidInfo;
4207 int j;
4208 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4209 /* Allocate num_ssid tCsrSSIDInfo structure */
4210 SsidInfo = scanRequest.SSIDs.SSIDList =
4211 ( tCsrSSIDInfo *)vos_mem_malloc(
4212 request->n_ssids*sizeof(tCsrSSIDInfo));
4213
4214 if(NULL == scanRequest.SSIDs.SSIDList)
4215 {
4216 hddLog(VOS_TRACE_LEVEL_ERROR,
4217 "memory alloc failed SSIDInfo buffer");
4218 return -ENOMEM;
4219 }
4220
4221 /* copy all the ssid's and their length */
4222 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4223 {
4224 /* get the ssid length */
4225 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4226 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4227 SsidInfo->SSID.length);
4228 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4229 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4230 j, SsidInfo->SSID.ssId);
4231 }
4232 /* set the scan type to active */
4233 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4234 }
4235 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4236 {
4237 /* set the scan type to active */
4238 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4239 }
4240 else
4241 {
4242 /*Set the scan type to default type, in this case it is ACTIVE*/
4243 scanRequest.scanType = pScanInfo->scan_mode;
4244 }
4245 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4246 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4247 }
4248 else
4249 {
4250 /* set the scan type to active */
4251 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4252 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4253
4254 /* set min and max channel time to zero */
4255 scanRequest.minChnTime = 0;
4256 scanRequest.maxChnTime = 0;
4257 }
4258
4259 /* set BSSType to default type */
4260 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4261
4262 /*TODO: scan the requested channels only*/
4263
4264 /*Right now scanning all the channels */
4265 if( request )
4266 {
4267 if( request->n_channels )
4268 {
4269 channelList = vos_mem_malloc( request->n_channels );
4270 if( NULL == channelList )
4271 {
4272 status = -ENOMEM;
4273 goto free_mem;
4274 }
4275
4276 for( i = 0 ; i < request->n_channels ; i++ )
4277 channelList[i] = request->channels[i]->hw_value;
4278 }
4279
4280 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4281 scanRequest.ChannelInfo.ChannelList = channelList;
4282
4283 /* set requestType to full scan */
4284 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004285
4286 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4287 * search (Flush on both full scan and social scan but not on single
4288 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4289 */
4290
4291 /* Supplicant does single channel scan after 8-way handshake
4292 * and in that case driver shoudnt flush scan results. If
4293 * driver flushes the scan results here and unfortunately if
4294 * the AP doesnt respond to our probe req then association
4295 * fails which is not desired
4296 */
4297
4298 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4299 {
4300 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4301 pAdapter->sessionId );
4302 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004303
4304 if( request->ie_len )
4305 {
4306 /* save this for future association (join requires this) */
4307 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4308 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4309 pScanInfo->scanAddIE.length = request->ie_len;
4310
4311 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004312 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4313 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004314 )
4315 {
4316 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4317 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4318 }
4319
4320 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4321 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4322
4323#ifdef WLAN_FEATURE_P2P
4324 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4325 request->ie_len);
4326 if (pP2pIe != NULL)
4327 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004328#ifdef WLAN_FEATURE_P2P_DEBUG
4329 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4330 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4331 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4332 {
4333 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4334 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4335 "Go nego completed to Connection is started");
4336 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4337 "for 8way Handshake");
4338 }
4339 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4340 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4341 {
4342 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4343 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4344 "Disconnected state to Connection is started");
4345 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4346 "for 4way Handshake");
4347 }
4348#endif
4349
Jeff Johnsone7245742012-09-05 17:12:55 -07004350 /* no_cck will be set during p2p find to disable 11b rates */
4351 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004352 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004353 hddLog(VOS_TRACE_LEVEL_INFO,
4354 "%s: This is a P2P Search", __func__);
4355 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004356
Jeff Johnsone7245742012-09-05 17:12:55 -07004357 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4358 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004359 /* set requestType to P2P Discovery */
4360 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004361 }
4362
4363 /*
4364 Skip Dfs Channel in case of P2P Search
4365 if it is set in ini file
4366 */
4367 if(cfg_param->skipDfsChnlInP2pSearch)
4368 {
4369 scanRequest.skipDfsChnlInP2pSearch = 1;
4370 }
4371 else
4372 {
4373 scanRequest.skipDfsChnlInP2pSearch = 0;
4374 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004375
Jeff Johnson295189b2012-06-20 16:38:30 -07004376 }
4377 }
4378#endif
4379 }
4380 }
4381
4382 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4383
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004384 /* acquire the wakelock to avoid the apps suspend during the scan. To
4385 * address the following issues.
4386 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4387 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4388 * for long time, this result in apps running at full power for long time.
4389 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4390 * be stuck in full power because of resume BMPS
4391 */
4392 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004393
4394 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004395 pAdapter->sessionId, &scanRequest, &scanId,
4396 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004397
Jeff Johnson295189b2012-06-20 16:38:30 -07004398 if (eHAL_STATUS_SUCCESS != status)
4399 {
4400 hddLog(VOS_TRACE_LEVEL_ERROR,
4401 "%s: sme_ScanRequest returned error %d", __func__, status);
4402 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004403 if(eHAL_STATUS_RESOURCES == status)
4404 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004405 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 -07004406 status = -EBUSY;
4407 } else {
4408 status = -EIO;
4409 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004410 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004411 goto free_mem;
4412 }
4413
4414 pScanInfo->mScanPending = TRUE;
4415 pAdapter->request = request;
4416 pScanInfo->scanId = scanId;
4417
4418 complete(&pScanInfo->scan_req_completion_event);
4419
4420free_mem:
4421 if( scanRequest.SSIDs.SSIDList )
4422 {
4423 vos_mem_free(scanRequest.SSIDs.SSIDList);
4424 }
4425
4426 if( channelList )
4427 vos_mem_free( channelList );
4428
4429 EXIT();
4430
4431 return status;
4432}
4433
4434/*
4435 * FUNCTION: wlan_hdd_cfg80211_connect_start
4436 * This function is used to start the association process
4437 */
4438int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004439 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004440{
4441 int status = 0;
4442 hdd_wext_state_t *pWextState;
4443 v_U32_t roamId;
4444 tCsrRoamProfile *pRoamProfile;
4445 eMib_dot11DesiredBssType connectedBssType;
4446 eCsrAuthType RSNAuthType;
4447
4448 ENTER();
4449
4450 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4451
4452 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4453 {
4454 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4455 return -EINVAL;
4456 }
4457
4458 pRoamProfile = &pWextState->roamProfile;
4459
4460 if (pRoamProfile)
4461 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004462 int ret = 0;
4463 hdd_station_ctx_t *pHddStaCtx;
4464 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4465 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4466
4467 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4468 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4469 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004470 {
4471 /* Issue disconnect to CSR */
4472 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4473 if( eHAL_STATUS_SUCCESS ==
4474 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4475 pAdapter->sessionId,
4476 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4477 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004478 ret = wait_for_completion_interruptible_timeout(
4479 &pAdapter->disconnect_comp_var,
4480 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4481 if (0 == ret)
4482 {
4483 VOS_ASSERT(0);
4484 }
4485 }
4486 }
4487 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4488 {
4489 ret = wait_for_completion_interruptible_timeout(
4490 &pAdapter->disconnect_comp_var,
4491 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4492 if (0 == ret)
4493 {
4494 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004495 }
4496 }
4497
4498 if (HDD_WMM_USER_MODE_NO_QOS ==
4499 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4500 {
4501 /*QoS not enabled in cfg file*/
4502 pRoamProfile->uapsd_mask = 0;
4503 }
4504 else
4505 {
4506 /*QoS enabled, update uapsd mask from cfg file*/
4507 pRoamProfile->uapsd_mask =
4508 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4509 }
4510
4511 pRoamProfile->SSIDs.numOfSSIDs = 1;
4512 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4513 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4514 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4515 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4516 ssid, ssid_len);
4517
4518 if (bssid)
4519 {
4520 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4521 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4522 WNI_CFG_BSSID_LEN);
4523 /* Save BSSID in seperate variable as well, as RoamProfile
4524 BSSID is getting zeroed out in the association process. And in
4525 case of join failure we should send valid BSSID to supplicant
4526 */
4527 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4528 WNI_CFG_BSSID_LEN);
4529 }
4530
4531 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4532 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4533 {
4534 /*set gen ie*/
4535 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4536 /*set auth*/
4537 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4538 }
4539 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4540 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4541 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4542 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4543 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4544 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4545 )
4546 {
4547 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4548 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4549 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4550 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4551 eCSR_AUTH_TYPE_AUTOSWITCH;
4552 pWextState->roamProfile.AuthType.authType[0] =
4553 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4554 }
4555#ifdef FEATURE_WLAN_WAPI
4556 if (pAdapter->wapi_info.nWapiMode)
4557 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004558 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004559 switch (pAdapter->wapi_info.wapiAuthMode)
4560 {
4561 case WAPI_AUTH_MODE_PSK:
4562 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004563 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004564 pAdapter->wapi_info.wapiAuthMode);
4565 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4566 break;
4567 }
4568 case WAPI_AUTH_MODE_CERT:
4569 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004570 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004571 pAdapter->wapi_info.wapiAuthMode);
4572 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4573 break;
4574 }
4575 } // End of switch
4576 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4577 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4578 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004579 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 pRoamProfile->AuthType.numEntries = 1;
4581 pRoamProfile->EncryptionType.numEntries = 1;
4582 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4583 pRoamProfile->mcEncryptionType.numEntries = 1;
4584 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4585 }
4586 }
4587#endif /* FEATURE_WLAN_WAPI */
4588 pRoamProfile->csrPersona = pAdapter->device_mode;
4589
Jeff Johnson32d95a32012-09-10 13:15:23 -07004590 if( operatingChannel )
4591 {
4592 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4593 pRoamProfile->ChannelInfo.numOfChannels = 1;
4594 }
4595
Madan Mohan Koyyalamudi6bd84fa2012-12-03 16:34:04 -08004596 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4597 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4598 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4599 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudif357acc2012-12-04 17:03:44 -08004600 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4601 */
4602 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4603 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4604 eConnectionState_Connecting);
Madan Mohan Koyyalamudi6bd84fa2012-12-03 16:34:04 -08004605
Jeff Johnson295189b2012-06-20 16:38:30 -07004606 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4607 pAdapter->sessionId, pRoamProfile, &roamId);
4608
Madan Mohan Koyyalamudi6bd84fa2012-12-03 16:34:04 -08004609 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304610 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4611
4612 {
Madan Mohan Koyyalamudi6bd84fa2012-12-03 16:34:04 -08004613 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4614 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4615 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304616 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi6bd84fa2012-12-03 16:34:04 -08004617 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304618 }
Madan Mohan Koyyalamudif357acc2012-12-04 17:03:44 -08004619
4620 pRoamProfile->ChannelInfo.ChannelList = NULL;
4621 pRoamProfile->ChannelInfo.numOfChannels = 0;
4622
Jeff Johnson295189b2012-06-20 16:38:30 -07004623 }
4624 else
4625 {
4626 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4627 return -EINVAL;
4628 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004629 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 return status;
4631}
4632
4633/*
4634 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4635 * This function is used to set the authentication type (OPEN/SHARED).
4636 *
4637 */
4638static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4639 enum nl80211_auth_type auth_type)
4640{
4641 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4642 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4643
4644 ENTER();
4645
4646 /*set authentication type*/
4647 switch (auth_type)
4648 {
4649 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4650 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004651#ifdef WLAN_FEATURE_VOWIFI_11R
4652 case NL80211_AUTHTYPE_FT:
4653#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004654 hddLog(VOS_TRACE_LEVEL_INFO,
4655 "%s: set authentication type to OPEN", __func__);
4656 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4657 break;
4658
4659 case NL80211_AUTHTYPE_SHARED_KEY:
4660 hddLog(VOS_TRACE_LEVEL_INFO,
4661 "%s: set authentication type to SHARED", __func__);
4662 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4663 break;
4664#ifdef FEATURE_WLAN_CCX
4665 case NL80211_AUTHTYPE_NETWORK_EAP:
4666 hddLog(VOS_TRACE_LEVEL_INFO,
4667 "%s: set authentication type to CCKM WPA", __func__);
4668 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4669 break;
4670#endif
4671
4672
4673 default:
4674 hddLog(VOS_TRACE_LEVEL_ERROR,
4675 "%s: Unsupported authentication type %d", __func__,
4676 auth_type);
4677 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4678 return -EINVAL;
4679 }
4680
4681 pWextState->roamProfile.AuthType.authType[0] =
4682 pHddStaCtx->conn_info.authType;
4683 return 0;
4684}
4685
4686/*
4687 * FUNCTION: wlan_hdd_set_akm_suite
4688 * This function is used to set the key mgmt type(PSK/8021x).
4689 *
4690 */
4691static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4692 u32 key_mgmt
4693 )
4694{
4695 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4696 ENTER();
4697
4698 /*set key mgmt type*/
4699 switch(key_mgmt)
4700 {
4701 case WLAN_AKM_SUITE_PSK:
4702 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4703 __func__);
4704 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4705 break;
4706
4707 case WLAN_AKM_SUITE_8021X:
4708 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4709 __func__);
4710 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4711 break;
4712#ifdef FEATURE_WLAN_CCX
4713#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4714#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4715 case WLAN_AKM_SUITE_CCKM:
4716 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4717 __func__);
4718 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4719 break;
4720#endif
4721
4722 default:
4723 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4724 __func__, key_mgmt);
4725 return -EINVAL;
4726
4727 }
4728 return 0;
4729}
4730
4731/*
4732 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4733 * This function is used to set the encryption type
4734 * (NONE/WEP40/WEP104/TKIP/CCMP).
4735 */
4736static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4737 u32 cipher,
4738 bool ucast
4739 )
4740{
4741 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4742 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4743 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4744
4745 ENTER();
4746
4747 if (!cipher)
4748 {
4749 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4750 __func__, cipher);
4751 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4752 }
4753 else
4754 {
4755
4756 /*set encryption method*/
4757 switch (cipher)
4758 {
4759 case IW_AUTH_CIPHER_NONE:
4760 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4761 break;
4762
4763 case WLAN_CIPHER_SUITE_WEP40:
4764 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4765 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4766 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4767 else
4768 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4769 break;
4770
4771 case WLAN_CIPHER_SUITE_WEP104:
4772 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4773 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4774 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4775 else
4776 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4777 break;
4778
4779 case WLAN_CIPHER_SUITE_TKIP:
4780 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4781 break;
4782
4783 case WLAN_CIPHER_SUITE_CCMP:
4784 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4785 break;
4786#ifdef FEATURE_WLAN_WAPI
4787 case WLAN_CIPHER_SUITE_SMS4:
4788 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4789 break;
4790#endif
4791
4792#ifdef FEATURE_WLAN_CCX
4793 case WLAN_CIPHER_SUITE_KRK:
4794 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4795 break;
4796#endif
4797 default:
4798 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4799 __func__, cipher);
4800 return -EOPNOTSUPP;
4801 }
4802 }
4803
4804 if (ucast)
4805 {
4806 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4807 __func__, encryptionType);
4808 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4809 pWextState->roamProfile.EncryptionType.numEntries = 1;
4810 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4811 encryptionType;
4812 }
4813 else
4814 {
4815 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4816 __func__, encryptionType);
4817 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4818 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4819 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4820 }
4821
4822 return 0;
4823}
4824
4825
4826/*
4827 * FUNCTION: wlan_hdd_cfg80211_set_ie
4828 * This function is used to parse WPA/RSN IE's.
4829 */
4830int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4831 u8 *ie,
4832 size_t ie_len
4833 )
4834{
4835 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4836 u8 *genie = ie;
4837 v_U16_t remLen = ie_len;
4838#ifdef FEATURE_WLAN_WAPI
4839 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4840 u16 *tmp;
4841 v_U16_t akmsuiteCount;
4842 int *akmlist;
4843#endif
4844 ENTER();
4845
4846 /* clear previous assocAddIE */
4847 pWextState->assocAddIE.length = 0;
4848 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4849
4850 while (remLen >= 2)
4851 {
4852 v_U16_t eLen = 0;
4853 v_U8_t elementId;
4854 elementId = *genie++;
4855 eLen = *genie++;
4856 remLen -= 2;
4857
4858 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4859 __func__, elementId, eLen);
4860
4861 switch ( elementId )
4862 {
4863 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004864 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 -07004865 {
4866 hddLog(VOS_TRACE_LEVEL_ERROR,
4867 "%s: Invalid WPA IE", __func__);
4868 return -EINVAL;
4869 }
4870 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4871 {
4872 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4873 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4874 __func__, eLen + 2);
4875
4876 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4877 {
Jeff Johnson1920a722012-12-10 14:28:09 -08004878 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4879 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004880 VOS_ASSERT(0);
4881 return -ENOMEM;
4882 }
4883 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4884 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4885 pWextState->assocAddIE.length += eLen + 2;
4886
4887 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4888 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4889 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4890 }
4891 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4892 {
4893 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4894 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4895 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4896 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4897 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4898 }
4899#ifdef WLAN_FEATURE_P2P
4900 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4901 P2P_OUI_TYPE_SIZE))
4902 /*Consider P2P IE, only for P2P Client */
4903 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4904 {
4905 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4906 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4907 __func__, eLen + 2);
4908
4909 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4910 {
Jeff Johnson1920a722012-12-10 14:28:09 -08004911 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4912 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004913 VOS_ASSERT(0);
4914 return -ENOMEM;
4915 }
4916 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4917 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4918 pWextState->assocAddIE.length += eLen + 2;
4919
4920 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4921 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4922 }
4923#endif
4924#ifdef WLAN_FEATURE_WFD
4925 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4926 WFD_OUI_TYPE_SIZE))
4927 /*Consider WFD IE, only for P2P Client */
4928 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4929 {
4930 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4931 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4932 __func__, eLen + 2);
4933
4934 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4935 {
Jeff Johnson1920a722012-12-10 14:28:09 -08004936 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4937 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004938 VOS_ASSERT(0);
4939 return -ENOMEM;
4940 }
4941 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4942 // WPS IE + P2P IE + WFD IE
4943 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4944 pWextState->assocAddIE.length += eLen + 2;
4945
4946 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4947 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4948 }
4949#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004950 /* Appending HS 2.0 Indication Element in Assiciation Request */
4951 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004952 HS20_OUI_TYPE_SIZE)) )
4953 {
4954 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4955 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4956 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004957
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004958 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4959 {
Jeff Johnson1920a722012-12-10 14:28:09 -08004960 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4961 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004962 VOS_ASSERT(0);
4963 return -ENOMEM;
4964 }
4965 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4966 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004967
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004968 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4969 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4970 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004971
Jeff Johnson295189b2012-06-20 16:38:30 -07004972 break;
4973 case DOT11F_EID_RSN:
4974 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4975 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4976 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4977 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4978 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4979 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004980 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4981 case DOT11F_EID_EXTCAP:
4982 {
4983 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4984 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4985 __func__, eLen + 2);
4986
4987 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4988 {
Jeff Johnson1920a722012-12-10 14:28:09 -08004989 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4990 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004991 VOS_ASSERT(0);
4992 return -ENOMEM;
4993 }
4994 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4995 pWextState->assocAddIE.length += eLen + 2;
4996
4997 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4998 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4999 break;
5000 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005001#ifdef FEATURE_WLAN_WAPI
5002 case WLAN_EID_WAPI:
5003 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
5004 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
5005 pAdapter->wapi_info.nWapiMode);
5006 tmp = (u16 *)ie;
5007 tmp = tmp + 2; // Skip element Id and Len, Version
5008 akmsuiteCount = WPA_GET_LE16(tmp);
5009 tmp = tmp + 1;
5010 akmlist = (int *)(tmp);
5011 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
5012 {
5013 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
5014 }
5015 else
5016 {
5017 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
5018 VOS_ASSERT(0);
5019 return -EINVAL;
5020 }
5021
5022 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
5023 {
5024 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005025 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005026 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5027 }
5028 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5029 {
5030 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005031 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005032 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5033 }
5034 break;
5035#endif
5036 default:
5037 hddLog (VOS_TRACE_LEVEL_ERROR,
5038 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005039 /* when Unknown IE is received we should break and continue
5040 * to the next IE in the buffer instead we were returning
5041 * so changing this to break */
5042 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005043 }
5044 genie += eLen;
5045 remLen -= eLen;
5046 }
5047 EXIT();
5048 return 0;
5049}
5050
5051/*
5052 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5053 * This function is used to initialize the security
5054 * parameters during connect operation.
5055 */
5056int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5057 struct cfg80211_connect_params *req
5058 )
5059{
5060 int status = 0;
5061 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5062 ENTER();
5063
5064 /*set wpa version*/
5065 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5066
5067 if (req->crypto.wpa_versions)
5068 {
5069 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5070 && ( (req->ie_len)
5071 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5072 // Make sure that it is including a WPA IE.
5073 /* Currently NL is putting WPA version 1 even for open,
5074 * since p2p ie is also put in same buffer.
5075 * */
5076 {
5077 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5078 }
5079 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5080 {
5081 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5082 }
5083 }
5084
5085 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5086 pWextState->wpaVersion);
5087
5088 /*set authentication type*/
5089 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5090
5091 if (0 > status)
5092 {
5093 hddLog(VOS_TRACE_LEVEL_ERROR,
5094 "%s: failed to set authentication type ", __func__);
5095 return status;
5096 }
5097
5098 /*set key mgmt type*/
5099 if (req->crypto.n_akm_suites)
5100 {
5101 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5102 if (0 > status)
5103 {
5104 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5105 __func__);
5106 return status;
5107 }
5108 }
5109
5110 /*set pairwise cipher type*/
5111 if (req->crypto.n_ciphers_pairwise)
5112 {
5113 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5114 req->crypto.ciphers_pairwise[0], true);
5115 if (0 > status)
5116 {
5117 hddLog(VOS_TRACE_LEVEL_ERROR,
5118 "%s: failed to set unicast cipher type", __func__);
5119 return status;
5120 }
5121 }
5122 else
5123 {
5124 /*Reset previous cipher suite to none*/
5125 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5126 if (0 > status)
5127 {
5128 hddLog(VOS_TRACE_LEVEL_ERROR,
5129 "%s: failed to set unicast cipher type", __func__);
5130 return status;
5131 }
5132 }
5133
5134 /*set group cipher type*/
5135 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5136 false);
5137
5138 if (0 > status)
5139 {
5140 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5141 __func__);
5142 return status;
5143 }
5144
5145 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5146 if (req->ie_len)
5147 {
5148 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5149 if ( 0 > status)
5150 {
5151 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5152 __func__);
5153 return status;
5154 }
5155 }
5156
5157 /*incase of WEP set default key information*/
5158 if (req->key && req->key_len)
5159 {
5160 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5161 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5162 )
5163 {
5164 if ( IW_AUTH_KEY_MGMT_802_1X
5165 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5166 {
5167 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5168 __func__);
5169 return -EOPNOTSUPP;
5170 }
5171 else
5172 {
5173 u8 key_len = req->key_len;
5174 u8 key_idx = req->key_idx;
5175
5176 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5177 && (CSR_MAX_NUM_KEY > key_idx)
5178 )
5179 {
5180 hddLog(VOS_TRACE_LEVEL_INFO,
5181 "%s: setting default wep key, key_idx = %hu key_len %hu",
5182 __func__, key_idx, key_len);
5183 vos_mem_copy(
5184 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5185 req->key, key_len);
5186 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5187 (u8)key_len;
5188 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5189 }
5190 }
5191 }
5192 }
5193
5194 return status;
5195}
5196
5197/*
5198 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5199 * This function is used to initialize the security
5200 * parameters during connect operation.
5201 */
5202static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5203 struct net_device *ndev,
5204 struct cfg80211_connect_params *req
5205 )
5206{
5207 int status = 0;
5208 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5209 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5210 hdd_context_t *pHddCtx = NULL;
5211
5212 ENTER();
5213
5214 hddLog(VOS_TRACE_LEVEL_INFO,
5215 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5216
5217 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5218 {
5219 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5220 "%s:LOGP in Progress. Ignore!!!", __func__);
5221 return -EAGAIN;
5222 }
5223
5224#ifdef WLAN_BTAMP_FEATURE
5225 //Infra connect not supported when AMP traffic is on.
5226 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5227 {
5228 hddLog(VOS_TRACE_LEVEL_ERROR,
5229 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005230 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005231 }
5232#endif
5233 /*initialise security parameters*/
5234 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5235
5236 if ( 0 > status)
5237 {
5238 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5239 __func__);
5240 return status;
5241 }
5242
5243 //If Device Mode is Station Concurrent Sessions Exit BMps
Madan Mohan Koyyalamudic1275fc2012-12-12 16:49:33 -08005244 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005245 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5246 (vos_concurrent_sessions_running()))
5247 {
5248 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5249
5250 if (NULL != pVosContext)
5251 {
5252 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5253 if(NULL != pHddCtx)
5254 {
5255 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5256 }
5257 }
5258 }
5259
Mohit Khanna765234a2012-09-11 15:08:35 -07005260 if ( req->channel )
5261 {
5262 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5263 req->ssid_len, req->bssid,
5264 req->channel->hw_value);
5265 }
5266 else
5267 {
5268 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5269 req->ssid_len, req->bssid,
5270 0);
5271 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005272
5273 if (0 > status)
5274 {
5275 //ReEnable BMPS if disabled
5276 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5277 (NULL != pHddCtx))
5278 {
5279 //ReEnable Bmps and Imps back
5280 hdd_enable_bmps_imps(pHddCtx);
5281 }
5282
5283 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5284 return status;
5285 }
5286 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5287 EXIT();
5288 return status;
5289}
5290
5291
5292/*
5293 * FUNCTION: wlan_hdd_cfg80211_disconnect
5294 * This function is used to issue a disconnect request to SME
5295 */
5296static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5297 struct net_device *dev,
5298 u16 reason
5299 )
5300{
5301 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5302 tCsrRoamProfile *pRoamProfile =
5303 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5304 int status = 0;
5305 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5306
5307 ENTER();
5308
5309 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5310 __func__,pAdapter->device_mode);
5311
5312 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5313 __func__, reason);
5314
5315 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5316 {
5317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5318 "%s:LOGP in Progress. Ignore!!!",__func__);
5319 return -EAGAIN;
5320 }
5321 if (NULL != pRoamProfile)
5322 {
5323 /*issue disconnect request to SME, if station is in connected state*/
5324 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5325 {
5326 eCsrRoamDisconnectReason reasonCode =
5327 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5328 switch(reason)
5329 {
5330 case WLAN_REASON_MIC_FAILURE:
5331 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5332 break;
5333
5334 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5335 case WLAN_REASON_DISASSOC_AP_BUSY:
5336 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5337 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5338 break;
5339
5340 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5341 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5342 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5343 break;
5344
5345 case WLAN_REASON_DEAUTH_LEAVING:
5346 default:
5347 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5348 break;
5349 }
5350 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5351 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5352 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5353
5354 /*issue disconnect*/
5355 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5356 pAdapter->sessionId, reasonCode);
5357
5358 if ( 0 != status)
5359 {
5360 hddLog(VOS_TRACE_LEVEL_ERROR,
5361 "%s csrRoamDisconnect failure, returned %d \n",
5362 __func__, (int)status );
5363 return -EINVAL;
5364 }
5365
5366 wait_for_completion_interruptible_timeout(
5367 &pAdapter->disconnect_comp_var,
5368 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5369
5370
5371 /*stop tx queues*/
5372 netif_tx_disable(dev);
5373 netif_carrier_off(dev);
5374 }
5375 }
5376 else
5377 {
5378 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5379 }
5380
5381 return status;
5382}
5383
5384/*
5385 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5386 * This function is used to initialize the security
5387 * settings in IBSS mode.
5388 */
5389static int wlan_hdd_cfg80211_set_privacy_ibss(
5390 hdd_adapter_t *pAdapter,
5391 struct cfg80211_ibss_params *params
5392 )
5393{
5394 int status = 0;
5395 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5396 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5397 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5398
5399 ENTER();
5400
5401 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5402
5403 if (params->ie_len && ( NULL != params->ie) )
5404 {
5405 if (WLAN_EID_RSN == params->ie[0])
5406 {
5407 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5408 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5409 }
5410 else
5411 {
5412 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5413 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5414 }
5415 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5416
5417 if (0 > status)
5418 {
5419 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5420 __func__);
5421 return status;
5422 }
5423 }
5424
5425 pWextState->roamProfile.AuthType.authType[0] =
5426 pHddStaCtx->conn_info.authType =
5427 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5428
5429 if (params->privacy)
5430 {
5431 /* Security enabled IBSS, At this time there is no information available
5432 * about the security paramters, so initialise the encryption type to
5433 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5434 * The correct security parameters will be updated later in
5435 * wlan_hdd_cfg80211_add_key */
5436 /* Hal expects encryption type to be set inorder
5437 *enable privacy bit in beacons */
5438
5439 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5440 }
5441
5442 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5443 pWextState->roamProfile.EncryptionType.numEntries = 1;
5444 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5445
5446 return status;
5447}
5448
5449/*
5450 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5451 * This function is used to create/join an IBSS
5452 */
5453static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5454 struct net_device *dev,
5455 struct cfg80211_ibss_params *params
5456 )
5457{
5458 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5459 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5460 tCsrRoamProfile *pRoamProfile;
5461 int status;
5462 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5463
5464 ENTER();
5465
5466 hddLog(VOS_TRACE_LEVEL_INFO,
5467 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5468
5469 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5470 {
5471 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5472 "%s:LOGP in Progress. Ignore!!!", __func__);
5473 return -EAGAIN;
5474 }
5475
5476 if (NULL == pWextState)
5477 {
5478 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5479 __func__);
5480 return -EIO;
5481 }
5482
5483 pRoamProfile = &pWextState->roamProfile;
5484
5485 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5486 {
5487 hddLog (VOS_TRACE_LEVEL_ERROR,
5488 "%s Interface type is not set to IBSS \n", __func__);
5489 return -EINVAL;
5490 }
5491
5492 /* Set Channel */
5493 if (NULL != params->channel)
5494 {
5495 u8 channelNum;
5496 if (IEEE80211_BAND_5GHZ == params->channel->band)
5497 {
5498 hddLog(VOS_TRACE_LEVEL_ERROR,
5499 "%s: IBSS join is called with unsupported band %d",
5500 __func__, params->channel->band);
5501 return -EOPNOTSUPP;
5502 }
5503
5504 /* Get channel number */
5505 channelNum =
5506 ieee80211_frequency_to_channel(params->channel->center_freq);
5507
5508 /*TODO: use macro*/
5509 if (14 >= channelNum)
5510 {
5511 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5512 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5513 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5514 int indx;
5515
5516 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5517 validChan, &numChans))
5518 {
5519 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5520 __func__);
5521 return -EOPNOTSUPP;
5522 }
5523
5524 for (indx = 0; indx < numChans; indx++)
5525 {
5526 if (channelNum == validChan[indx])
5527 {
5528 break;
5529 }
5530 }
5531 if (indx >= numChans)
5532 {
5533 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5534 __func__, channelNum);
5535 return -EINVAL;
5536 }
5537 /* Set the Operational Channel */
5538 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5539 channelNum);
5540 pRoamProfile->ChannelInfo.numOfChannels = 1;
5541 pHddStaCtx->conn_info.operationChannel = channelNum;
5542 pRoamProfile->ChannelInfo.ChannelList =
5543 &pHddStaCtx->conn_info.operationChannel;
5544 }
5545 else
5546 {
5547 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5548 __func__, channelNum);
5549 return -EINVAL;
5550 }
5551 }
5552
5553 /* Initialize security parameters */
5554 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5555 if (status < 0)
5556 {
5557 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5558 __func__);
5559 return status;
5560 }
5561
5562 /* Issue connect start */
5563 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005564 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005565
5566 if (0 > status)
5567 {
5568 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5569 return status;
5570 }
5571
5572 return 0;
5573}
5574
5575/*
5576 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5577 * This function is used to leave an IBSS
5578 */
5579static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5580 struct net_device *dev
5581 )
5582{
5583 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5584 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5585 tCsrRoamProfile *pRoamProfile;
5586
5587 ENTER();
5588
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005589 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5590 {
5591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5592 "%s:LOGP in Progress. Ignore!!!", __func__);
5593 return -EAGAIN;
5594 }
5595
Jeff Johnson295189b2012-06-20 16:38:30 -07005596 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5597 if (NULL == pWextState)
5598 {
5599 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5600 __func__);
5601 return -EIO;
5602 }
5603
5604 pRoamProfile = &pWextState->roamProfile;
5605
5606 /* Issue disconnect only if interface type is set to IBSS */
5607 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5608 {
5609 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5610 __func__);
5611 return -EINVAL;
5612 }
5613
5614 /* Issue Disconnect request */
5615 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5616 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5617 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5618
5619 return 0;
5620}
5621
5622/*
5623 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5624 * This function is used to set the phy parameters
5625 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5626 */
5627static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5628 u32 changed)
5629{
5630 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5631 tHalHandle hHal = pHddCtx->hHal;
5632
5633 ENTER();
5634
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005635 if ( pHddCtx->isLogpInProgress )
5636 {
5637 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5638 "%s:LOGP in Progress. Ignore!!!", __func__);
5639 return -EAGAIN;
5640 }
5641
Jeff Johnson295189b2012-06-20 16:38:30 -07005642 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5643 {
5644 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5645 WNI_CFG_RTS_THRESHOLD_STAMAX :
5646 wiphy->rts_threshold;
5647
5648 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5649 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5650 {
5651 hddLog(VOS_TRACE_LEVEL_ERROR,
5652 "%s: Invalid RTS Threshold value %hu",
5653 __func__, rts_threshold);
5654 return -EINVAL;
5655 }
5656
5657 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5658 rts_threshold, ccmCfgSetCallback,
5659 eANI_BOOLEAN_TRUE))
5660 {
5661 hddLog(VOS_TRACE_LEVEL_ERROR,
5662 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5663 __func__, rts_threshold);
5664 return -EIO;
5665 }
5666
5667 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5668 rts_threshold);
5669 }
5670
5671 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5672 {
5673 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5674 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5675 wiphy->frag_threshold;
5676
5677 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5678 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5679 {
5680 hddLog(VOS_TRACE_LEVEL_ERROR,
5681 "%s: Invalid frag_threshold value %hu", __func__,
5682 frag_threshold);
5683 return -EINVAL;
5684 }
5685
5686 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5687 frag_threshold, ccmCfgSetCallback,
5688 eANI_BOOLEAN_TRUE))
5689 {
5690 hddLog(VOS_TRACE_LEVEL_ERROR,
5691 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5692 __func__, frag_threshold);
5693 return -EIO;
5694 }
5695
5696 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5697 frag_threshold);
5698 }
5699
5700 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5701 || (changed & WIPHY_PARAM_RETRY_LONG))
5702 {
5703 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5704 wiphy->retry_short :
5705 wiphy->retry_long;
5706
5707 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5708 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5709 {
5710 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5711 __func__, retry_value);
5712 return -EINVAL;
5713 }
5714
5715 if (changed & WIPHY_PARAM_RETRY_SHORT)
5716 {
5717 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5718 retry_value, ccmCfgSetCallback,
5719 eANI_BOOLEAN_TRUE))
5720 {
5721 hddLog(VOS_TRACE_LEVEL_ERROR,
5722 "%s: ccmCfgSetInt failed for long retry count %hu",
5723 __func__, retry_value);
5724 return -EIO;
5725 }
5726 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5727 __func__, retry_value);
5728 }
5729 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5730 {
5731 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5732 retry_value, ccmCfgSetCallback,
5733 eANI_BOOLEAN_TRUE))
5734 {
5735 hddLog(VOS_TRACE_LEVEL_ERROR,
5736 "%s: ccmCfgSetInt failed for short retry count %hu",
5737 __func__, retry_value);
5738 return -EIO;
5739 }
5740 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5741 __func__, retry_value);
5742 }
5743 }
5744
5745 return 0;
5746}
5747
5748/*
5749 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5750 * This function is used to set the txpower
5751 */
5752static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5753#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5754 enum tx_power_setting type,
5755#else
5756 enum nl80211_tx_power_setting type,
5757#endif
5758 int dbm)
5759{
5760 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5761 tHalHandle hHal = pHddCtx->hHal;
5762 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5763 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5764
5765 ENTER();
5766
5767 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5768 dbm, ccmCfgSetCallback,
5769 eANI_BOOLEAN_TRUE))
5770 {
5771 hddLog(VOS_TRACE_LEVEL_ERROR,
5772 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5773 return -EIO;
5774 }
5775
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005776 if ( pHddCtx->isLogpInProgress )
5777 {
5778 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5779 "%s:LOGP in Progress. Ignore!!!", __func__);
5780 return -EAGAIN;
5781 }
5782
Jeff Johnson295189b2012-06-20 16:38:30 -07005783 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5784 dbm);
5785
5786 switch(type)
5787 {
5788 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5789 /* Fall through */
5790 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5791 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5792 {
5793 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5794 __func__);
5795 return -EIO;
5796 }
5797 break;
5798 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5799 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5800 __func__);
5801 return -EOPNOTSUPP;
5802 break;
5803 default:
5804 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5805 __func__, type);
5806 return -EIO;
5807 }
5808
5809 return 0;
5810}
5811
5812/*
5813 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5814 * This function is used to read the txpower
5815 */
5816static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5817{
5818
5819 hdd_adapter_t *pAdapter;
5820 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5821
Jeff Johnsone7245742012-09-05 17:12:55 -07005822 ENTER();
5823
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 if (NULL == pHddCtx)
5825 {
5826 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5827 *dbm = 0;
5828 return -ENOENT;
5829 }
5830
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005831 if ( pHddCtx->isLogpInProgress )
5832 {
5833 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5834 "%s:LOGP in Progress. Ignore!!!", __func__);
5835 return -EAGAIN;
5836 }
5837
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5839 if (NULL == pAdapter)
5840 {
5841 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5842 return -ENOENT;
5843 }
5844
5845 wlan_hdd_get_classAstats(pAdapter);
5846 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5847
Jeff Johnsone7245742012-09-05 17:12:55 -07005848 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005849 return 0;
5850}
5851
5852static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5853 u8* mac, struct station_info *sinfo)
5854{
5855 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5856 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5857 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5858 tANI_U8 rate_flags;
5859
5860 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5861 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5862 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5863
5864 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5865 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5866 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5867 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5868 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5869 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5870 tANI_U16 maxRate = 0;
5871 tANI_U16 myRate;
5872 tANI_U16 currentRate = 0;
5873 tANI_U8 maxSpeedMCS = 0;
5874 tANI_U8 maxMCSIdx = 0;
5875 tANI_U8 rateFlag = 1;
5876 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005877 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005878
Jeff Johnsone7245742012-09-05 17:12:55 -07005879 ENTER();
5880
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5882 (0 == ssidlen))
5883 {
5884 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5885 " Invalid ssidlen, %d", __func__, ssidlen);
5886 /*To keep GUI happy*/
5887 return 0;
5888 }
5889
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005890 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5891 {
5892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5893 "%s:LOGP in Progress. Ignore!!!", __func__);
5894 return -EAGAIN;
5895 }
5896
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5898 sinfo->filled |= STATION_INFO_SIGNAL;
5899
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005900 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005901 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5902
5903 //convert to the UI units of 100kbps
5904 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5905
5906#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005907 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 -07005908 sinfo->signal,
5909 pCfg->reportMaxLinkSpeed,
5910 myRate,
5911 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005912 (int) pCfg->linkSpeedRssiMid,
5913 (int) pCfg->linkSpeedRssiLow,
5914 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005915#endif //LINKSPEED_DEBUG_ENABLED
5916
5917 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5918 {
5919 // we do not want to necessarily report the current speed
5920 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5921 {
5922 // report the max possible speed
5923 rssidx = 0;
5924 }
5925 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5926 {
5927 // report the max possible speed with RSSI scaling
5928 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5929 {
5930 // report the max possible speed
5931 rssidx = 0;
5932 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005933 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005934 {
5935 // report middle speed
5936 rssidx = 1;
5937 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005938 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5939 {
5940 // report middle speed
5941 rssidx = 2;
5942 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 else
5944 {
5945 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005946 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 }
5948 }
5949 else
5950 {
5951 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5952 hddLog(VOS_TRACE_LEVEL_ERROR,
5953 "%s: Invalid value for reportMaxLinkSpeed: %u",
5954 __func__, pCfg->reportMaxLinkSpeed);
5955 rssidx = 0;
5956 }
5957
5958 maxRate = 0;
5959
5960 /* Get Basic Rate Set */
5961 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5962 for (i = 0; i < ORLeng; i++)
5963 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005964 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005965 {
5966 /* Validate Rate Set */
5967 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5968 {
5969 currentRate = supported_data_rate[j].supported_rate[rssidx];
5970 break;
5971 }
5972 }
5973 /* Update MAX rate */
5974 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5975 }
5976
5977 /* Get Extended Rate Set */
5978 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5979 for (i = 0; i < ERLeng; i++)
5980 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005981 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005982 {
5983 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5984 {
5985 currentRate = supported_data_rate[j].supported_rate[rssidx];
5986 break;
5987 }
5988 }
5989 /* Update MAX rate */
5990 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5991 }
5992
5993 /* Get MCS Rate Set -- but only if we are connected at MCS
5994 rates or if we are always reporting max speed or if we have
5995 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005996 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005997 {
5998 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5999 rateFlag = 0;
6000 if (rate_flags & eHAL_TX_RATE_HT40)
6001 {
6002 rateFlag |= 1;
6003 }
6004 if (rate_flags & eHAL_TX_RATE_SGI)
6005 {
6006 rateFlag |= 2;
6007 }
6008
6009 for (i = 0; i < MCSLeng; i++)
6010 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006011 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
6012 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07006013 {
6014 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
6015 {
6016 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
6017 break;
6018 }
6019 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006020 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006021 {
6022 maxRate = currentRate;
6023 maxSpeedMCS = 1;
6024 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6025 }
6026 }
6027 }
6028
6029 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006030 if (((maxRate < myRate) && (0 == rssidx)) ||
6031 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006032 {
6033 maxRate = myRate;
6034 if (rate_flags & eHAL_TX_RATE_LEGACY)
6035 {
6036 maxSpeedMCS = 0;
6037 }
6038 else
6039 {
6040 maxSpeedMCS = 1;
6041 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6042 }
6043 }
6044
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006045 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006046 {
6047 sinfo->txrate.legacy = maxRate;
6048#ifdef LINKSPEED_DEBUG_ENABLED
6049 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6050#endif //LINKSPEED_DEBUG_ENABLED
6051 }
6052 else
6053 {
6054 sinfo->txrate.mcs = maxMCSIdx;
6055 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6056 if (rate_flags & eHAL_TX_RATE_SGI)
6057 {
6058 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6059 }
6060 if (rate_flags & eHAL_TX_RATE_HT40)
6061 {
6062 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6063 }
6064#ifdef LINKSPEED_DEBUG_ENABLED
6065 pr_info("Reporting MCS rate %d flags %x\n",
6066 sinfo->txrate.mcs,
6067 sinfo->txrate.flags );
6068#endif //LINKSPEED_DEBUG_ENABLED
6069 }
6070 }
6071 else
6072 {
6073 // report current rate instead of max rate
6074
6075 if (rate_flags & eHAL_TX_RATE_LEGACY)
6076 {
6077 //provide to the UI in units of 100kbps
6078 sinfo->txrate.legacy = myRate;
6079#ifdef LINKSPEED_DEBUG_ENABLED
6080 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6081#endif //LINKSPEED_DEBUG_ENABLED
6082 }
6083 else
6084 {
6085 //must be MCS
6086 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6087 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6088 if (rate_flags & eHAL_TX_RATE_SGI)
6089 {
6090 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6091 }
6092 if (rate_flags & eHAL_TX_RATE_HT40)
6093 {
6094 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6095 }
6096#ifdef LINKSPEED_DEBUG_ENABLED
6097 pr_info("Reporting actual MCS rate %d flags %x\n",
6098 sinfo->txrate.mcs,
6099 sinfo->txrate.flags );
6100#endif //LINKSPEED_DEBUG_ENABLED
6101 }
6102 }
6103 sinfo->filled |= STATION_INFO_TX_BITRATE;
6104
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006105 sinfo->tx_packets =
6106 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6107 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6108 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6109 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6110
6111 sinfo->tx_retries =
6112 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6113 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6114 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6115 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6116
6117 sinfo->tx_failed =
6118 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6119 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6120 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6121 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6122
6123 sinfo->filled |=
6124 STATION_INFO_TX_PACKETS |
6125 STATION_INFO_TX_RETRIES |
6126 STATION_INFO_TX_FAILED;
6127
6128 EXIT();
6129 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006130}
6131
6132static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6133 struct net_device *dev, bool mode, v_SINT_t timeout)
6134{
6135 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6136 VOS_STATUS vos_status;
6137
Jeff Johnsone7245742012-09-05 17:12:55 -07006138 ENTER();
6139
Jeff Johnson295189b2012-06-20 16:38:30 -07006140 if (NULL == pAdapter)
6141 {
6142 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6143 return -ENODEV;
6144 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006145 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6146 {
6147 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6148 "%s:LOGP in Progress. Ignore!!!", __func__);
6149 return -EAGAIN;
6150 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006151
6152 /**The get power cmd from the supplicant gets updated by the nl only
6153 *on successful execution of the function call
6154 *we are oppositely mapped w.r.t mode in the driver
6155 **/
6156 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6157
Jeff Johnsone7245742012-09-05 17:12:55 -07006158 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006159 if (VOS_STATUS_E_FAILURE == vos_status)
6160 {
6161 return -EINVAL;
6162 }
6163 return 0;
6164}
6165
6166
6167#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6168static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6169 struct net_device *netdev,
6170 u8 key_index)
6171{
Jeff Johnsone7245742012-09-05 17:12:55 -07006172 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006173 return 0;
6174}
6175#endif //LINUX_VERSION_CODE
6176
6177#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6178static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6179 struct net_device *dev,
6180 struct ieee80211_txq_params *params)
6181{
Jeff Johnsone7245742012-09-05 17:12:55 -07006182 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006183 return 0;
6184}
6185#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6186static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6187 struct ieee80211_txq_params *params)
6188{
Jeff Johnsone7245742012-09-05 17:12:55 -07006189 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 return 0;
6191}
6192#endif //LINUX_VERSION_CODE
6193
6194static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6195 struct net_device *dev, u8 *mac)
6196{
6197 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudi15407ac2013-01-11 15:30:36 -08006198 VOS_STATUS vos_status;
6199 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006200
Jeff Johnsone7245742012-09-05 17:12:55 -07006201 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006202 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6203 {
6204 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6205 return -EINVAL;
6206 }
6207
6208 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6209 {
6210 hddLog( LOGE,
6211 "%s: Wlan Load/Unload is in progress", __func__);
6212 return -EBUSY;
6213 }
6214
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006215 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6216 {
6217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6218 "%s:LOGP in Progress. Ignore!!!", __func__);
6219 return -EAGAIN;
6220 }
6221
Jeff Johnson295189b2012-06-20 16:38:30 -07006222 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6223#ifdef WLAN_FEATURE_P2P
6224 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6225#endif
6226 )
6227 {
6228 if( NULL == mac )
6229 {
6230 v_U16_t i;
6231 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6232 {
6233 if(pAdapter->aStaInfo[i].isUsed)
6234 {
6235 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6236 hddLog(VOS_TRACE_LEVEL_INFO,
6237 "%s: Delete STA with MAC::"
6238 "%02x:%02x:%02x:%02x:%02x:%02x",
6239 __func__,
6240 macAddr[0], macAddr[1], macAddr[2],
6241 macAddr[3], macAddr[4], macAddr[5]);
6242 hdd_softap_sta_deauth(pAdapter, macAddr);
6243 }
6244 }
6245 }
6246 else
6247 {
Madan Mohan Koyyalamudi15407ac2013-01-11 15:30:36 -08006248
6249 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6250 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6251 {
6252 hddLog(VOS_TRACE_LEVEL_INFO,
6253 "%s: Skip this DEL STA as this is not used::"
6254 "%02x:%02x:%02x:%02x:%02x:%02x",
6255 __func__,
6256 mac[0], mac[1], mac[2],
6257 mac[3], mac[4], mac[5]);
6258 return -ENOENT;
6259 }
6260
6261 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6262 {
6263 hddLog(VOS_TRACE_LEVEL_INFO,
6264 "%s: Skip this DEL STA as deauth is in progress::"
6265 "%02x:%02x:%02x:%02x:%02x:%02x",
6266 __func__,
6267 mac[0], mac[1], mac[2],
6268 mac[3], mac[4], mac[5]);
6269 return -ENOENT;
6270 }
6271
6272 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6273
Jeff Johnson295189b2012-06-20 16:38:30 -07006274 hddLog(VOS_TRACE_LEVEL_INFO,
6275 "%s: Delete STA with MAC::"
6276 "%02x:%02x:%02x:%02x:%02x:%02x",
6277 __func__,
6278 mac[0], mac[1], mac[2],
6279 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudi15407ac2013-01-11 15:30:36 -08006280
6281 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6282 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6283 {
6284 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6285 hddLog(VOS_TRACE_LEVEL_INFO,
6286 "%s: STA removal failed for ::"
6287 "%02x:%02x:%02x:%02x:%02x:%02x",
6288 __func__,
6289 mac[0], mac[1], mac[2],
6290 mac[3], mac[4], mac[5]);
6291 return -ENOENT;
6292 }
6293
Jeff Johnson295189b2012-06-20 16:38:30 -07006294 }
6295 }
6296
6297 EXIT();
6298
6299 return 0;
6300}
6301
6302static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6303 struct net_device *dev, u8 *mac, struct station_parameters *params)
6304{
Mohit Khannac0b992f2012-12-04 15:08:18 -08006305#ifdef FEATURE_WLAN_TDLS
6306 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6307 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6308 u32 mask, set;
6309 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006310 ENTER();
Mohit Khannac0b992f2012-12-04 15:08:18 -08006311
6312 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6313 {
6314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6315 "Invalid arguments");
6316 return -EINVAL;
6317 }
6318
6319 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6320 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6321 {
6322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6323 "TDLS Disabled in INI OR not enabled in FW.\
6324 Cannot process TDLS commands \n");
6325 return -ENOTSUPP;
6326 }
Lee Hoonkif1431702013-01-24 21:59:00 -08006327 /* first to check if we reached to maximum supported TDLS peer.
6328 TODO: for now, return -EPERM looks working fine,
6329 but need to check if any other errno fit into this category.*/
6330 if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
6331 {
6332 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6333 "%s: TDLS Max peer already connected. Request declined. \n",
6334 __func__);
6335 return -EPERM;
6336 }
Mohit Khannac0b992f2012-12-04 15:08:18 -08006337
6338 mask = params->sta_flags_mask;
6339
6340 set = params->sta_flags_set;
6341
6342
Lee Hoonkif1431702013-01-24 21:59:00 -08006343 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6344 "%s: mask 0x%x set 0x%x\n",__func__, mask, set);
Mohit Khannac0b992f2012-12-04 15:08:18 -08006345
6346 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6347 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6349 "Add TDLS peer");
6350
6351
6352 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6353 pAdapter->sessionId, mac);
6354
6355 if (VOS_STATUS_SUCCESS != status) {
6356 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6357 "%s: sme_AddTdlsPeerSta failed!", __func__);
6358 }
6359 }
6360 }
6361#endif
6362
Jeff Johnson295189b2012-06-20 16:38:30 -07006363 return 0;
6364}
6365
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006366
6367#ifdef FEATURE_WLAN_LFR
6368static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006369 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006370{
6371#define MAX_PMKSAIDS_IN_CACHE 8
6372 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006373 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006374 tANI_U32 j=0;
6375 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6376 tHalHandle halHandle;
6377 eHalStatus result;
6378 tANI_U8 BSSIDMatched = 0;
6379
Jeff Johnsone7245742012-09-05 17:12:55 -07006380 ENTER();
6381
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006382 // Validate pAdapter
6383 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6384 {
6385 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6386 return -EINVAL;
6387 }
6388
6389 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6390 {
6391 hddLog( LOGE,
6392 "%s: Wlan Load/Unload is in progress", __func__);
6393 return -EBUSY;
6394 }
6395
6396 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6397 {
6398 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6399 "%s:LOGP in Progress. Ignore!!!", __func__);
6400 return -EAGAIN;
6401 }
6402
6403 // Retrieve halHandle
6404 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6405
6406 for (j = 0; j < i; j++)
6407 {
6408 if(vos_mem_compare(PMKIDCache[j].BSSID,
6409 pmksa->bssid, WNI_CFG_BSSID_LEN))
6410 {
6411 /* BSSID matched previous entry. Overwrite it. */
6412 BSSIDMatched = 1;
6413 vos_mem_copy(PMKIDCache[j].BSSID,
6414 pmksa->bssid, WNI_CFG_BSSID_LEN);
6415 vos_mem_copy(PMKIDCache[j].PMKID,
6416 pmksa->pmkid,
6417 CSR_RSN_PMKID_SIZE);
6418 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006419 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006420 dump_bssid(pmksa->bssid);
6421 dump_pmkid(halHandle, pmksa->pmkid);
6422 break;
6423 }
6424 }
6425
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006426 /* Check we compared all entries,if then take the first slot now */
6427 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6428
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006429 if (!BSSIDMatched)
6430 {
6431 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6432 vos_mem_copy(PMKIDCache[i].BSSID,
6433 pmksa->bssid, ETHER_ADDR_LEN);
6434 vos_mem_copy(PMKIDCache[i].PMKID,
6435 pmksa->pmkid,
6436 CSR_RSN_PMKID_SIZE);
6437 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006438 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006439 dump_bssid(pmksa->bssid);
6440 dump_pmkid(halHandle, pmksa->pmkid);
6441 // Increment the HDD Local Cache index
6442 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6443 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6444 }
6445
6446
6447 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6448 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006449 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006450 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006451 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006452 // Finally set the PMKSA ID Cache in CSR
6453 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6454 PMKIDCache,
6455 i );
6456 return 0;
6457}
6458
6459
6460static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006461 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006462{
Jeff Johnsone7245742012-09-05 17:12:55 -07006463 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006464 // TODO: Implement this later.
6465 return 0;
6466}
6467
6468static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6469{
Jeff Johnsone7245742012-09-05 17:12:55 -07006470 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006471 // TODO: Implement this later.
6472 return 0;
6473}
6474#endif
6475
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006476#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6477static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6478 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6479{
6480 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6481 hdd_station_ctx_t *pHddStaCtx;
6482
6483 if (NULL == pAdapter)
6484 {
6485 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6486 return -ENODEV;
6487 }
6488
6489 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6490
6491 // Added for debug on reception of Re-assoc Req.
6492 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6493 {
6494 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6495 ftie->ie_len);
6496 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6497 }
6498
6499#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6500 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6501 ftie->ie_len);
6502#endif
6503
6504 // Pass the received FT IEs to SME
6505 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6506 ftie->ie_len);
6507 return 0;
6508}
6509#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006510
Mohit Khannac0b992f2012-12-04 15:08:18 -08006511#ifdef FEATURE_WLAN_TDLS
6512static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6513 u8 *peer, u8 action_code, u8 dialog_token,
6514 u16 status_code, const u8 *buf, size_t len)
6515{
6516
6517 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6518 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6519 u8 *buf_1;
6520 size_t len_1 = len;
6521 u8 peerMac[6];
6522 VOS_STATUS status;
6523
6524 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6525 {
6526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6527 "Invalid arguments");
6528 return -EINVAL;
6529 }
6530
6531 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6532 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6533 {
6534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6535 "TDLS Disabled in INI OR not enabled in FW.\
6536 Cannot process TDLS commands \n");
6537 return -ENOTSUPP;
6538 }
Lee Hoonkif1431702013-01-24 21:59:00 -08006539
6540 if(SIR_MAC_TDLS_SETUP_REQ == action_code ||
6541 SIR_MAC_TDLS_SETUP_RSP == action_code )
6542 {
6543 if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
6544 {
6545 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6546 we return error code at 'add_station()'. Hence we have this
6547 check again in addtion to add_station().
6548 Anyway, there is no hard to double-check. */
6549 if(SIR_MAC_TDLS_SETUP_REQ == action_code)
6550 {
6551 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6552 "%s: TDLS Max peer already connected. Request declined. \n",
6553 __func__);
6554 return -EPERM;
6555 }
6556 else
6557 {
6558 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
6559 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6560 "%s: TDLS Max peer already connected send response status %d \n",
6561 __func__,status_code);
6562 }
6563 }
6564 }
Mohit Khannac0b992f2012-12-04 15:08:18 -08006565 vos_mem_copy( peerMac, peer, 6);
6566
Hoonki Lee068d4142013-01-16 17:40:54 -08006567#ifdef WLAN_FEATURE_TDLS_DEBUG
6568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6569 "%s: %02x:%02x:%02x:%02x:%02x:%02x) action %d, dialog_token %d status %d, len = %d",
6570 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6571 action_code, dialog_token, status_code, len);
6572#endif
Mohit Khannac0b992f2012-12-04 15:08:18 -08006573
6574 buf_1 = vos_mem_malloc(len);
6575 if(buf_1 == NULL) {
6576 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6577 "%s: malloc failed!", __func__);
6578 return -ENOMEM;
6579 }
6580 vos_mem_copy(buf_1, buf, len);
6581
6582 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6583 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6584
6585 if (VOS_STATUS_SUCCESS != status) {
6586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6587 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6588 }
6589
6590 vos_mem_free(buf_1);
6591
6592 return 0;
6593}
6594
6595static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6596 u8 *peer, enum nl80211_tdls_operation oper)
6597{
6598 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6599 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee068d4142013-01-16 17:40:54 -08006600#ifdef WLAN_FEATURE_TDLS_DEBUG
6601 const char *tdls_oper_str[]= {
6602 "NL80211_TDLS_DISCOVERY_REQ",
6603 "NL80211_TDLS_SETUP",
6604 "NL80211_TDLS_TEARDOWN",
6605 "NL80211_TDLS_ENABLE_LINK",
6606 "NL80211_TDLS_DISABLE_LINK",
6607 "NL80211_TDLS_UNKONW_OPER"};
6608#endif
Mohit Khannac0b992f2012-12-04 15:08:18 -08006609
6610 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6611 {
6612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6613 "Invalid arguments");
6614 return -EINVAL;
6615 }
Hoonki Lee068d4142013-01-16 17:40:54 -08006616
6617#ifdef WLAN_FEATURE_TDLS_DEBUG
6618 if((int)oper > 4)
6619 oper = 5;
6620
6621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6622 "%s: %02x:%02x:%02x:%02x:%02x:%02x: %d (%s) ", "tdls_oper",
6623 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5], (int)oper,
6624 tdls_oper_str[(int)oper]);
6625#endif
Mohit Khannac0b992f2012-12-04 15:08:18 -08006626
6627 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee068d4142013-01-16 17:40:54 -08006628 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khannac0b992f2012-12-04 15:08:18 -08006629 {
Hoonki Lee068d4142013-01-16 17:40:54 -08006630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khannac0b992f2012-12-04 15:08:18 -08006631 "TDLS Disabled in INI OR not enabled in FW.\
6632 Cannot process TDLS commands \n");
6633 return -ENOTSUPP;
6634 }
6635
6636 switch (oper) {
6637 case NL80211_TDLS_ENABLE_LINK:
6638 {
Hoonki Lee068d4142013-01-16 17:40:54 -08006639 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Mohit Khannac0b992f2012-12-04 15:08:18 -08006640 v_U8_t my_peer[6];
6641 v_U8_t ucSTAId;
6642 VOS_STATUS status;
6643
6644 if (peer) {
6645 vos_mem_copy(my_peer, peer, 6);
6646 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6647
6648 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6649 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6650 __func__, peer[0], peer[1],
6651 peer[2], peer[3],
6652 peer[4], peer[5] );
6653
6654 if (-1 == ucSTAId ) {
6655 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
Hoonki Leebec7bad2013-01-16 19:29:14 -08006656 return -EINVAL;
Mohit Khannac0b992f2012-12-04 15:08:18 -08006657 }
6658
6659 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6660 WLANTL_STA_AUTHENTICATED );
6661
Hoonki Leebec7bad2013-01-16 19:29:14 -08006662 //This can fail only if the staId is not registered yet with TL
6663 //return -EINVAL in such case.
Mohit Khannac0b992f2012-12-04 15:08:18 -08006664 if (0 != status) {
6665 hddLog(VOS_TRACE_LEVEL_ERROR,
6666 "%s: WLANTL_ChangeSTAState failed, returned %d",
6667 __func__, status);
Hoonki Leebec7bad2013-01-16 19:29:14 -08006668 return -EINVAL;
Mohit Khannac0b992f2012-12-04 15:08:18 -08006669 }
Hoonki Leebec7bad2013-01-16 19:29:14 -08006670
Chilam NGde0b4112013-01-19 12:27:36 +05306671 wlan_hdd_tdls_set_link_status(peer, eTDLS_LINK_CONNECTED);
6672
Mohit Khannac0b992f2012-12-04 15:08:18 -08006673 } else {
6674 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6675 }
6676 }
6677 break;
6678 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkif1431702013-01-24 21:59:00 -08006679 {
6680 if(-1 != wlan_hdd_findTdlsPeer(peer))
6681 {
6682 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6683 pAdapter->sessionId, peer );
6684 }
6685 else
6686 {
6687 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6688 "%s: TDLS Peer Station doesn't exist \n",__func__);
6689 }
6690 return 0;
6691 }
Mohit Khannac0b992f2012-12-04 15:08:18 -08006692 case NL80211_TDLS_TEARDOWN:
6693 case NL80211_TDLS_SETUP:
6694 case NL80211_TDLS_DISCOVERY_REQ:
6695 /* We don't support in-driver setup/teardown/discovery */
6696 return -ENOTSUPP;
6697 default:
6698 return -ENOTSUPP;
6699 }
6700 return 0;
6701}
Chilam NGde0b4112013-01-19 12:27:36 +05306702
6703int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
6704 struct net_device *dev, u8 *peer)
6705{
6706 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
6707 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6708
6709 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
6710 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
6711}
Mohit Khannac0b992f2012-12-04 15:08:18 -08006712#endif
6713
Jeff Johnson295189b2012-06-20 16:38:30 -07006714/* cfg80211_ops */
6715static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6716{
6717 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6718 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6719 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6720 .change_station = wlan_hdd_change_station,
6721#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6722 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6723 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6724 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006725#else
6726 .start_ap = wlan_hdd_cfg80211_start_ap,
6727 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6728 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006729#endif
6730 .change_bss = wlan_hdd_cfg80211_change_bss,
6731 .add_key = wlan_hdd_cfg80211_add_key,
6732 .get_key = wlan_hdd_cfg80211_get_key,
6733 .del_key = wlan_hdd_cfg80211_del_key,
6734 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnsoncab8ddc2013-01-18 17:05:29 -08006735#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07006736 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnsoncab8ddc2013-01-18 17:05:29 -08006737#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006738 .scan = wlan_hdd_cfg80211_scan,
6739 .connect = wlan_hdd_cfg80211_connect,
6740 .disconnect = wlan_hdd_cfg80211_disconnect,
6741 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6742 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6743 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6744 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6745 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6746#ifdef WLAN_FEATURE_P2P
6747 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6748 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6749 .mgmt_tx = wlan_hdd_action,
6750#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6751 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6752 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6753 .set_txq_params = wlan_hdd_set_txq_params,
6754#endif
6755#endif
6756 .get_station = wlan_hdd_cfg80211_get_station,
6757 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6758 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006759 .add_station = wlan_hdd_cfg80211_add_station,
6760#ifdef FEATURE_WLAN_LFR
6761 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6762 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6763 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6764#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006765#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6766 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6767#endif
Mohit Khannac0b992f2012-12-04 15:08:18 -08006768#ifdef FEATURE_WLAN_TDLS
6769 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6770 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6771#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006772};
6773
6774#endif // CONFIG_CFG80211