blob: 1c6e7f03018414bbd503cc769a6d62ebf2a8cfd1 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
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
22/**========================================================================
23
24 \file wlan_hdd_cfg80211.c
25
26 \brief WLAN Host Device Driver implementation
27
28 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
29
30 Qualcomm Confidential and Proprietary.
31
32 ========================================================================*/
33
34/**=========================================================================
35
36 EDIT HISTORY FOR FILE
37
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
42
43 $Header:$ $DateTime: $ $Author: $
44
45
46 when who what, where, why
47 -------- --- --------------------------------------------------------
48 21/12/09 Ashwani Created module.
49
50 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
51 Ganesh K
52 ==========================================================================*/
53
54#ifdef CONFIG_CFG80211
55
56#include <linux/version.h>
57#include <linux/module.h>
58#include <linux/kernel.h>
59#include <linux/init.h>
60#include <linux/wireless.h>
61#include <wlan_hdd_includes.h>
62#include <net/arp.h>
63#include <net/cfg80211.h>
64#include <linux/wireless.h>
65#include <wlan_hdd_wowl.h>
66#include <aniGlobal.h>
67#include "ccmApi.h"
68#include "sirParams.h"
69#include "dot11f.h"
70#include "wlan_hdd_assoc.h"
71#include "wlan_hdd_wext.h"
72#include "sme_Api.h"
73#include "wlan_hdd_p2p.h"
74#include "wlan_hdd_cfg80211.h"
75#include "wlan_hdd_hostapd.h"
76#include "sapInternal.h"
77#include "wlan_hdd_softap_tx_rx.h"
78#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053079#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070080#ifdef WLAN_BTAMP_FEATURE
81#include "bap_hdd_misc.h"
82#endif
83#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -080084#ifdef FEATURE_WLAN_TDLS
85#include "wlan_hdd_tdls.h"
86#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070087
88#define g_mode_rates_size (12)
89#define a_mode_rates_size (8)
90#define FREQ_BASE_80211G (2407)
91#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070092#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -070093#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
94 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
95
96#define HDD2GHZCHAN(freq, chan, flag) { \
97 .band = IEEE80211_BAND_2GHZ, \
98 .center_freq = (freq), \
99 .hw_value = (chan),\
100 .flags = (flag), \
101 .max_antenna_gain = 0 ,\
102 .max_power = 30, \
103}
104
105#define HDD5GHZCHAN(freq, chan, flag) { \
106 .band = IEEE80211_BAND_5GHZ, \
107 .center_freq = (freq), \
108 .hw_value = (chan),\
109 .flags = (flag), \
110 .max_antenna_gain = 0 ,\
111 .max_power = 30, \
112}
113
114#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
115{\
116 .bitrate = rate, \
117 .hw_value = rate_id, \
118 .flags = flag, \
119}
120
121static const u32 hdd_cipher_suites[] =
122{
123 WLAN_CIPHER_SUITE_WEP40,
124 WLAN_CIPHER_SUITE_WEP104,
125 WLAN_CIPHER_SUITE_TKIP,
126#ifdef FEATURE_WLAN_CCX
127#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
128 WLAN_CIPHER_SUITE_KRK,
129 WLAN_CIPHER_SUITE_CCMP,
130#else
131 WLAN_CIPHER_SUITE_CCMP,
132#endif
133#ifdef FEATURE_WLAN_WAPI
134 WLAN_CIPHER_SUITE_SMS4,
135#endif
136};
137
138static inline int is_broadcast_ether_addr(const u8 *addr)
139{
140 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
141 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
142}
143
144static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
145{
146 HDD2GHZCHAN(2412, 1, 0) ,
147 HDD2GHZCHAN(2417, 2, 0) ,
148 HDD2GHZCHAN(2422, 3, 0) ,
149 HDD2GHZCHAN(2427, 4, 0) ,
150 HDD2GHZCHAN(2432, 5, 0) ,
151 HDD2GHZCHAN(2437, 6, 0) ,
152 HDD2GHZCHAN(2442, 7, 0) ,
153 HDD2GHZCHAN(2447, 8, 0) ,
154 HDD2GHZCHAN(2452, 9, 0) ,
155 HDD2GHZCHAN(2457, 10, 0) ,
156 HDD2GHZCHAN(2462, 11, 0) ,
157 HDD2GHZCHAN(2467, 12, 0) ,
158 HDD2GHZCHAN(2472, 13, 0) ,
159 HDD2GHZCHAN(2484, 14, 0) ,
160};
161
162#ifdef WLAN_FEATURE_P2P
163static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
164{
165 HDD2GHZCHAN(2412, 1, 0) ,
166 HDD2GHZCHAN(2437, 6, 0) ,
167 HDD2GHZCHAN(2462, 11, 0) ,
168};
169#endif
170
171static struct ieee80211_channel hdd_channels_5_GHZ[] =
172{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700173 HDD5GHZCHAN(4920, 240, 0) ,
174 HDD5GHZCHAN(4940, 244, 0) ,
175 HDD5GHZCHAN(4960, 248, 0) ,
176 HDD5GHZCHAN(4980, 252, 0) ,
177 HDD5GHZCHAN(5040, 208, 0) ,
178 HDD5GHZCHAN(5060, 212, 0) ,
179 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700180 HDD5GHZCHAN(5180, 36, 0) ,
181 HDD5GHZCHAN(5200, 40, 0) ,
182 HDD5GHZCHAN(5220, 44, 0) ,
183 HDD5GHZCHAN(5240, 48, 0) ,
184 HDD5GHZCHAN(5260, 52, 0) ,
185 HDD5GHZCHAN(5280, 56, 0) ,
186 HDD5GHZCHAN(5300, 60, 0) ,
187 HDD5GHZCHAN(5320, 64, 0) ,
188 HDD5GHZCHAN(5500,100, 0) ,
189 HDD5GHZCHAN(5520,104, 0) ,
190 HDD5GHZCHAN(5540,108, 0) ,
191 HDD5GHZCHAN(5560,112, 0) ,
192 HDD5GHZCHAN(5580,116, 0) ,
193 HDD5GHZCHAN(5600,120, 0) ,
194 HDD5GHZCHAN(5620,124, 0) ,
195 HDD5GHZCHAN(5640,128, 0) ,
196 HDD5GHZCHAN(5660,132, 0) ,
197 HDD5GHZCHAN(5680,136, 0) ,
198 HDD5GHZCHAN(5700,140, 0) ,
199 HDD5GHZCHAN(5745,149, 0) ,
200 HDD5GHZCHAN(5765,153, 0) ,
201 HDD5GHZCHAN(5785,157, 0) ,
202 HDD5GHZCHAN(5805,161, 0) ,
203 HDD5GHZCHAN(5825,165, 0) ,
204};
205
206static struct ieee80211_rate g_mode_rates[] =
207{
208 HDD_G_MODE_RATETAB(10, 0x1, 0),
209 HDD_G_MODE_RATETAB(20, 0x2, 0),
210 HDD_G_MODE_RATETAB(55, 0x4, 0),
211 HDD_G_MODE_RATETAB(110, 0x8, 0),
212 HDD_G_MODE_RATETAB(60, 0x10, 0),
213 HDD_G_MODE_RATETAB(90, 0x20, 0),
214 HDD_G_MODE_RATETAB(120, 0x40, 0),
215 HDD_G_MODE_RATETAB(180, 0x80, 0),
216 HDD_G_MODE_RATETAB(240, 0x100, 0),
217 HDD_G_MODE_RATETAB(360, 0x200, 0),
218 HDD_G_MODE_RATETAB(480, 0x400, 0),
219 HDD_G_MODE_RATETAB(540, 0x800, 0),
220};
221
222static struct ieee80211_rate a_mode_rates[] =
223{
224 HDD_G_MODE_RATETAB(60, 0x10, 0),
225 HDD_G_MODE_RATETAB(90, 0x20, 0),
226 HDD_G_MODE_RATETAB(120, 0x40, 0),
227 HDD_G_MODE_RATETAB(180, 0x80, 0),
228 HDD_G_MODE_RATETAB(240, 0x100, 0),
229 HDD_G_MODE_RATETAB(360, 0x200, 0),
230 HDD_G_MODE_RATETAB(480, 0x400, 0),
231 HDD_G_MODE_RATETAB(540, 0x800, 0),
232};
233
234static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
235{
236 .channels = hdd_channels_2_4_GHZ,
237 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
238 .band = IEEE80211_BAND_2GHZ,
239 .bitrates = g_mode_rates,
240 .n_bitrates = g_mode_rates_size,
241 .ht_cap.ht_supported = 1,
242 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
243 | IEEE80211_HT_CAP_GRN_FLD
244 | IEEE80211_HT_CAP_DSSSCCK40
245 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
246 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
247 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
248 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
249 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
250 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
251};
252
253#ifdef WLAN_FEATURE_P2P
254static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
255{
256 .channels = hdd_social_channels_2_4_GHZ,
257 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
258 .band = IEEE80211_BAND_2GHZ,
259 .bitrates = g_mode_rates,
260 .n_bitrates = g_mode_rates_size,
261 .ht_cap.ht_supported = 1,
262 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
263 | IEEE80211_HT_CAP_GRN_FLD
264 | IEEE80211_HT_CAP_DSSSCCK40
265 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
266 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
267 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
268 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
269 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
270 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
271};
272#endif
273
274static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
275{
276 .channels = hdd_channels_5_GHZ,
277 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
278 .band = IEEE80211_BAND_5GHZ,
279 .bitrates = a_mode_rates,
280 .n_bitrates = a_mode_rates_size,
281 .ht_cap.ht_supported = 1,
282 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
283 | IEEE80211_HT_CAP_GRN_FLD
284 | IEEE80211_HT_CAP_DSSSCCK40
285 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
286 | IEEE80211_HT_CAP_SGI_40
287 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
288 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
289 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
290 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
291 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
292 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
293};
294
295/* This structure contain information what kind of frame are expected in
296 TX/RX direction for each kind of interface */
297static const struct ieee80211_txrx_stypes
298wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
299 [NL80211_IFTYPE_STATION] = {
300 .tx = 0xffff,
301 .rx = BIT(SIR_MAC_MGMT_ACTION) |
302 BIT(SIR_MAC_MGMT_PROBE_REQ),
303 },
304 [NL80211_IFTYPE_AP] = {
305 .tx = 0xffff,
306 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
307 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
308 BIT(SIR_MAC_MGMT_PROBE_REQ) |
309 BIT(SIR_MAC_MGMT_DISASSOC) |
310 BIT(SIR_MAC_MGMT_AUTH) |
311 BIT(SIR_MAC_MGMT_DEAUTH) |
312 BIT(SIR_MAC_MGMT_ACTION),
313 },
314#ifdef WLAN_FEATURE_P2P
315 [NL80211_IFTYPE_P2P_CLIENT] = {
316 .tx = 0xffff,
317 .rx = BIT(SIR_MAC_MGMT_ACTION) |
318 BIT(SIR_MAC_MGMT_PROBE_REQ),
319 },
320 [NL80211_IFTYPE_P2P_GO] = {
321 /* This is also same as for SoftAP */
322 .tx = 0xffff,
323 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
324 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
325 BIT(SIR_MAC_MGMT_PROBE_REQ) |
326 BIT(SIR_MAC_MGMT_DISASSOC) |
327 BIT(SIR_MAC_MGMT_AUTH) |
328 BIT(SIR_MAC_MGMT_DEAUTH) |
329 BIT(SIR_MAC_MGMT_ACTION),
330 },
331#endif
332};
333
334static struct cfg80211_ops wlan_hdd_cfg80211_ops;
335
336/* Data rate 100KBPS based on IE Index */
337struct index_data_rate_type
338{
339 v_U8_t beacon_rate_index;
340 v_U16_t supported_rate[4];
341};
342
343/* 11B, 11G Rate table include Basic rate and Extended rate
344 The IDX field is the rate index
345 The HI field is the rate when RSSI is strong or being ignored
346 (in this case we report actual rate)
347 The MID field is the rate when RSSI is moderate
348 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
349 The LO field is the rate when RSSI is low
350 (in this case we don't report rates, actual current rate used)
351 */
352static const struct
353{
354 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700355 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700356} supported_data_rate[] =
357{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700358/* IDX HI HM LM LO (RSSI-based index */
359 {2, { 10, 10, 10, 0}},
360 {4, { 20, 20, 10, 0}},
361 {11, { 55, 20, 10, 0}},
362 {12, { 60, 55, 20, 0}},
363 {18, { 90, 55, 20, 0}},
364 {22, {110, 55, 20, 0}},
365 {24, {120, 90, 60, 0}},
366 {36, {180, 120, 60, 0}},
367 {44, {220, 180, 60, 0}},
368 {48, {240, 180, 90, 0}},
369 {66, {330, 180, 90, 0}},
370 {72, {360, 240, 90, 0}},
371 {96, {480, 240, 120, 0}},
372 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700373};
374
375/* MCS Based rate table */
376static struct index_data_rate_type supported_mcs_rate[] =
377{
378/* MCS L20 L40 S20 S40 */
379 {0, {65, 135, 72, 150}},
380 {1, {130, 270, 144, 300}},
381 {2, {195, 405, 217, 450}},
382 {3, {260, 540, 289, 600}},
383 {4, {390, 810, 433, 900}},
384 {5, {520, 1080, 578, 1200}},
385 {6, {585, 1215, 650, 1350}},
386 {7, {650, 1350, 722, 1500}}
387};
388
389extern struct net_device_ops net_ops_struct;
390
391/*
392 * FUNCTION: wlan_hdd_cfg80211_init
393 * This function is called by hdd_wlan_startup()
394 * during initialization.
395 * This function is used to initialize and register wiphy structure.
396 */
397struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
398{
399 struct wiphy *wiphy;
400 ENTER();
401
402 /*
403 * Create wiphy device
404 */
405 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
406
407 if (!wiphy)
408 {
409 /* Print error and jump into err label and free the memory */
410 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
411 return NULL;
412 }
413
414 return wiphy;
415}
416
417/*
418 * FUNCTION: wlan_hdd_cfg80211_update_band
419 * This function is called from the supplicant through a
420 * private ioctl to change the band value
421 */
422int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
423{
Jeff Johnsone7245742012-09-05 17:12:55 -0700424 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700425 switch(eBand)
426 {
427 case eCSR_BAND_24:
428 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
429 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
430 break;
431 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700432#ifdef WLAN_FEATURE_P2P
433 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
434#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700435 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700436#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700437 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
438 break;
439 case eCSR_BAND_ALL:
440 default:
441 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
442 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
443 }
444 return 0;
445}
446/*
447 * FUNCTION: wlan_hdd_cfg80211_init
448 * This function is called by hdd_wlan_startup()
449 * during initialization.
450 * This function is used to initialize and register wiphy structure.
451 */
452int wlan_hdd_cfg80211_register(struct device *dev,
453 struct wiphy *wiphy,
454 hdd_config_t *pCfg
455 )
456{
Jeff Johnsone7245742012-09-05 17:12:55 -0700457 ENTER();
458
Jeff Johnson295189b2012-06-20 16:38:30 -0700459 /* Now bind the underlying wlan device with wiphy */
460 set_wiphy_dev(wiphy, dev);
461
462 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
463
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700464 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700465
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700466#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700467 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
468 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
469 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700470 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700471#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800472#ifdef FEATURE_WLAN_TDLS
473 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
474 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
475#endif
476
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700477 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
478 driver can still register regulatory callback and
479 it will get CRDA setting in wiphy->band[], but
480 driver need to determine what to do with both
481 regulatory settings */
482 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700483
Jeff Johnson295189b2012-06-20 16:38:30 -0700484 wiphy->max_scan_ssids = MAX_SCAN_SSID;
485
486 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
487
488 /* Supports STATION & AD-HOC modes right now */
489 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
490 | BIT(NL80211_IFTYPE_ADHOC)
491#ifdef WLAN_FEATURE_P2P
492 | BIT(NL80211_IFTYPE_P2P_CLIENT)
493 | BIT(NL80211_IFTYPE_P2P_GO)
494#endif
495 | BIT(NL80211_IFTYPE_AP);
496
497 /* Before registering we need to update the ht capabilitied based
498 * on ini values*/
499 if( !pCfg->ShortGI20MhzEnable )
500 {
501 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
502 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
503 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
504 }
505
506 if( !pCfg->ShortGI40MhzEnable )
507 {
508 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
509 }
510
511 if( !pCfg->nChannelBondingMode5GHz )
512 {
513 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
514 }
515
516 /*Initialize band capability*/
517 switch(pCfg->nBandCapability)
518 {
519 case eCSR_BAND_24:
520 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
521 break;
522 case eCSR_BAND_5G:
523#ifdef WLAN_FEATURE_P2P
524 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
525#endif
526 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
527 break;
528 case eCSR_BAND_ALL:
529 default:
530 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
531 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
532 }
533 /*Initialise the supported cipher suite details*/
534 wiphy->cipher_suites = hdd_cipher_suites;
535 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
536
537 /*signal strength in mBm (100*dBm) */
538 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
539
540#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
541#ifdef WLAN_FEATURE_P2P
542 wiphy->max_remain_on_channel_duration = 1000;
543#endif
544#endif
545
546 /* Register our wiphy dev with cfg80211 */
547 if (0 > wiphy_register(wiphy))
548 {
549 /* print eror */
550 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
551 return -EIO;
552 }
553
554 EXIT();
555 return 0;
556}
557
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700558/* In this function we will try to get default country code from crda.
559 If the gCrdaDefaultCountryCode is configured in ini file,
560 we will try to call user space crda to get the regulatory settings for
561 that country. We will timeout if we can't get it from crda.
562 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
563*/
564int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
565{
566 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
567 if (memcmp(pCfg->crdaDefaultCountryCode,
568 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
569 {
570 init_completion(&pHddCtx->driver_crda_req);
571 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
572 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
573 CRDA_WAIT_TIME);
574 }
575 return 0;
576}
577
Jeff Johnson295189b2012-06-20 16:38:30 -0700578/* In this function we will do all post VOS start initialization.
579 In this function we will register for all frame in which supplicant
580 is interested.
581*/
582void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
583{
584#ifdef WLAN_FEATURE_P2P
585 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
586 /* Register for all P2P action, public action etc frames */
587 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
588
Jeff Johnsone7245742012-09-05 17:12:55 -0700589 ENTER();
590
Jeff Johnson295189b2012-06-20 16:38:30 -0700591 /* Right now we are registering these frame when driver is getting
592 initialized. Once we will move to 2.6.37 kernel, in which we have
593 frame register ops, we will move this code as a part of that */
594 /* GAS Initial Request */
595 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
596 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
597
598 /* GAS Initial Response */
599 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
600 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
601
602 /* GAS Comeback Request */
603 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
604 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
605
606 /* GAS Comeback Response */
607 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
608 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
609
610 /* P2P Public Action */
611 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
612 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
613 P2P_PUBLIC_ACTION_FRAME_SIZE );
614
615 /* P2P Action */
616 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
617 (v_U8_t*)P2P_ACTION_FRAME,
618 P2P_ACTION_FRAME_SIZE );
619#endif /* WLAN_FEATURE_P2P */
620}
621
622void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
623{
624#ifdef WLAN_FEATURE_P2P
625 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
626 /* Register for all P2P action, public action etc frames */
627 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
628
Jeff Johnsone7245742012-09-05 17:12:55 -0700629 ENTER();
630
Jeff Johnson295189b2012-06-20 16:38:30 -0700631 /* Right now we are registering these frame when driver is getting
632 initialized. Once we will move to 2.6.37 kernel, in which we have
633 frame register ops, we will move this code as a part of that */
634 /* GAS Initial Request */
635
636 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
637 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
638
639 /* GAS Initial Response */
640 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
641 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
642
643 /* GAS Comeback Request */
644 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
645 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
646
647 /* GAS Comeback Response */
648 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
649 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
650
651 /* P2P Public Action */
652 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
653 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
654 P2P_PUBLIC_ACTION_FRAME_SIZE );
655
656 /* P2P Action */
657 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
658 (v_U8_t*)P2P_ACTION_FRAME,
659 P2P_ACTION_FRAME_SIZE );
660#endif /* WLAN_FEATURE_P2P */
661}
662
663#ifdef FEATURE_WLAN_WAPI
664void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
665 const u8 *mac_addr, u8 *key , int key_Len)
666{
667 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
668 tCsrRoamSetKey setKey;
669 v_BOOL_t isConnected = TRUE;
670 int status = 0;
671 v_U32_t roamId= 0xFF;
672 tANI_U8 *pKeyPtr = NULL;
673 int n = 0;
674
675 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
676 __func__,pAdapter->device_mode);
677
678 setKey.keyId = key_index; // Store Key ID
679 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
680 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
681 setKey.paeRole = 0 ; // the PAE role
682 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
683 {
684 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
685 }
686 else
687 {
688 isConnected = hdd_connIsConnected(pHddStaCtx);
689 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
690 }
691 setKey.keyLength = key_Len;
692 pKeyPtr = setKey.Key;
693 memcpy( pKeyPtr, key, key_Len);
694
695 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
696 __func__, key_Len);
697 for (n = 0 ; n < key_Len; n++)
698 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
699 __func__,n,setKey.Key[n]);
700
701 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
702 if ( isConnected )
703 {
704 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
705 pAdapter->sessionId, &setKey, &roamId );
706 }
707 if ( status != 0 )
708 {
709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
710 "[%4d] sme_RoamSetKey returned ERROR status= %d",
711 __LINE__, status );
712 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
713 }
714}
715#endif /* FEATURE_WLAN_WAPI*/
716
717#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
718int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
719 beacon_data_t **ppBeacon,
720 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700721#else
722int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
723 beacon_data_t **ppBeacon,
724 struct cfg80211_beacon_data *params,
725 int dtim_period)
726#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700727{
728 int size;
729 beacon_data_t *beacon = NULL;
730 beacon_data_t *old = NULL;
731 int head_len,tail_len;
732
Jeff Johnsone7245742012-09-05 17:12:55 -0700733 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700734 if (params->head && !params->head_len)
735 return -EINVAL;
736
737 old = pAdapter->sessionCtx.ap.beacon;
738
739 if (!params->head && !old)
740 return -EINVAL;
741
742 if (params->tail && !params->tail_len)
743 return -EINVAL;
744
745#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
746 /* Kernel 3.0 is not updating dtim_period for set beacon */
747 if (!params->dtim_period)
748 return -EINVAL;
749#endif
750
751 if(params->head)
752 head_len = params->head_len;
753 else
754 head_len = old->head_len;
755
756 if(params->tail || !old)
757 tail_len = params->tail_len;
758 else
759 tail_len = old->tail_len;
760
761 size = sizeof(beacon_data_t) + head_len + tail_len;
762
763 beacon = kzalloc(size, GFP_KERNEL);
764
765 if( beacon == NULL )
766 return -ENOMEM;
767
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700768#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700769 if(params->dtim_period || !old )
770 beacon->dtim_period = params->dtim_period;
771 else
772 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700773#else
774 if(dtim_period || !old )
775 beacon->dtim_period = dtim_period;
776 else
777 beacon->dtim_period = old->dtim_period;
778#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700779
780 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
781 beacon->tail = beacon->head + head_len;
782 beacon->head_len = head_len;
783 beacon->tail_len = tail_len;
784
785 if(params->head) {
786 memcpy (beacon->head,params->head,beacon->head_len);
787 }
788 else {
789 if(old)
790 memcpy (beacon->head,old->head,beacon->head_len);
791 }
792
793 if(params->tail) {
794 memcpy (beacon->tail,params->tail,beacon->tail_len);
795 }
796 else {
797 if(old)
798 memcpy (beacon->tail,old->tail,beacon->tail_len);
799 }
800
801 *ppBeacon = beacon;
802
803 kfree(old);
804
805 return 0;
806
807}
Jeff Johnson295189b2012-06-20 16:38:30 -0700808
809v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
810{
811 int left = length;
812 v_U8_t *ptr = pIes;
813 v_U8_t elem_id,elem_len;
814
815 while(left >= 2)
816 {
817 elem_id = ptr[0];
818 elem_len = ptr[1];
819 left -= 2;
820 if(elem_len > left)
821 {
822 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700823 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700824 eid,elem_len,left);
825 return NULL;
826 }
827 if (elem_id == eid)
828 {
829 return ptr;
830 }
831
832 left -= elem_len;
833 ptr += (elem_len + 2);
834 }
835 return NULL;
836}
837
Jeff Johnson295189b2012-06-20 16:38:30 -0700838/* Check if rate is 11g rate or not */
839static int wlan_hdd_rate_is_11g(u8 rate)
840{
841 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
842 u8 i;
843 for (i = 0; i < 8; i++)
844 {
845 if(rate == gRateArray[i])
846 return TRUE;
847 }
848 return FALSE;
849}
850
851/* Check for 11g rate and set proper 11g only mode */
852static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
853 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
854{
855 u8 i, num_rates = pIe[0];
856
857 pIe += 1;
858 for ( i = 0; i < num_rates; i++)
859 {
860 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
861 {
862 /* If rate set have 11g rate than change the mode to 11G */
863 *pSapHw_mode = eSAP_DOT11_MODE_11g;
864 if (pIe[i] & BASIC_RATE_MASK)
865 {
866 /* If we have 11g rate as basic rate, it means mode
867 is 11g only mode.
868 */
869 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
870 *pCheckRatesfor11g = FALSE;
871 }
872 }
873 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
874 {
875 *require_ht = TRUE;
876 }
877 }
878 return;
879}
880
881static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
882{
883 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
884 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
885 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
886 u8 checkRatesfor11g = TRUE;
887 u8 require_ht = FALSE;
888 u8 *pIe=NULL;
889
890 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
891
892 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
893 pBeacon->head_len, WLAN_EID_SUPP_RATES);
894 if (pIe != NULL)
895 {
896 pIe += 1;
897 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
898 &pConfig->SapHw_mode);
899 }
900
901 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
902 WLAN_EID_EXT_SUPP_RATES);
903 if (pIe != NULL)
904 {
905
906 pIe += 1;
907 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
908 &pConfig->SapHw_mode);
909 }
910
911 if( pConfig->channel > 14 )
912 {
913 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
914 }
915
916 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
917 WLAN_EID_HT_CAPABILITY);
918
919 if(pIe)
920 {
921 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
922 if(require_ht)
923 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
924 }
925}
926
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700927#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700928static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
929 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700930#else
931static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
932 struct cfg80211_beacon_data *params)
933#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700934{
935 v_U8_t *genie;
936 v_U8_t total_ielen = 0, ielen = 0;
937 v_U8_t *pIe = NULL;
938 v_U8_t addIE[1] = {0};
939 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -0700940 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700941
942 genie = vos_mem_malloc(MAX_GENIE_LEN);
943
944 if(genie == NULL) {
945
946 return -ENOMEM;
947 }
948
949 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
950
951 if(pIe)
952 {
953 /*Copy the wps IE*/
954 ielen = pIe[1] + 2;
955 if( ielen <=MAX_GENIE_LEN)
956 {
957 vos_mem_copy(genie, pIe, ielen);
958 }
959 else
960 {
961 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700962 ret = -EINVAL;
963 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700964 }
965 total_ielen = ielen;
966 }
967
968#ifdef WLAN_FEATURE_WFD
969 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
970
971 if(pIe)
972 {
973 ielen = pIe[1] + 2;
974 if(total_ielen + ielen <= MAX_GENIE_LEN) {
975 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
976 }
977 else {
978 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700979 ret = -EINVAL;
980 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700981 }
982 total_ielen += ielen;
983 }
984#endif
985
986#ifdef WLAN_FEATURE_P2P
987 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
988
989 if(pIe)
990 {
991 ielen = pIe[1] + 2;
992 if(total_ielen + ielen <= MAX_GENIE_LEN)
993 {
994 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
995 }
996 else
997 {
998 hddLog( VOS_TRACE_LEVEL_ERROR,
999 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001000 ret = -EINVAL;
1001 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001002 }
1003 total_ielen += ielen;
1004 }
1005#endif
1006
1007 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1008 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1009 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1010 {
1011 hddLog(LOGE,
1012 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001013 ret = -EINVAL;
1014 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001015 }
1016
1017 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1018 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1019 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1020 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1021 ==eHAL_STATUS_FAILURE)
1022 {
1023 hddLog(LOGE,
1024 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001025 ret = -EINVAL;
1026 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001027 }
1028
1029 // Added for ProResp IE
1030 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1031 {
1032 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1033 u8 probe_rsp_ie_len[3] = {0};
1034 u8 counter = 0;
1035 /* Check Probe Resp Length if it is greater then 255 then Store
1036 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1037 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1038 Store More then 255 bytes into One Variable.
1039 */
1040 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1041 {
1042 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1043 {
1044 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1045 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1046 }
1047 else
1048 {
1049 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1050 rem_probe_resp_ie_len = 0;
1051 }
1052 }
1053
1054 rem_probe_resp_ie_len = 0;
1055
1056 if (probe_rsp_ie_len[0] > 0)
1057 {
1058 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1059 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1060 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1061 probe_rsp_ie_len[0], NULL,
1062 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1063 {
1064 hddLog(LOGE,
1065 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001066 ret = -EINVAL;
1067 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001068 }
1069 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1070 }
1071
1072 if (probe_rsp_ie_len[1] > 0)
1073 {
1074 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1075 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1076 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1077 probe_rsp_ie_len[1], NULL,
1078 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1079 {
1080 hddLog(LOGE,
1081 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001082 ret = -EINVAL;
1083 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001084 }
1085 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1086 }
1087
1088 if (probe_rsp_ie_len[2] > 0)
1089 {
1090 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1091 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1092 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1093 probe_rsp_ie_len[2], NULL,
1094 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1095 {
1096 hddLog(LOGE,
1097 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001098 ret = -EINVAL;
1099 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001100 }
1101 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1102 }
1103
1104 if (probe_rsp_ie_len[1] == 0 )
1105 {
1106 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1107 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1108 eANI_BOOLEAN_FALSE) )
1109 {
1110 hddLog(LOGE,
1111 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1112 }
1113 }
1114
1115 if (probe_rsp_ie_len[2] == 0 )
1116 {
1117 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1118 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1119 eANI_BOOLEAN_FALSE) )
1120 {
1121 hddLog(LOGE,
1122 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1123 }
1124 }
1125
1126 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1127 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1128 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1129 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1130 == eHAL_STATUS_FAILURE)
1131 {
1132 hddLog(LOGE,
1133 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001134 ret = -EINVAL;
1135 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001136 }
1137 }
1138 else
1139 {
1140 // Reset WNI_CFG_PROBE_RSP Flags
1141 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1142
1143 hddLog(VOS_TRACE_LEVEL_INFO,
1144 "%s: No Probe Response IE received in set beacon",
1145 __func__);
1146 }
1147
1148 // Added for AssocResp IE
1149 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1150 {
1151 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1152 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1153 params->assocresp_ies_len, NULL,
1154 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1155 {
1156 hddLog(LOGE,
1157 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001158 ret = -EINVAL;
1159 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001160 }
1161
1162 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1163 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1164 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1165 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1166 == eHAL_STATUS_FAILURE)
1167 {
1168 hddLog(LOGE,
1169 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001170 ret = -EINVAL;
1171 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001172 }
1173 }
1174 else
1175 {
1176 hddLog(VOS_TRACE_LEVEL_INFO,
1177 "%s: No Assoc Response IE received in set beacon",
1178 __func__);
1179
1180 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1181 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1182 eANI_BOOLEAN_FALSE) )
1183 {
1184 hddLog(LOGE,
1185 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1186 }
1187 }
1188
Jeff Johnsone7245742012-09-05 17:12:55 -07001189done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001190 vos_mem_free(genie);
1191 return 0;
1192}
Jeff Johnson295189b2012-06-20 16:38:30 -07001193
1194/*
1195 * FUNCTION: wlan_hdd_validate_operation_channel
1196 * called by wlan_hdd_cfg80211_start_bss() and
1197 * wlan_hdd_cfg80211_set_channel()
1198 * This function validates whether given channel is part of valid
1199 * channel list.
1200 */
1201static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1202{
1203
1204 v_U32_t num_ch = 0;
1205 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1206 u32 indx = 0;
1207 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1208
1209 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1210
1211 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1212 valid_ch, &num_ch))
1213 {
1214 hddLog(VOS_TRACE_LEVEL_ERROR,
1215 "%s: failed to get valid channel list\n", __func__);
1216 return VOS_STATUS_E_FAILURE;
1217 }
1218
1219 for (indx = 0; indx < num_ch; indx++)
1220 {
1221 if (channel == valid_ch[indx])
1222 {
1223 break;
1224 }
1225 }
1226
1227 if (indx >= num_ch)
1228 {
1229 hddLog(VOS_TRACE_LEVEL_ERROR,
1230 "%s: Invalid Channel [%d] \n", __func__, channel);
1231 return VOS_STATUS_E_FAILURE;
1232 }
1233 return VOS_STATUS_SUCCESS;
1234
1235}
1236
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301237/*
1238 * FUNCTION: wlan_hdd_select_cbmode
1239 * called by wlan_hdd_cfg80211_start_bss() and
1240 * This function selects the cbmode based on primary channel
1241 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001242VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301243{
1244 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001245 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1246 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1247
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301248 if(
1249#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001250 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1251 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301252#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001253 SapHw_mode != eSAP_DOT11_MODE_11n &&
1254 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301255 )
1256 {
1257 return VOS_STATUS_SUCCESS;
1258 }
1259
1260 if (!pConfigIni->nChannelBondingMode5GHz) {
1261 return VOS_STATUS_SUCCESS;
1262 }
1263
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001264 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301265 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1266
1267 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1268
1269#ifdef WLAN_FEATURE_11AC
1270
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001271 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1272 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301273 {
1274 if ( channel== 36 || channel == 52 || channel == 100 ||
1275 channel == 116 || channel == 149 )
1276 {
1277 smeConfig.csrConfig.channelBondingMode5GHz =
1278 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1279 }
1280 else if ( channel == 40 || channel == 56 || channel == 104 ||
1281 channel == 120 || channel == 153 )
1282 {
1283 smeConfig.csrConfig.channelBondingMode5GHz =
1284 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1285 }
1286 else if ( channel == 44 || channel == 60 || channel == 108 ||
1287 channel == 124 || channel == 157 )
1288 {
1289 smeConfig.csrConfig.channelBondingMode5GHz =
1290 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1291 }
1292 else if ( channel == 48 || channel == 64 || channel == 112 ||
1293 channel == 128 || channel == 161 )
1294 {
1295 smeConfig.csrConfig.channelBondingMode5GHz =
1296 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1297 }
1298 else
1299 {
1300 smeConfig.csrConfig.channelBondingMode5GHz=0;
1301 }
1302 }
1303#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001304 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1305 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301306 {
1307 if ( channel== 40 || channel == 48 || channel == 56 ||
1308 channel == 64 || channel == 104 || channel == 112 ||
1309 channel == 120 || channel == 128 || channel == 136 ||
1310 channel == 144 || channel == 153 || channel == 161 )
1311 {
1312 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1313 }
1314 else if ( channel== 36 || channel == 44 || channel == 52 ||
1315 channel == 60 || channel == 100 || channel == 108 ||
1316 channel == 116 || channel == 124 || channel == 132 ||
1317 channel == 140 || channel == 149 || channel == 157 )
1318 {
1319 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1320 }
1321 else
1322 {
1323 smeConfig.csrConfig.channelBondingMode5GHz=0;
1324 }
1325 }
1326 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1327
1328 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1329 return VOS_STATUS_SUCCESS;
1330}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001331
Jeff Johnson295189b2012-06-20 16:38:30 -07001332#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1333static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1334 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001335#else
1336static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1337 struct cfg80211_beacon_data *params,
1338 const u8 *ssid, size_t ssid_len,
1339 enum nl80211_hidden_ssid hidden_ssid)
1340#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001341{
1342 tsap_Config_t *pConfig;
1343 beacon_data_t *pBeacon = NULL;
1344 struct ieee80211_mgmt *pMgmt_frame;
1345 v_U8_t *pIe=NULL;
1346 v_U16_t capab_info;
1347 eCsrAuthType RSNAuthType;
1348 eCsrEncryptionType RSNEncryptType;
1349 eCsrEncryptionType mcRSNEncryptType;
1350 int status = VOS_STATUS_SUCCESS;
1351 tpWLAN_SAPEventCB pSapEventCallback;
1352 hdd_hostapd_state_t *pHostapdState;
1353 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1354 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1355 struct qc_mac_acl_entry *acl_entry = NULL;
1356 v_SINT_t i;
1357
1358 ENTER();
1359
1360 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1361
1362 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1363
1364 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1365
1366 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1367
1368 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1369
1370 //channel is already set in the set_channel Call back
1371 //pConfig->channel = pCommitConfig->channel;
1372
1373 /*Protection parameter to enable or disable*/
1374 pConfig->protEnabled =
1375 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1376
1377 pConfig->dtim_period = pBeacon->dtim_period;
1378
1379 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1380 pConfig->dtim_period);
1381
1382
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001383 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001384 {
1385 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001386 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001387 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001388 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001389 tANI_BOOLEAN restartNeeded;
1390 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1391 pConfig->ieee80211d = 1;
1392 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1393 sme_setRegInfo(hHal, pConfig->countryCode);
1394 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1395 /*
1396 * If auto channel is configured i.e. channel is 0,
1397 * so skip channel validation.
1398 */
1399 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001400 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001401 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1402 {
1403 hddLog(VOS_TRACE_LEVEL_ERROR,
1404 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1405 return -EINVAL;
1406 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001407 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001408 /*
1409 * Validate the given channel range for the given country code
1410 */
1411 else
1412 {
1413 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1414 WLANSAP_SetChannelRange(hHal,hdd_pConfig->apStartChannelNum,hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1415 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001416 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001417 else
1418 {
1419 pConfig->ieee80211d = 0;
1420 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001421 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001422 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001423 {
1424 pConfig->ieee80211d = 0;
1425 }
1426 pConfig->authType = eSAP_AUTO_SWITCH;
1427
1428 capab_info = pMgmt_frame->u.beacon.capab_info;
1429
1430 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1431 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1432
1433 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1434
1435 /*Set wps station to configured*/
1436 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1437
1438 if(pIe)
1439 {
1440 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1441 {
1442 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1443 return -EINVAL;
1444 }
1445 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1446 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001447 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001448 /* Check 15 bit of WPS IE as it contain information for wps state
1449 * WPS state
1450 */
1451 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1452 {
1453 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1454 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1455 {
1456 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1457 }
1458 }
1459 }
1460 else
1461 {
1462 pConfig->wps_state = SAP_WPS_DISABLED;
1463 }
1464 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1465
1466 pConfig->RSNWPAReqIELength = 0;
1467 pConfig->pRSNWPAReqIE = NULL;
1468 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1469 WLAN_EID_RSN);
1470 if(pIe && pIe[1])
1471 {
1472 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1473 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1474 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1475 /* The actual processing may eventually be more extensive than
1476 * this. Right now, just consume any PMKIDs that are sent in
1477 * by the app.
1478 * */
1479 status = hdd_softap_unpackIE(
1480 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1481 &RSNEncryptType,
1482 &mcRSNEncryptType,
1483 &RSNAuthType,
1484 pConfig->pRSNWPAReqIE[1]+2,
1485 pConfig->pRSNWPAReqIE );
1486
1487 if( VOS_STATUS_SUCCESS == status )
1488 {
1489 /* Now copy over all the security attributes you have
1490 * parsed out
1491 * */
1492 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1493 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1494 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1495 = RSNEncryptType;
1496 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1497 "EncryptionType = %d mcEncryptionType = %d\n"),
1498 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1499 }
1500 }
1501
1502 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1503 pBeacon->tail, pBeacon->tail_len);
1504
1505 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1506 {
1507 if (pConfig->pRSNWPAReqIE)
1508 {
1509 /*Mixed mode WPA/WPA2*/
1510 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1511 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1512 }
1513 else
1514 {
1515 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1516 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1517 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1518 status = hdd_softap_unpackIE(
1519 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1520 &RSNEncryptType,
1521 &mcRSNEncryptType,
1522 &RSNAuthType,
1523 pConfig->pRSNWPAReqIE[1]+2,
1524 pConfig->pRSNWPAReqIE );
1525
1526 if( VOS_STATUS_SUCCESS == status )
1527 {
1528 /* Now copy over all the security attributes you have
1529 * parsed out
1530 * */
1531 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1532 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1533 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1534 = RSNEncryptType;
1535 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1536 "EncryptionType = %d mcEncryptionType = %d\n"),
1537 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1538 }
1539 }
1540 }
1541
1542 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1543
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001544#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001545 if (params->ssid != NULL)
1546 {
1547 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1548 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1549 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1550 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1551 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001552#else
1553 if (ssid != NULL)
1554 {
1555 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1556 pConfig->SSIDinfo.ssid.length = ssid_len;
1557 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1558 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1559 }
1560#endif
1561
Jeff Johnson295189b2012-06-20 16:38:30 -07001562 vos_mem_copy(pConfig->self_macaddr.bytes,
1563 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1564
1565 /* default value */
1566 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1567 pConfig->num_accept_mac = 0;
1568 pConfig->num_deny_mac = 0;
1569
1570 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1571 pBeacon->tail, pBeacon->tail_len);
1572
1573 /* pIe for black list is following form:
1574 type : 1 byte
1575 length : 1 byte
1576 OUI : 4 bytes
1577 acl type : 1 byte
1578 no of mac addr in black list: 1 byte
1579 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1580 */
1581 if ((pIe != NULL) && (pIe[1] != 0))
1582 {
1583 pConfig->SapMacaddr_acl = pIe[6];
1584 pConfig->num_deny_mac = pIe[7];
1585 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1586 pIe[6], pIe[7]);
1587 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1588 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1589 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1590 for (i = 0; i < pConfig->num_deny_mac; i++)
1591 {
1592 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1593 acl_entry++;
1594 }
1595 }
1596 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1597 pBeacon->tail, pBeacon->tail_len);
1598
1599 /* pIe for white list is following form:
1600 type : 1 byte
1601 length : 1 byte
1602 OUI : 4 bytes
1603 acl type : 1 byte
1604 no of mac addr in white list: 1 byte
1605 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1606 */
1607 if ((pIe != NULL) && (pIe[1] != 0))
1608 {
1609 pConfig->SapMacaddr_acl = pIe[6];
1610 pConfig->num_accept_mac = pIe[7];
1611 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1612 pIe[6], pIe[7]);
1613 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1614 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1615 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1616 for (i = 0; i < pConfig->num_accept_mac; i++)
1617 {
1618 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1619 acl_entry++;
1620 }
1621 }
1622 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1623
Jeff Johnsone7245742012-09-05 17:12:55 -07001624#ifdef WLAN_FEATURE_11AC
1625 if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1626 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1627 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) )
1628 {
1629 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1630 }
1631#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301632
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001633 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1634 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001635 // ht_capab is not what the name conveys,this is used for protection bitmap
1636 pConfig->ht_capab =
1637 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1638
1639 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1640 {
1641 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1642 return -EINVAL;
1643 }
1644
1645 //Uapsd Enabled Bit
1646 pConfig->UapsdEnable =
1647 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1648 //Enable OBSS protection
1649 pConfig->obssProtEnabled =
1650 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1651
1652 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1653 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1654 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1655 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1656 (int)pConfig->channel);
1657 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1658 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1659 pConfig->authType);
1660 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1661 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1662 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1663 pConfig->protEnabled, pConfig->obssProtEnabled);
1664
1665 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1666 {
1667 //Bss already started. just return.
1668 //TODO Probably it should update some beacon params.
1669 hddLog( LOGE, "Bss Already started...Ignore the request");
1670 EXIT();
1671 return 0;
1672 }
1673
1674 pConfig->persona = pHostapdAdapter->device_mode;
1675
1676 pSapEventCallback = hdd_hostapd_SAPEventCB;
1677 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1678 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1679 {
1680 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1681 return -EINVAL;
1682 }
1683
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001684 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001685 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1686
1687 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1688
1689 if (!VOS_IS_STATUS_SUCCESS(status))
1690 {
1691 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1692 ("ERROR: HDD vos wait for single_event failed!!\n"));
1693 VOS_ASSERT(0);
1694 }
1695
1696 //Succesfully started Bss update the state bit.
1697 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1698
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001699#ifdef WLAN_FEATURE_P2P_DEBUG
1700 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1701 {
1702 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1703 {
1704 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1705 hddLog(LOGE,"[P2P State] From Go nego completed to "
1706 "Non-autonomus Group started");
1707 }
1708 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1709 {
1710 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1711 hddLog(LOGE,"[P2P State] From Inactive to "
1712 "Autonomus Group started");
1713 }
1714 }
1715#endif
1716
Jeff Johnson295189b2012-06-20 16:38:30 -07001717 pHostapdState->bCommit = TRUE;
1718 EXIT();
1719
1720 return 0;
1721}
1722
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001723#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001724static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1725 struct net_device *dev,
1726 struct beacon_parameters *params)
1727{
1728 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1729 int status=VOS_STATUS_SUCCESS;
1730
1731 ENTER();
1732
1733 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1734
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001735 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1736 {
1737 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1738 "%s:LOGP in Progress. Ignore!!!", __func__);
1739 return -EAGAIN;
1740 }
1741
Jeff Johnson295189b2012-06-20 16:38:30 -07001742 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1743#ifdef WLAN_FEATURE_P2P
1744 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1745#endif
1746 )
1747 {
1748 beacon_data_t *old,*new;
1749
1750 old = pAdapter->sessionCtx.ap.beacon;
1751
1752 if (old)
1753 return -EALREADY;
1754
1755 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1756
1757 if(status != VOS_STATUS_SUCCESS)
1758 {
1759 hddLog(VOS_TRACE_LEVEL_FATAL,
1760 "%s:Error!!! Allocating the new beacon\n",__func__);
1761 return -EINVAL;
1762 }
1763
1764 pAdapter->sessionCtx.ap.beacon = new;
1765
1766 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1767 }
1768
1769 EXIT();
1770 return status;
1771}
1772
1773static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1774 struct net_device *dev,
1775 struct beacon_parameters *params)
1776{
1777 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1778 int status=VOS_STATUS_SUCCESS;
1779
1780 ENTER();
1781
1782 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1783 __func__,pAdapter->device_mode);
1784
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001785 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1786 {
1787 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1788 "%s:LOGP in Progress. Ignore!!!", __func__);
1789 return -EAGAIN;
1790 }
1791
Jeff Johnson295189b2012-06-20 16:38:30 -07001792 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1793#ifdef WLAN_FEATURE_P2P
1794 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1795#endif
1796 )
1797 {
1798 beacon_data_t *old,*new;
1799
1800 old = pAdapter->sessionCtx.ap.beacon;
1801
1802 if (!old)
1803 return -ENOENT;
1804
1805 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1806
1807 if(status != VOS_STATUS_SUCCESS) {
1808 hddLog(VOS_TRACE_LEVEL_FATAL,
1809 "%s: Error!!! Allocating the new beacon\n",__func__);
1810 return -EINVAL;
1811 }
1812
1813 pAdapter->sessionCtx.ap.beacon = new;
1814
1815 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1816 }
1817
1818 EXIT();
1819 return status;
1820}
1821
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001822#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1823
1824#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001825static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1826 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001827#else
1828static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1829 struct net_device *dev)
1830#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001831{
1832 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001833 hdd_context_t *pHddCtx = NULL;
1834 hdd_scaninfo_t *pScanInfo = NULL;
1835 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001836 VOS_STATUS status = 0;
1837
1838 ENTER();
1839
1840 if (NULL == pAdapter)
1841 {
1842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001843 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001844 return -ENODEV;
1845 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001846 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1847 {
1848 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1849 "%s:LOGP in Progress. Ignore!!!", __func__);
1850 return -EAGAIN;
1851 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001852
1853 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1854 if (NULL == pHddCtx)
1855 {
1856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001857 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001858 return -ENODEV;
1859 }
1860
1861 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1862 if (NULL == staAdapter)
1863 {
1864 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1865 if (NULL == staAdapter)
1866 {
1867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001868 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001869 return -ENODEV;
1870 }
1871 }
1872
1873 pScanInfo = &pHddCtx->scan_info;
1874
Jeff Johnson295189b2012-06-20 16:38:30 -07001875 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1876 {
1877 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1878 return -EAGAIN;
1879 }
1880
1881 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1882
1883 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1884 __func__,pAdapter->device_mode);
1885
Jeff Johnsone7245742012-09-05 17:12:55 -07001886 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1887 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001888 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001889 hdd_abort_mac_scan(staAdapter->pHddCtx);
1890 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001891 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07001892 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1893 if (!status)
1894 {
1895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1896 "%s: Timeout occured while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001897 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001898 VOS_ASSERT(pScanInfo->mScanPending);
1899 return 0;
1900 }
1901 }
1902
Jeff Johnson295189b2012-06-20 16:38:30 -07001903 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1904#ifdef WLAN_FEATURE_P2P
1905 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1906#endif
1907 )
1908 {
1909 beacon_data_t *old;
1910
1911 old = pAdapter->sessionCtx.ap.beacon;
1912
1913 if (!old)
1914 return -ENOENT;
1915
1916#ifdef CONFIG_CFG80211
1917 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1918#endif
1919
1920 mutex_lock(&pHddCtx->sap_lock);
1921 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1922 {
1923 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
1924 {
1925 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
1926
1927 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1928
1929 if (!VOS_IS_STATUS_SUCCESS(status))
1930 {
1931 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1932 ("ERROR: HDD vos wait for single_event failed!!\n"));
1933 VOS_ASSERT(0);
1934 }
1935 }
1936 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
1937 }
1938 mutex_unlock(&pHddCtx->sap_lock);
1939
1940 if(status != VOS_STATUS_SUCCESS)
1941 {
1942 hddLog(VOS_TRACE_LEVEL_FATAL,
1943 "%s:Error!!! Stopping the BSS\n",__func__);
1944 return -EINVAL;
1945 }
1946
1947 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1948 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
1949 ==eHAL_STATUS_FAILURE)
1950 {
1951 hddLog(LOGE,
1952 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
1953 }
1954
1955 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1956 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1957 eANI_BOOLEAN_FALSE) )
1958 {
1959 hddLog(LOGE,
1960 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1961 }
1962
1963 // Reset WNI_CFG_PROBE_RSP Flags
1964 wlan_hdd_reset_prob_rspies(pAdapter);
1965
1966 pAdapter->sessionCtx.ap.beacon = NULL;
1967 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001968#ifdef WLAN_FEATURE_P2P_DEBUG
1969 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
1970 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
1971 {
1972 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
1973 "GO got removed");
1974 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
1975 }
1976#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001977 }
1978 EXIT();
1979 return status;
1980}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001981
1982#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
1983
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05301984static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
1985 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001986 struct cfg80211_ap_settings *params)
1987{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05301988 hdd_adapter_t *pAdapter;
1989 hdd_context_t *pHddCtx;
1990 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001991
1992 ENTER();
1993
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05301994 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001995 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05301996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1997 "%s: Device is Null", __func__);
1998 return -ENODEV;
1999 }
2000
2001 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2002 if (NULL == pAdapter)
2003 {
2004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2005 "%s: HDD adapter is Null", __func__);
2006 return -ENODEV;
2007 }
2008
2009 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2010 {
2011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2012 "%s: HDD adapter magic is invalid", __func__);
2013 return -ENODEV;
2014 }
2015
2016 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2017 if (NULL == pHddCtx)
2018 {
2019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2020 "%s: HDD context is Null", __func__);
2021 return -ENODEV;
2022 }
2023
2024 if (pHddCtx->isLogpInProgress)
2025 {
2026 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2027 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002028 return -EAGAIN;
2029 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302030
2031 if (pHddCtx->isLoadUnloadInProgress)
2032 {
2033 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2034 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2035 return -EAGAIN;
2036 }
2037
2038 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2039 __func__, pAdapter->device_mode);
2040
2041 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002042#ifdef WLAN_FEATURE_P2P
2043 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2044#endif
2045 )
2046 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302047 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002048
2049 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302050
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002051 if (old)
2052 return -EALREADY;
2053
2054 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2055
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302056 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002057 {
2058 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302059 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002060 return -EINVAL;
2061 }
2062 pAdapter->sessionCtx.ap.beacon = new;
2063 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2064 params->ssid_len, params->hidden_ssid);
2065 }
2066
2067 EXIT();
2068 return status;
2069}
2070
2071
2072static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2073 struct net_device *dev,
2074 struct cfg80211_beacon_data *params)
2075{
2076 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2077 int status=VOS_STATUS_SUCCESS;
2078
2079 ENTER();
2080
2081 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2082 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002083 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2084 {
2085 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2086 return -EAGAIN;
2087 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002088
2089 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2090#ifdef WLAN_FEATURE_P2P
2091 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2092#endif
2093 )
2094 {
2095 beacon_data_t *old,*new;
2096
2097 old = pAdapter->sessionCtx.ap.beacon;
2098
2099 if (!old)
2100 return -ENOENT;
2101
2102 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2103
2104 if(status != VOS_STATUS_SUCCESS) {
2105 hddLog(VOS_TRACE_LEVEL_FATAL,
2106 "%s: Error!!! Allocating the new beacon\n",__func__);
2107 return -EINVAL;
2108 }
2109
2110 pAdapter->sessionCtx.ap.beacon = new;
2111
2112 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2113 }
2114
2115 EXIT();
2116 return status;
2117}
2118
2119#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2120
Jeff Johnson295189b2012-06-20 16:38:30 -07002121
2122static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2123 struct net_device *dev,
2124 struct bss_parameters *params)
2125{
2126 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2127
2128 ENTER();
2129
2130 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2131 __func__,pAdapter->device_mode);
2132
2133 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2134#ifdef WLAN_FEATURE_P2P
2135 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2136#endif
2137 )
2138 {
2139 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2140 * want to update this parameter */
2141 if (-1 != params->ap_isolate)
2142 {
2143 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2144 }
2145 }
2146
2147 EXIT();
2148 return 0;
2149}
2150
2151/*
2152 * FUNCTION: wlan_hdd_cfg80211_change_iface
2153 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2154 */
2155int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2156 struct net_device *ndev,
2157 enum nl80211_iftype type,
2158 u32 *flags,
2159 struct vif_params *params
2160 )
2161{
2162 struct wireless_dev *wdev;
2163 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2164 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002165 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002166 tCsrRoamProfile *pRoamProfile = NULL;
2167 eCsrRoamBssType LastBSSType;
2168 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2169 eMib_dot11DesiredBssType connectedBssType;
2170 VOS_STATUS status;
2171
2172 ENTER();
2173
2174 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2175 {
2176 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2177 return -EAGAIN;
2178 }
2179
2180 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2181 __func__, pAdapter->device_mode);
2182
2183 wdev = ndev->ieee80211_ptr;
2184
2185#ifdef WLAN_BTAMP_FEATURE
2186 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2187 (NL80211_IFTYPE_ADHOC == type)||
2188 (NL80211_IFTYPE_AP == type)||
2189 (NL80211_IFTYPE_P2P_GO == type))
2190 {
2191 pHddCtx->isAmpAllowed = VOS_FALSE;
2192 // stop AMP traffic
2193 status = WLANBAP_StopAmp();
2194 if(VOS_STATUS_SUCCESS != status )
2195 {
2196 pHddCtx->isAmpAllowed = VOS_TRUE;
2197 hddLog(VOS_TRACE_LEVEL_FATAL,
2198 "%s: Failed to stop AMP", __func__);
2199 return -EINVAL;
2200 }
2201 }
2202#endif //WLAN_BTAMP_FEATURE
2203 /* Reset the current device mode bit mask*/
2204 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2205
2206 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2207#ifdef WLAN_FEATURE_P2P
2208 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002209 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002210#endif
2211 )
2212 {
2213 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2214 pRoamProfile = &pWextState->roamProfile;
2215 LastBSSType = pRoamProfile->BSSType;
2216
2217 switch (type)
2218 {
2219 case NL80211_IFTYPE_STATION:
2220#ifdef WLAN_FEATURE_P2P
2221 case NL80211_IFTYPE_P2P_CLIENT:
2222#endif
2223 hddLog(VOS_TRACE_LEVEL_INFO,
2224 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2225 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002226#ifdef WLAN_FEATURE_11AC
2227 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2228 {
2229 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2230 }
2231#endif
2232 pRoamProfile->phyMode =
2233 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002234 wdev->iftype = type;
2235#ifdef WLAN_FEATURE_P2P
2236 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2237 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2238#endif
2239 break;
2240 case NL80211_IFTYPE_ADHOC:
2241 hddLog(VOS_TRACE_LEVEL_INFO,
2242 "%s: setting interface Type to ADHOC", __func__);
2243 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2244 pRoamProfile->phyMode =
2245 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2246 wdev->iftype = type;
2247 break;
2248
2249 case NL80211_IFTYPE_AP:
2250#ifdef WLAN_FEATURE_P2P
2251 case NL80211_IFTYPE_P2P_GO:
2252#endif
2253 {
2254 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2255 "%s: setting interface Type to %s", __func__,
2256 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2257
Mohit Khanna0f232092012-09-11 14:46:08 -07002258 if (NL80211_IFTYPE_AP == type)
2259 {
2260 /* As Loading WLAN Driver one interface being created for p2p device
2261 * address. This will take one HW STA and the max number of clients
2262 * that can connect to softAP will be reduced by one. so while changing
2263 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2264 * interface as it is not required in SoftAP mode.
2265 */
2266
2267 // Get P2P Adapter
2268 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2269
2270 if (pP2pAdapter)
2271 {
2272 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2273 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2274 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2275 }
2276 }
2277
Jeff Johnson295189b2012-06-20 16:38:30 -07002278 //De-init the adapter.
2279 hdd_stop_adapter( pHddCtx, pAdapter );
2280 hdd_deinit_adapter( pHddCtx, pAdapter );
2281 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2282#ifdef WLAN_SOFTAP_FEATURE
2283#ifdef WLAN_FEATURE_P2P
2284 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2285 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2286#else
2287 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2288#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002289
2290 //Disable BMPS and IMPS if enabled
2291 //before starting Go
2292 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2293 {
2294 if(VOS_STATUS_E_FAILURE ==
2295 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2296 {
2297 //Fail to Exit BMPS
2298 VOS_ASSERT(0);
2299 }
2300 }
2301
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002302 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2303 (pConfig->apRandomBssidEnabled))
2304 {
2305 /* To meet Android requirements create a randomized
2306 MAC address of the form 02:1A:11:Fx:xx:xx */
2307 get_random_bytes(&ndev->dev_addr[3], 3);
2308 ndev->dev_addr[0] = 0x02;
2309 ndev->dev_addr[1] = 0x1A;
2310 ndev->dev_addr[2] = 0x11;
2311 ndev->dev_addr[3] |= 0xF0;
2312 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2313 VOS_MAC_ADDR_SIZE);
2314 pr_info("wlan: Generated HotSpot BSSID "
2315 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2316 ndev->dev_addr[0],
2317 ndev->dev_addr[1],
2318 ndev->dev_addr[2],
2319 ndev->dev_addr[3],
2320 ndev->dev_addr[4],
2321 ndev->dev_addr[5]);
2322 }
2323
Jeff Johnson295189b2012-06-20 16:38:30 -07002324 hdd_set_ap_ops( pAdapter->dev );
2325
2326 status = hdd_init_ap_mode(pAdapter);
2327 if(status != VOS_STATUS_SUCCESS)
2328 {
2329 hddLog(VOS_TRACE_LEVEL_FATAL,
2330 "%s: Error initializing the ap mode", __func__);
2331 return -EINVAL;
2332 }
2333 hdd_set_conparam(1);
2334
2335#endif
2336 /*interface type changed update in wiphy structure*/
2337 if(wdev)
2338 {
2339 wdev->iftype = type;
2340 pHddCtx->change_iface = type;
2341 }
2342 else
2343 {
2344 hddLog(VOS_TRACE_LEVEL_ERROR,
2345 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2346 return -EINVAL;
2347 }
2348 goto done;
2349 }
2350
2351 default:
2352 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2353 __func__);
2354 return -EOPNOTSUPP;
2355 }
2356 }
2357 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2358#ifdef WLAN_FEATURE_P2P
2359 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2360#endif
2361 )
2362 {
2363 switch(type)
2364 {
2365 case NL80211_IFTYPE_STATION:
2366#ifdef WLAN_FEATURE_P2P
2367 case NL80211_IFTYPE_P2P_CLIENT:
2368#endif
2369 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002370 hdd_stop_adapter( pHddCtx, pAdapter );
2371 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002372 wdev->iftype = type;
2373#ifdef WLAN_FEATURE_P2P
2374 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2375 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2376#endif
2377 hdd_set_conparam(0);
2378 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002379 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2380 hdd_set_station_ops( pAdapter->dev );
2381 status = hdd_init_station_mode( pAdapter );
2382 if( VOS_STATUS_SUCCESS != status )
2383 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002384 /* In case of JB, for P2P-GO, only change interface will be called,
2385 * This is the right place to enable back bmps_imps()
2386 */
2387 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002388 goto done;
2389 case NL80211_IFTYPE_AP:
2390#ifdef WLAN_FEATURE_P2P
2391 case NL80211_IFTYPE_P2P_GO:
2392#endif
2393 wdev->iftype = type;
2394#ifdef WLAN_FEATURE_P2P
2395 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2396 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2397#endif
2398 goto done;
2399 default:
2400 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2401 __func__);
2402 return -EOPNOTSUPP;
2403
2404 }
2405
2406 }
2407 else
2408 {
2409 return -EOPNOTSUPP;
2410 }
2411
2412
2413 if(pRoamProfile)
2414 {
2415 if ( LastBSSType != pRoamProfile->BSSType )
2416 {
2417 /*interface type changed update in wiphy structure*/
2418 wdev->iftype = type;
2419
2420 /*the BSS mode changed, We need to issue disconnect
2421 if connected or in IBSS disconnect state*/
2422 if ( hdd_connGetConnectedBssType(
2423 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2424 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2425 {
2426 /*need to issue a disconnect to CSR.*/
2427 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2428 if( eHAL_STATUS_SUCCESS ==
2429 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2430 pAdapter->sessionId,
2431 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2432 {
2433 wait_for_completion_interruptible_timeout(
2434 &pAdapter->disconnect_comp_var,
2435 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2436 }
2437 }
2438 }
2439 }
2440
2441done:
2442 /*set bitmask based on updated value*/
2443 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2444#ifdef WLAN_BTAMP_FEATURE
2445 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2446 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2447 {
2448 //we are ok to do AMP
2449 pHddCtx->isAmpAllowed = VOS_TRUE;
2450 }
2451#endif //WLAN_BTAMP_FEATURE
2452 EXIT();
2453 return 0;
2454}
2455
2456static int wlan_hdd_change_station(struct wiphy *wiphy,
2457 struct net_device *dev,
2458 u8 *mac,
2459 struct station_parameters *params)
2460{
2461 VOS_STATUS status = VOS_STATUS_SUCCESS;
2462 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2463 v_MACADDR_t STAMacAddress;
2464
Jeff Johnsone7245742012-09-05 17:12:55 -07002465 ENTER();
2466
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002467 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2468 {
2469 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2470 "%s:LOGP in Progress. Ignore!!!", __func__);
2471 return -EAGAIN;
2472 }
2473
Jeff Johnson295189b2012-06-20 16:38:30 -07002474 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2475
2476 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2477#ifdef WLAN_FEATURE_P2P
2478 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2479#endif
2480 )
2481 {
2482 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2483 {
2484 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2485 WLANTL_STA_AUTHENTICATED);
2486
2487 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002488 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002489 return -EINVAL;
2490 }
2491 }
2492
Jeff Johnsone7245742012-09-05 17:12:55 -07002493 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002494 return status;
2495}
2496
2497/*
2498 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2499 * This function is used to get peer station index in IBSS mode
2500 */
2501static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2502{
2503 u8 idx = 0;
2504 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2505 ENTER();
2506 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2507 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2508 {
2509 if ( (0 !=
2510 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2511 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2512 temp, VOS_MAC_ADDR_SIZE)
2513 )
2514 {
2515 return idx;
2516 }
2517 }
2518 return idx;
2519}
2520
2521
2522/*
2523 * FUNCTION: wlan_hdd_cfg80211_add_key
2524 * This function is used to initialize the key information
2525 */
2526#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2527static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2528 struct net_device *ndev,
2529 u8 key_index, bool pairwise,
2530 const u8 *mac_addr,
2531 struct key_params *params
2532 )
2533#else
2534static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2535 struct net_device *ndev,
2536 u8 key_index, const u8 *mac_addr,
2537 struct key_params *params
2538 )
2539#endif
2540{
2541 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2542 tCsrRoamSetKey setKey;
2543 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2544 int status = 0;
2545 v_U32_t roamId= 0xFF;
2546 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2547 hdd_hostapd_state_t *pHostapdState;
2548 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002549 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002550
2551 ENTER();
2552
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002553 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2554 {
2555 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2556 "%s:LOGP in Progress. Ignore!!!", __func__);
2557 return -EAGAIN;
2558 }
2559
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2561 __func__,pAdapter->device_mode);
2562
2563 if (CSR_MAX_NUM_KEY <= key_index)
2564 {
2565 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2566 key_index);
2567
2568 return -EINVAL;
2569 }
2570
2571 hddLog(VOS_TRACE_LEVEL_INFO,
2572 "%s: called with key index = %d & key length %d",
2573 __func__, key_index, params->key_len);
2574
2575 /*extract key idx, key len and key*/
2576 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2577 setKey.keyId = key_index;
2578 setKey.keyLength = params->key_len;
2579 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2580
2581 switch (params->cipher)
2582 {
2583 case WLAN_CIPHER_SUITE_WEP40:
2584 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2585 break;
2586
2587 case WLAN_CIPHER_SUITE_WEP104:
2588 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2589 break;
2590
2591 case WLAN_CIPHER_SUITE_TKIP:
2592 {
2593 u8 *pKey = &setKey.Key[0];
2594 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2595
2596 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2597
2598 /*Supplicant sends the 32bytes key in this order
2599
2600 |--------------|----------|----------|
2601 | Tk1 |TX-MIC | RX Mic |
2602 |--------------|----------|----------|
2603 <---16bytes---><--8bytes--><--8bytes-->
2604
2605 */
2606 /*Sme expects the 32 bytes key to be in the below order
2607
2608 |--------------|----------|----------|
2609 | Tk1 |RX-MIC | TX Mic |
2610 |--------------|----------|----------|
2611 <---16bytes---><--8bytes--><--8bytes-->
2612 */
2613 /* Copy the Temporal Key 1 (TK1) */
2614 vos_mem_copy(pKey, params->key,16);
2615
2616 /*Copy the rx mic first*/
2617 vos_mem_copy(&pKey[16],&params->key[24],8);
2618
2619 /*Copy the tx mic */
2620 vos_mem_copy(&pKey[24],&params->key[16],8);
2621
2622
2623 break;
2624 }
2625
2626 case WLAN_CIPHER_SUITE_CCMP:
2627 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2628 break;
2629
2630#ifdef FEATURE_WLAN_WAPI
2631 case WLAN_CIPHER_SUITE_SMS4:
2632 {
2633 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2634 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2635 params->key, params->key_len);
2636 return 0;
2637 }
2638#endif
2639#ifdef FEATURE_WLAN_CCX
2640 case WLAN_CIPHER_SUITE_KRK:
2641 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2642 break;
2643#endif
2644 default:
2645 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2646 __func__, params->cipher);
2647 return -EOPNOTSUPP;
2648 }
2649
2650 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2651 __func__, setKey.encType);
2652
2653
2654
2655 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2656#ifdef WLAN_FEATURE_P2P
2657 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2658#endif
2659 )
2660 {
2661
2662
2663 if (
2664#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2665 (!pairwise)
2666#else
2667 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2668#endif
2669 )
2670 {
2671 /* set group key*/
2672 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2673 "%s- %d: setting Broacast key",
2674 __func__, __LINE__);
2675 setKey.keyDirection = eSIR_RX_ONLY;
2676 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2677 }
2678 else
2679 {
2680 /* set pairwise key*/
2681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2682 "%s- %d: setting pairwise key",
2683 __func__, __LINE__);
2684 setKey.keyDirection = eSIR_TX_RX;
2685 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2686 }
2687
2688 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2689 if( pHostapdState->bssState == BSS_START )
2690 {
2691 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2692
2693 if ( status != eHAL_STATUS_SUCCESS )
2694 {
2695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2696 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2697 __LINE__, status );
2698 }
2699 }
2700
2701 /* Saving WEP keys */
2702 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2703 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2704 {
2705 //Save the wep key in ap context. Issue setkey after the BSS is started.
2706 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2707 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2708 }
2709 else
2710 {
2711 //Save the key in ap context. Issue setkey after the BSS is started.
2712 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2713 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2714 }
2715 }
2716 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2717#ifdef WLAN_FEATURE_P2P
2718 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2719#endif
2720 )
2721 {
2722 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2723 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2724
2725 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2726
2727 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2728 params->key, params->key_len);
2729
2730 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2731
2732 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2733 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2734 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2735 )
2736 &&
2737 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2738 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2739 )
2740 )
2741 {
2742 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2743 * interface, copy bssid for pairwise key and group macaddr for
2744 * group key initialization*/
2745
2746 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2747
2748 pWextState->roamProfile.negotiatedUCEncryptionType =
2749 pHddStaCtx->conn_info.ucEncryptionType =
2750 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2751 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2752 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2753
2754
2755 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2756 "%s: Negotiated encryption type %d", __func__,
2757 pWextState->roamProfile.negotiatedUCEncryptionType);
2758
2759 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2760 &pWextState->roamProfile, true);
2761 setKey.keyLength = 0;
2762 setKey.keyDirection = eSIR_TX_RX;
2763
2764#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2765 if (pairwise)
2766 {
2767#endif
2768 if (mac_addr)
2769 {
2770 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2771 }
2772 else
2773 {
2774 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2775 * and peerMacAddress in case of IBSS*/
2776 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2777 {
2778 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2779 if (HDD_MAX_NUM_IBSS_STA != staidx)
2780 {
2781 vos_mem_copy(setKey.peerMac,
2782 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2783 WNI_CFG_BSSID_LEN);
2784
2785 }
2786 else
2787 {
2788 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2789 __func__);
2790 return -EOPNOTSUPP;
2791 }
2792 }
2793 else
2794 {
2795 vos_mem_copy(setKey.peerMac,
2796 &pHddStaCtx->conn_info.bssId[0],
2797 WNI_CFG_BSSID_LEN);
2798 }
2799 }
2800#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2801 }
2802 else
2803 {
2804 /* set group key*/
2805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2806 "%s- %d: setting Group key",
2807 __func__, __LINE__);
2808 setKey.keyDirection = eSIR_RX_ONLY;
2809 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2810 }
2811#endif
2812 }
2813 else if (
2814#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2815 (!pairwise)
2816#else
2817 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2818#endif
2819 )
2820 {
2821 /* set group key*/
2822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2823 "%s- %d: setting Group key",
2824 __func__, __LINE__);
2825 setKey.keyDirection = eSIR_RX_ONLY;
2826 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2827 }
2828 else
2829 {
2830 /* set pairwise key*/
2831 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2832 "%s- %d: setting pairwise key",
2833 __func__, __LINE__);
2834 setKey.keyDirection = eSIR_TX_RX;
2835 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2836 }
2837
2838 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2839 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2840 __func__, setKey.peerMac[0], setKey.peerMac[1],
2841 setKey.peerMac[2], setKey.peerMac[3],
2842 setKey.peerMac[4], setKey.peerMac[5],
2843 setKey.keyDirection);
2844
2845 vos_status = wlan_hdd_check_ula_done(pAdapter);
2846
2847 if ( vos_status != VOS_STATUS_SUCCESS )
2848 {
2849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2850 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2851 __LINE__, vos_status );
2852
2853 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2854
2855 return -EINVAL;
2856
2857 }
2858
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002859#ifdef WLAN_FEATURE_VOWIFI_11R
2860 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2861 Save the key in the UMAC and include it in the ADD BSS request */
2862 /*TODO 11r - is this used?? */
2863 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2864 if( halStatus == eHAL_STATUS_SUCCESS )
2865 {
2866 return halStatus;
2867 }
2868#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002869
2870 /* issue set key request to SME*/
2871 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2872 pAdapter->sessionId, &setKey, &roamId );
2873
2874 if ( 0 != status )
2875 {
2876 hddLog(VOS_TRACE_LEVEL_ERROR,
2877 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2878 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2879 return -EINVAL;
2880 }
2881
2882
2883 /* in case of IBSS as there was no information available about WEP keys during
2884 * IBSS join, group key intialized with NULL key, so re-initialize group key
2885 * with correct value*/
2886 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2887 !( ( IW_AUTH_KEY_MGMT_802_1X
2888 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2889 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2890 )
2891 &&
2892 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2893 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2894 )
2895 )
2896 {
2897 setKey.keyDirection = eSIR_RX_ONLY;
2898 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2899
2900 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2901 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2902 __func__, setKey.peerMac[0], setKey.peerMac[1],
2903 setKey.peerMac[2], setKey.peerMac[3],
2904 setKey.peerMac[4], setKey.peerMac[5],
2905 setKey.keyDirection);
2906
2907 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2908 pAdapter->sessionId, &setKey, &roamId );
2909
2910 if ( 0 != status )
2911 {
2912 hddLog(VOS_TRACE_LEVEL_ERROR,
2913 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
2914 __func__, status);
2915 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2916 return -EINVAL;
2917 }
2918 }
2919 }
2920
2921 return 0;
2922}
2923
2924/*
2925 * FUNCTION: wlan_hdd_cfg80211_get_key
2926 * This function is used to get the key information
2927 */
2928#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2929static int wlan_hdd_cfg80211_get_key(
2930 struct wiphy *wiphy,
2931 struct net_device *ndev,
2932 u8 key_index, bool pairwise,
2933 const u8 *mac_addr, void *cookie,
2934 void (*callback)(void *cookie, struct key_params*)
2935 )
2936#else
2937static int wlan_hdd_cfg80211_get_key(
2938 struct wiphy *wiphy,
2939 struct net_device *ndev,
2940 u8 key_index, const u8 *mac_addr, void *cookie,
2941 void (*callback)(void *cookie, struct key_params*)
2942 )
2943#endif
2944{
2945 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2946 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2947 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
2948 struct key_params params;
2949
2950 ENTER();
2951
2952 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2953 __func__,pAdapter->device_mode);
2954
2955 memset(&params, 0, sizeof(params));
2956
2957 if (CSR_MAX_NUM_KEY <= key_index)
2958 {
2959 return -EINVAL;
2960 }
2961
2962 switch(pRoamProfile->EncryptionType.encryptionType[0])
2963 {
2964 case eCSR_ENCRYPT_TYPE_NONE:
2965 params.cipher = IW_AUTH_CIPHER_NONE;
2966 break;
2967
2968 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
2969 case eCSR_ENCRYPT_TYPE_WEP40:
2970 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2971 break;
2972
2973 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
2974 case eCSR_ENCRYPT_TYPE_WEP104:
2975 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2976 break;
2977
2978 case eCSR_ENCRYPT_TYPE_TKIP:
2979 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2980 break;
2981
2982 case eCSR_ENCRYPT_TYPE_AES:
2983 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2984 break;
2985
2986 default:
2987 params.cipher = IW_AUTH_CIPHER_NONE;
2988 break;
2989 }
2990
2991 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
2992 params.seq_len = 0;
2993 params.seq = NULL;
2994 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
2995 callback(cookie, &params);
2996 return 0;
2997}
2998
2999/*
3000 * FUNCTION: wlan_hdd_cfg80211_del_key
3001 * This function is used to delete the key information
3002 */
3003#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3004static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3005 struct net_device *ndev,
3006 u8 key_index,
3007 bool pairwise,
3008 const u8 *mac_addr
3009 )
3010#else
3011static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3012 struct net_device *ndev,
3013 u8 key_index,
3014 const u8 *mac_addr
3015 )
3016#endif
3017{
3018 int status = 0;
3019
3020 //This code needs to be revisited. There is sme_removeKey API, we should
3021 //plan to use that. After the change to use correct index in setkey,
3022 //it is observed that this is invalidating peer
3023 //key index whenever re-key is done. This is affecting data link.
3024 //It should be ok to ignore del_key.
3025#if 0
3026 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3027 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3028 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3029 tCsrRoamSetKey setKey;
3030 v_U32_t roamId= 0xFF;
3031
3032 ENTER();
3033
3034 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3035 __func__,pAdapter->device_mode);
3036
3037 if (CSR_MAX_NUM_KEY <= key_index)
3038 {
3039 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3040 key_index);
3041
3042 return -EINVAL;
3043 }
3044
3045 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3046 setKey.keyId = key_index;
3047
3048 if (mac_addr)
3049 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3050 else
3051 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3052
3053 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3054
3055 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3056#ifdef WLAN_FEATURE_P2P
3057 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3058#endif
3059 )
3060 {
3061
3062 hdd_hostapd_state_t *pHostapdState =
3063 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3064 if( pHostapdState->bssState == BSS_START)
3065 {
3066 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3067
3068 if ( status != eHAL_STATUS_SUCCESS )
3069 {
3070 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3071 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3072 __LINE__, status );
3073 }
3074 }
3075 }
3076 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3077#ifdef WLAN_FEATURE_P2P
3078 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3079#endif
3080 )
3081 {
3082 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3083
3084 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3085
3086 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3087 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3088 __func__, setKey.peerMac[0], setKey.peerMac[1],
3089 setKey.peerMac[2], setKey.peerMac[3],
3090 setKey.peerMac[4], setKey.peerMac[5]);
3091 if(pAdapter->sessionCtx.station.conn_info.connState ==
3092 eConnectionState_Associated)
3093 {
3094 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3095 pAdapter->sessionId, &setKey, &roamId );
3096
3097 if ( 0 != status )
3098 {
3099 hddLog(VOS_TRACE_LEVEL_ERROR,
3100 "%s: sme_RoamSetKey failure, returned %d",
3101 __func__, status);
3102 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3103 return -EINVAL;
3104 }
3105 }
3106 }
3107#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003108 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003109 return status;
3110}
3111
3112/*
3113 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3114 * This function is used to set the default tx key index
3115 */
3116#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3117static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3118 struct net_device *ndev,
3119 u8 key_index,
3120 bool unicast, bool multicast)
3121#else
3122static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3123 struct net_device *ndev,
3124 u8 key_index)
3125#endif
3126{
3127 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3128 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3129 int status = 0;
3130 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3131
3132 ENTER();
3133
3134 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3135 __func__,pAdapter->device_mode, key_index);
3136
3137 if (CSR_MAX_NUM_KEY <= key_index)
3138 {
3139 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3140 key_index);
3141
3142 return -EINVAL;
3143 }
3144
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003145 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3146 {
3147 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3148 "%s:LOGP in Progress. Ignore!!!", __func__);
3149 return -EAGAIN;
3150 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003151
3152 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3153#ifdef WLAN_FEATURE_P2P
3154 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3155#endif
3156 )
3157 {
3158 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3159 (eCSR_ENCRYPT_TYPE_TKIP !=
3160 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3161 (eCSR_ENCRYPT_TYPE_AES !=
3162 pWextState->roamProfile.EncryptionType.encryptionType[0])
3163 )
3164 {
3165 /* if default key index is not same as previous one,
3166 * then update the default key index */
3167
3168 tCsrRoamSetKey setKey;
3169 v_U32_t roamId= 0xFF;
3170 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3171
3172 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3173 __func__, key_index);
3174
3175 Keys->defaultIndex = (u8)key_index;
3176 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3177 setKey.keyId = key_index;
3178 setKey.keyLength = Keys->KeyLength[key_index];
3179
3180 vos_mem_copy(&setKey.Key[0],
3181 &Keys->KeyMaterial[key_index][0],
3182 Keys->KeyLength[key_index]);
3183
3184 setKey.keyDirection = eSIR_TX_ONLY;
3185
3186 vos_mem_copy(setKey.peerMac,
3187 &pHddStaCtx->conn_info.bssId[0],
3188 WNI_CFG_BSSID_LEN);
3189
3190 setKey.encType =
3191 pWextState->roamProfile.EncryptionType.encryptionType[0];
3192
3193 /* issue set key request */
3194 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3195 pAdapter->sessionId, &setKey, &roamId );
3196
3197 if ( 0 != status )
3198 {
3199 hddLog(VOS_TRACE_LEVEL_ERROR,
3200 "%s: sme_RoamSetKey failed, returned %d", __func__,
3201 status);
3202 return -EINVAL;
3203 }
3204 }
3205 }
3206
3207 /* In SoftAp mode setting key direction for default mode */
3208 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3209 {
3210 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3211 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3212 (eCSR_ENCRYPT_TYPE_AES !=
3213 pWextState->roamProfile.EncryptionType.encryptionType[0])
3214 )
3215 {
3216 /* Saving key direction for default key index to TX default */
3217 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3218 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3219 }
3220 }
3221
3222 return status;
3223}
3224
3225/**
3226 * FUNCTION: wlan_hdd_cfg80211_set_channel
3227 * This function is used to set the channel number
3228 */
3229int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3230 struct ieee80211_channel *chan,
3231 enum nl80211_channel_type channel_type
3232 )
3233{
3234 v_U32_t num_ch = 0;
3235 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003236 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003237 int freq = chan->center_freq; /* freq is in MHZ */
3238
3239 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003240
3241 if( NULL == dev )
3242 {
3243 hddLog(VOS_TRACE_LEVEL_ERROR,
3244 "%s: Called with dev = NULL.\n", __func__);
3245 return -ENODEV;
3246 }
3247 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003248
3249 hddLog(VOS_TRACE_LEVEL_INFO,
3250 "%s: device_mode = %d freq = %d \n",__func__,
3251 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003252 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3253 {
3254 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3255 return -EAGAIN;
3256 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003257
3258 /*
3259 * Do freq to chan conversion
3260 * TODO: for 11a
3261 */
3262
3263 channel = ieee80211_frequency_to_channel(freq);
3264
3265 /* Check freq range */
3266 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3267 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3268 {
3269 hddLog(VOS_TRACE_LEVEL_ERROR,
3270 "%s: Channel [%d] is outside valid range from %d to %d\n",
3271 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3272 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3273 return -EINVAL;
3274 }
3275
3276 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3277
3278 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3279#ifdef WLAN_FEATURE_P2P
3280 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3281#endif
3282 )
3283 {
3284 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3285 {
3286 hddLog(VOS_TRACE_LEVEL_ERROR,
3287 "%s: Invalid Channel [%d] \n", __func__, channel);
3288 return -EINVAL;
3289 }
3290 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3291 "%s: set channel to [%d] for device mode =%d",
3292 __func__, channel,pAdapter->device_mode);
3293 }
3294 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3295#ifdef WLAN_FEATURE_P2P
3296 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3297#endif
3298 )
3299 {
3300 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3301 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3302 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3303
3304 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3305 {
3306 /* Link is up then return cant set channel*/
3307 hddLog( VOS_TRACE_LEVEL_ERROR,
3308 "%s: IBSS Associated, can't set the channel\n", __func__);
3309 return -EINVAL;
3310 }
3311
3312 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3313 pHddStaCtx->conn_info.operationChannel = channel;
3314 pRoamProfile->ChannelInfo.ChannelList =
3315 &pHddStaCtx->conn_info.operationChannel;
3316 }
3317 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3318#ifdef WLAN_FEATURE_P2P
3319 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3320#endif
3321 )
3322 {
3323 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3324
3325 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3326 {
3327 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3328
3329 /* If auto channel selection is configured as enable/ 1 then ignore
3330 channel set by supplicant
3331 */
3332 if ( cfg_param->apAutoChannelSelection )
3333 {
3334 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3335
3336 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3337 "%s: set channel to auto channel (0) for device mode =%d",
3338 __func__, pAdapter->device_mode);
3339 }
3340 }
3341 }
3342 else
3343 {
3344 hddLog(VOS_TRACE_LEVEL_FATAL,
3345 "%s: Invalid device mode failed to set valid channel", __func__);
3346 return -EINVAL;
3347 }
3348 EXIT();
3349 return 0;
3350}
3351
3352
3353
3354/*
3355 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3356 * This function is used to inform the BSS details to nl80211 interface.
3357 */
3358static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3359 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3360{
3361 struct net_device *dev = pAdapter->dev;
3362 struct wireless_dev *wdev = dev->ieee80211_ptr;
3363 struct wiphy *wiphy = wdev->wiphy;
3364 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3365 int chan_no;
3366 int ie_length;
3367 const char *ie;
3368 unsigned int freq;
3369 struct ieee80211_channel *chan;
3370 int rssi = 0;
3371 struct cfg80211_bss *bss = NULL;
3372
3373 ENTER();
3374
3375 if( NULL == pBssDesc )
3376 {
3377 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3378 return bss;
3379 }
3380
3381 chan_no = pBssDesc->channelId;
3382 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3383 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3384
3385 if( NULL == ie )
3386 {
3387 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3388 return bss;
3389 }
3390
3391#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3392 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3393 {
3394 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3395 }
3396 else
3397 {
3398 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3399 }
3400#else
3401 freq = ieee80211_channel_to_frequency(chan_no);
3402#endif
3403
3404 chan = __ieee80211_get_channel(wiphy, freq);
3405
3406 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3407 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3408 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3409 if (bss == NULL)
3410 {
3411 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3412
3413 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3414 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3415 pBssDesc->capabilityInfo,
3416 pBssDesc->beaconInterval, ie, ie_length,
3417 rssi, GFP_KERNEL ));
3418}
3419 else
3420 {
3421 return bss;
3422 }
3423}
3424
3425
3426
3427/*
3428 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3429 * This function is used to inform the BSS details to nl80211 interface.
3430 */
3431struct cfg80211_bss*
3432wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3433 tSirBssDescription *bss_desc
3434 )
3435{
3436 /*
3437 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3438 already exists in bss data base of cfg80211 for that particular BSS ID.
3439 Using cfg80211_inform_bss_frame to update the bss entry instead of
3440 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3441 now there is no possibility to get the mgmt(probe response) frame from PE,
3442 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3443 cfg80211_inform_bss_frame.
3444 */
3445 struct net_device *dev = pAdapter->dev;
3446 struct wireless_dev *wdev = dev->ieee80211_ptr;
3447 struct wiphy *wiphy = wdev->wiphy;
3448 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003449#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3450 qcom_ie_age *qie_age = NULL;
3451 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3452#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003453 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003454#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003455 const char *ie =
3456 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3457 unsigned int freq;
3458 struct ieee80211_channel *chan;
3459 struct ieee80211_mgmt *mgmt =
3460 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3461 struct cfg80211_bss *bss_status = NULL;
3462 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3463 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003464#ifdef WLAN_OPEN_SOURCE
3465 struct timespec ts;
3466#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003467
3468 ENTER();
3469
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003470 if (!mgmt)
3471 return NULL;
3472
Jeff Johnson295189b2012-06-20 16:38:30 -07003473 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003474
3475#ifdef WLAN_OPEN_SOURCE
3476 /* Android does not want the timestamp from the frame.
3477 Instead it wants a monotonic increasing value */
3478 get_monotonic_boottime(&ts);
3479 mgmt->u.probe_resp.timestamp =
3480 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3481#else
3482 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003483 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3484 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003485
3486#endif
3487
Jeff Johnson295189b2012-06-20 16:38:30 -07003488 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3489 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003490
3491#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3492 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3493 /* Assuming this is the last IE, copy at the end */
3494 ie_length -=sizeof(qcom_ie_age);
3495 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3496 qie_age->element_id = QCOM_VENDOR_IE_ID;
3497 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3498 qie_age->oui_1 = QCOM_OUI1;
3499 qie_age->oui_2 = QCOM_OUI2;
3500 qie_age->oui_3 = QCOM_OUI3;
3501 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3502 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3503#endif
3504
Jeff Johnson295189b2012-06-20 16:38:30 -07003505 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3506
3507 mgmt->frame_control |=
3508 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3509
3510#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3511 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3512 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3513 {
3514 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3515 }
3516 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3517 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3518
3519 {
3520 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3521 }
3522 else
3523 {
3524 kfree(mgmt);
3525 return NULL;
3526 }
3527#else
3528 freq = ieee80211_channel_to_frequency(chan_no);
3529#endif
3530 chan = __ieee80211_get_channel(wiphy, freq);
3531
3532 /*To keep the rssi icon of the connected AP in the scan window
3533 *and the rssi icon of the wireless networks in sync
3534 * */
3535 if (( eConnectionState_Associated ==
3536 pAdapter->sessionCtx.station.conn_info.connState ) &&
3537 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3538 pAdapter->sessionCtx.station.conn_info.bssId,
3539 WNI_CFG_BSSID_LEN)))
3540 {
3541 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3542 rssi = (pAdapter->rssi * 100);
3543 }
3544 else
3545 {
3546 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3547 }
3548
3549 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3550 frame_len, rssi, GFP_KERNEL);
3551 kfree(mgmt);
3552 return bss_status;
3553}
3554
3555/*
3556 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3557 * This function is used to update the BSS data base of CFG8011
3558 */
3559struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3560 tCsrRoamInfo *pRoamInfo
3561 )
3562{
3563 tCsrRoamConnectedProfile roamProfile;
3564 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3565 struct cfg80211_bss *bss = NULL;
3566
3567 ENTER();
3568
3569 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3570 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3571
3572 if (NULL != roamProfile.pBssDesc)
3573 {
3574 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3575 &roamProfile);
3576
3577 if (NULL == bss)
3578 {
3579 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3580 __func__);
3581 }
3582
3583 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3584 }
3585 else
3586 {
3587 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3588 __func__);
3589 }
3590 return bss;
3591}
3592
3593/*
3594 * FUNCTION: wlan_hdd_cfg80211_update_bss
3595 */
3596static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3597 hdd_adapter_t *pAdapter
3598 )
3599{
3600 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3601 tCsrScanResultInfo *pScanResult;
3602 eHalStatus status = 0;
3603 tScanResultHandle pResult;
3604 struct cfg80211_bss *bss_status = NULL;
3605
3606 ENTER();
3607
3608 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3609 {
3610 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3611 return -EAGAIN;
3612 }
3613
3614 /*
3615 * start getting scan results and populate cgf80211 BSS database
3616 */
3617 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3618
3619 /* no scan results */
3620 if (NULL == pResult)
3621 {
3622 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3623 return status;
3624 }
3625
3626 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3627
3628 while (pScanResult)
3629 {
3630 /*
3631 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3632 * entry already exists in bss data base of cfg80211 for that
3633 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3634 * bss entry instead of cfg80211_inform_bss, But this call expects
3635 * mgmt packet as input. As of now there is no possibility to get
3636 * the mgmt(probe response) frame from PE, converting bss_desc to
3637 * ieee80211_mgmt(probe response) and passing to c
3638 * fg80211_inform_bss_frame.
3639 * */
3640
3641 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3642 &pScanResult->BssDescriptor);
3643
3644
3645 if (NULL == bss_status)
3646 {
3647 hddLog(VOS_TRACE_LEVEL_INFO,
3648 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3649 }
3650 else
3651 {
3652 cfg80211_put_bss(bss_status);
3653 }
3654
3655 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3656 }
3657
3658 sme_ScanResultPurge(hHal, pResult);
3659
3660 return 0;
3661}
3662
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003663void
3664hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3665{
3666 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003667 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3668 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3669 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003670} /****** end hddPrintMacAddr() ******/
3671
3672void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003673hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003674{
3675 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003676 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3677 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3678 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3679 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003680} /****** end hddPrintPmkId() ******/
3681
3682//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3683//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3684
3685//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3686//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3687
3688#define dump_bssid(bssid) \
3689 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003690 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3691 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3692 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003693 }
3694
3695#define dump_pmkid(pMac, pmkid) \
3696 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003697 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3698 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3699 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003700 }
3701
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003702#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003703/*
3704 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3705 * This function is used to notify the supplicant of a new PMKSA candidate.
3706 */
3707int wlan_hdd_cfg80211_pmksa_candidate_notify(
3708 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3709 int index, bool preauth )
3710{
Jeff Johnsone7245742012-09-05 17:12:55 -07003711#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003712 struct net_device *dev = pAdapter->dev;
3713
3714 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003715 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003716
3717 if( NULL == pRoamInfo )
3718 {
3719 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3720 return -EINVAL;
3721 }
3722
3723 dump_bssid(pRoamInfo->bssid);
3724 cfg80211_pmksa_candidate_notify(dev, index,
3725 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003726#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003727 return 0;
3728}
3729#endif //FEATURE_WLAN_LFR
3730
Jeff Johnson295189b2012-06-20 16:38:30 -07003731/*
3732 * FUNCTION: hdd_cfg80211_scan_done_callback
3733 * scanning callback function, called after finishing scan
3734 *
3735 */
3736static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3737 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3738{
3739 struct net_device *dev = (struct net_device *) pContext;
3740 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3741 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003742 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3743 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003744 struct cfg80211_scan_request *req = NULL;
3745 int ret = 0;
3746
3747 ENTER();
3748
3749 hddLog(VOS_TRACE_LEVEL_INFO,
3750 "%s called with halHandle = %p, pContext = %p,"
3751 "scanID = %d, returned status = %d\n",
3752 __func__, halHandle, pContext, (int) scanId, (int) status);
3753
3754 //Block on scan req completion variable. Can't wait forever though.
3755 ret = wait_for_completion_interruptible_timeout(
3756 &pScanInfo->scan_req_completion_event,
3757 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3758 if (!ret)
3759 {
3760 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003761 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003762 }
3763
3764 if(pScanInfo->mScanPending != VOS_TRUE)
3765 {
3766 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003767 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003768 }
3769
3770 /* Check the scanId */
3771 if (pScanInfo->scanId != scanId)
3772 {
3773 hddLog(VOS_TRACE_LEVEL_INFO,
3774 "%s called with mismatched scanId pScanInfo->scanId = %d "
3775 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3776 (int) scanId);
3777 }
3778
Jeff Johnson295189b2012-06-20 16:38:30 -07003779 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3780 pAdapter);
3781
3782 if (0 > ret)
3783 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3784
3785
3786 /* If any client wait scan result through WEXT
3787 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003788 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003789 {
3790 /* The other scan request waiting for current scan finish
3791 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003792 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003793 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003794 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003795 }
3796 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003797 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003798 {
3799 struct net_device *dev = pAdapter->dev;
3800 union iwreq_data wrqu;
3801 int we_event;
3802 char *msg;
3803
3804 memset(&wrqu, '\0', sizeof(wrqu));
3805 we_event = SIOCGIWSCAN;
3806 msg = NULL;
3807 wireless_send_event(dev, we_event, &wrqu, msg);
3808 }
3809 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003810 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003811
3812 /* Get the Scan Req */
3813 req = pAdapter->request;
3814
3815 if (!req)
3816 {
3817 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003818 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003819 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003820 }
3821
3822 /*
3823 * setting up 0, just in case.
3824 */
3825 req->n_ssids = 0;
3826 req->n_channels = 0;
3827 req->ie = 0;
3828
Jeff Johnson295189b2012-06-20 16:38:30 -07003829 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003830 /* Scan is no longer pending */
3831 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003832
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003833 /*
3834 * cfg80211_scan_done informing NL80211 about completion
3835 * of scanning
3836 */
3837 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003838 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003839
Jeff Johnsone7245742012-09-05 17:12:55 -07003840allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003841 /* release the wake lock at the end of the scan*/
3842 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003843
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003844 /* Acquire wakelock to handle the case where APP's tries to suspend
3845 * immediatly after the driver gets connect request(i.e after scan)
3846 * from supplicant, this result in app's is suspending and not able
3847 * to process the connect request to AP */
3848 hdd_allow_suspend_timeout(100);
3849
Jeff Johnson295189b2012-06-20 16:38:30 -07003850 EXIT();
3851 return 0;
3852}
3853
3854/*
3855 * FUNCTION: wlan_hdd_cfg80211_scan
3856 * this scan respond to scan trigger and update cfg80211 scan database
3857 * later, scan dump command can be used to recieve scan results
3858 */
3859int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3860 struct cfg80211_scan_request *request)
3861{
3862 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3863 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3864 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3865 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3866 tCsrScanRequest scanRequest;
3867 tANI_U8 *channelList = NULL, i;
3868 v_U32_t scanId = 0;
3869 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003870 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003871#ifdef WLAN_FEATURE_P2P
3872 v_U8_t* pP2pIe = NULL;
3873#endif
3874
3875 ENTER();
3876
3877 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3878 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003879
3880 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
3881 (eConnectionState_Connecting ==
3882 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
3883 {
3884 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08003885 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
3886 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003887 return -EBUSY;
3888 }
3889
Jeff Johnson295189b2012-06-20 16:38:30 -07003890#ifdef WLAN_BTAMP_FEATURE
3891 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003892 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07003893 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003894 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 "%s: No scanning when AMP is on", __func__);
3896 return -EOPNOTSUPP;
3897 }
3898#endif
3899 //Scan on any other interface is not supported.
3900 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
3901 {
3902 hddLog(VOS_TRACE_LEVEL_ERROR,
3903 "%s: Not scanning on device_mode = %d",
3904 __func__, pAdapter->device_mode);
3905 return -EOPNOTSUPP;
3906 }
3907
3908 if (TRUE == pScanInfo->mScanPending)
3909 {
3910 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
3911 return -EBUSY;
3912 }
3913
3914 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3915 {
3916 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3917 "%s:LOGP in Progress. Ignore!!!", __func__);
3918 return -EAGAIN;
3919 }
3920
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07003921 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
3922 {
3923 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3924 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
3925 return -EAGAIN;
3926 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07003927 //Don't Allow Scan and return busy if Remain On
3928 //Channel and action frame is pending
3929 //Otherwise Cancel Remain On Channel and allow Scan
3930 //If no action frame pending
3931 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
3932 {
3933 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
3934 return -EBUSY;
3935 }
3936
Jeff Johnson295189b2012-06-20 16:38:30 -07003937 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
3938 {
3939 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
3940 "%s: Aquire lock fail", __func__);
3941 return -EAGAIN;
3942 }
3943 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
3944 {
3945 hddLog(VOS_TRACE_LEVEL_WARN,
3946 "%s: MAX TM Level Scan not allowed", __func__);
3947 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3948 return -EBUSY;
3949 }
3950 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3951
3952 vos_mem_zero( &scanRequest, sizeof(scanRequest));
3953
3954 if (NULL != request)
3955 {
3956 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
3957 (int)request->n_ssids);
3958
3959 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
3960 * Becasue of this, driver is assuming that this is not wildcard scan and so
3961 * is not aging out the scan results.
3962 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07003963 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07003964 {
3965 request->n_ssids = 0;
3966 }
3967
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003968 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07003969 {
3970 tCsrSSIDInfo *SsidInfo;
3971 int j;
3972 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
3973 /* Allocate num_ssid tCsrSSIDInfo structure */
3974 SsidInfo = scanRequest.SSIDs.SSIDList =
3975 ( tCsrSSIDInfo *)vos_mem_malloc(
3976 request->n_ssids*sizeof(tCsrSSIDInfo));
3977
3978 if(NULL == scanRequest.SSIDs.SSIDList)
3979 {
3980 hddLog(VOS_TRACE_LEVEL_ERROR,
3981 "memory alloc failed SSIDInfo buffer");
3982 return -ENOMEM;
3983 }
3984
3985 /* copy all the ssid's and their length */
3986 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
3987 {
3988 /* get the ssid length */
3989 SsidInfo->SSID.length = request->ssids[j].ssid_len;
3990 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
3991 SsidInfo->SSID.length);
3992 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
3993 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
3994 j, SsidInfo->SSID.ssId);
3995 }
3996 /* set the scan type to active */
3997 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3998 }
3999 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4000 {
4001 /* set the scan type to active */
4002 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4003 }
4004 else
4005 {
4006 /*Set the scan type to default type, in this case it is ACTIVE*/
4007 scanRequest.scanType = pScanInfo->scan_mode;
4008 }
4009 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4010 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4011 }
4012 else
4013 {
4014 /* set the scan type to active */
4015 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4016 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4017
4018 /* set min and max channel time to zero */
4019 scanRequest.minChnTime = 0;
4020 scanRequest.maxChnTime = 0;
4021 }
4022
4023 /* set BSSType to default type */
4024 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4025
4026 /*TODO: scan the requested channels only*/
4027
4028 /*Right now scanning all the channels */
4029 if( request )
4030 {
4031 if( request->n_channels )
4032 {
4033 channelList = vos_mem_malloc( request->n_channels );
4034 if( NULL == channelList )
4035 {
4036 status = -ENOMEM;
4037 goto free_mem;
4038 }
4039
4040 for( i = 0 ; i < request->n_channels ; i++ )
4041 channelList[i] = request->channels[i]->hw_value;
4042 }
4043
4044 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4045 scanRequest.ChannelInfo.ChannelList = channelList;
4046
4047 /* set requestType to full scan */
4048 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004049
4050 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4051 * search (Flush on both full scan and social scan but not on single
4052 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4053 */
4054
4055 /* Supplicant does single channel scan after 8-way handshake
4056 * and in that case driver shoudnt flush scan results. If
4057 * driver flushes the scan results here and unfortunately if
4058 * the AP doesnt respond to our probe req then association
4059 * fails which is not desired
4060 */
4061
4062 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4063 {
4064 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4065 pAdapter->sessionId );
4066 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004067
4068 if( request->ie_len )
4069 {
4070 /* save this for future association (join requires this) */
4071 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4072 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4073 pScanInfo->scanAddIE.length = request->ie_len;
4074
4075 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004076 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4077 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004078 )
4079 {
4080 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4081 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4082 }
4083
4084 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4085 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4086
4087#ifdef WLAN_FEATURE_P2P
4088 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4089 request->ie_len);
4090 if (pP2pIe != NULL)
4091 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004092#ifdef WLAN_FEATURE_P2P_DEBUG
4093 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4094 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4095 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4096 {
4097 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4098 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4099 "Go nego completed to Connection is started");
4100 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4101 "for 8way Handshake");
4102 }
4103 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4104 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4105 {
4106 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4107 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4108 "Disconnected state to Connection is started");
4109 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4110 "for 4way Handshake");
4111 }
4112#endif
4113
Jeff Johnsone7245742012-09-05 17:12:55 -07004114 /* no_cck will be set during p2p find to disable 11b rates */
4115 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004116 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004117 hddLog(VOS_TRACE_LEVEL_INFO,
4118 "%s: This is a P2P Search", __func__);
4119 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004120
Jeff Johnsone7245742012-09-05 17:12:55 -07004121 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4122 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004123 /* set requestType to P2P Discovery */
4124 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004125 }
4126
4127 /*
4128 Skip Dfs Channel in case of P2P Search
4129 if it is set in ini file
4130 */
4131 if(cfg_param->skipDfsChnlInP2pSearch)
4132 {
4133 scanRequest.skipDfsChnlInP2pSearch = 1;
4134 }
4135 else
4136 {
4137 scanRequest.skipDfsChnlInP2pSearch = 0;
4138 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004139
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 }
4141 }
4142#endif
4143 }
4144 }
4145
4146 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4147
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004148 /* acquire the wakelock to avoid the apps suspend during the scan. To
4149 * address the following issues.
4150 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4151 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4152 * for long time, this result in apps running at full power for long time.
4153 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4154 * be stuck in full power because of resume BMPS
4155 */
4156 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004157
4158 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004159 pAdapter->sessionId, &scanRequest, &scanId,
4160 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004161
Jeff Johnson295189b2012-06-20 16:38:30 -07004162 if (eHAL_STATUS_SUCCESS != status)
4163 {
4164 hddLog(VOS_TRACE_LEVEL_ERROR,
4165 "%s: sme_ScanRequest returned error %d", __func__, status);
4166 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004167 if(eHAL_STATUS_RESOURCES == status)
4168 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004169 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 -07004170 status = -EBUSY;
4171 } else {
4172 status = -EIO;
4173 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004174 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004175 goto free_mem;
4176 }
4177
4178 pScanInfo->mScanPending = TRUE;
4179 pAdapter->request = request;
4180 pScanInfo->scanId = scanId;
4181
4182 complete(&pScanInfo->scan_req_completion_event);
4183
4184free_mem:
4185 if( scanRequest.SSIDs.SSIDList )
4186 {
4187 vos_mem_free(scanRequest.SSIDs.SSIDList);
4188 }
4189
4190 if( channelList )
4191 vos_mem_free( channelList );
4192
4193 EXIT();
4194
4195 return status;
4196}
4197
4198/*
4199 * FUNCTION: wlan_hdd_cfg80211_connect_start
4200 * This function is used to start the association process
4201 */
4202int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004203 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004204{
4205 int status = 0;
4206 hdd_wext_state_t *pWextState;
4207 v_U32_t roamId;
4208 tCsrRoamProfile *pRoamProfile;
4209 eMib_dot11DesiredBssType connectedBssType;
4210 eCsrAuthType RSNAuthType;
4211
4212 ENTER();
4213
4214 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4215
4216 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4217 {
4218 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4219 return -EINVAL;
4220 }
4221
4222 pRoamProfile = &pWextState->roamProfile;
4223
4224 if (pRoamProfile)
4225 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004226 int ret = 0;
4227 hdd_station_ctx_t *pHddStaCtx;
4228 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4229 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4230
4231 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4232 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4233 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004234 {
4235 /* Issue disconnect to CSR */
4236 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4237 if( eHAL_STATUS_SUCCESS ==
4238 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4239 pAdapter->sessionId,
4240 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4241 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004242 ret = wait_for_completion_interruptible_timeout(
4243 &pAdapter->disconnect_comp_var,
4244 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4245 if (0 == ret)
4246 {
4247 VOS_ASSERT(0);
4248 }
4249 }
4250 }
4251 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4252 {
4253 ret = wait_for_completion_interruptible_timeout(
4254 &pAdapter->disconnect_comp_var,
4255 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4256 if (0 == ret)
4257 {
4258 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004259 }
4260 }
4261
4262 if (HDD_WMM_USER_MODE_NO_QOS ==
4263 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4264 {
4265 /*QoS not enabled in cfg file*/
4266 pRoamProfile->uapsd_mask = 0;
4267 }
4268 else
4269 {
4270 /*QoS enabled, update uapsd mask from cfg file*/
4271 pRoamProfile->uapsd_mask =
4272 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4273 }
4274
4275 pRoamProfile->SSIDs.numOfSSIDs = 1;
4276 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4277 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4278 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4279 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4280 ssid, ssid_len);
4281
4282 if (bssid)
4283 {
4284 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4285 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4286 WNI_CFG_BSSID_LEN);
4287 /* Save BSSID in seperate variable as well, as RoamProfile
4288 BSSID is getting zeroed out in the association process. And in
4289 case of join failure we should send valid BSSID to supplicant
4290 */
4291 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4292 WNI_CFG_BSSID_LEN);
4293 }
4294
4295 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4296 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4297 {
4298 /*set gen ie*/
4299 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4300 /*set auth*/
4301 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4302 }
4303 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4304 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4305 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4306 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4307 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4308 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4309 )
4310 {
4311 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4312 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4313 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4314 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4315 eCSR_AUTH_TYPE_AUTOSWITCH;
4316 pWextState->roamProfile.AuthType.authType[0] =
4317 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4318 }
4319#ifdef FEATURE_WLAN_WAPI
4320 if (pAdapter->wapi_info.nWapiMode)
4321 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004322 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004323 switch (pAdapter->wapi_info.wapiAuthMode)
4324 {
4325 case WAPI_AUTH_MODE_PSK:
4326 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004327 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004328 pAdapter->wapi_info.wapiAuthMode);
4329 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4330 break;
4331 }
4332 case WAPI_AUTH_MODE_CERT:
4333 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004334 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004335 pAdapter->wapi_info.wapiAuthMode);
4336 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4337 break;
4338 }
4339 } // End of switch
4340 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4341 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4342 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004343 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004344 pRoamProfile->AuthType.numEntries = 1;
4345 pRoamProfile->EncryptionType.numEntries = 1;
4346 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4347 pRoamProfile->mcEncryptionType.numEntries = 1;
4348 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4349 }
4350 }
4351#endif /* FEATURE_WLAN_WAPI */
4352 pRoamProfile->csrPersona = pAdapter->device_mode;
4353
Jeff Johnson32d95a32012-09-10 13:15:23 -07004354 if( operatingChannel )
4355 {
4356 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4357 pRoamProfile->ChannelInfo.numOfChannels = 1;
4358 }
4359
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004360 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4361 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4362 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4363 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004364 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4365 */
4366 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4367 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4368 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004369
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4371 pAdapter->sessionId, pRoamProfile, &roamId);
4372
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004373 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304374 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4375
4376 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004377 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4378 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4379 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304380 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004381 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304382 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004383
4384 pRoamProfile->ChannelInfo.ChannelList = NULL;
4385 pRoamProfile->ChannelInfo.numOfChannels = 0;
4386
Jeff Johnson295189b2012-06-20 16:38:30 -07004387 }
4388 else
4389 {
4390 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4391 return -EINVAL;
4392 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004393 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004394 return status;
4395}
4396
4397/*
4398 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4399 * This function is used to set the authentication type (OPEN/SHARED).
4400 *
4401 */
4402static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4403 enum nl80211_auth_type auth_type)
4404{
4405 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4406 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4407
4408 ENTER();
4409
4410 /*set authentication type*/
4411 switch (auth_type)
4412 {
4413 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4414 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004415#ifdef WLAN_FEATURE_VOWIFI_11R
4416 case NL80211_AUTHTYPE_FT:
4417#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004418 hddLog(VOS_TRACE_LEVEL_INFO,
4419 "%s: set authentication type to OPEN", __func__);
4420 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4421 break;
4422
4423 case NL80211_AUTHTYPE_SHARED_KEY:
4424 hddLog(VOS_TRACE_LEVEL_INFO,
4425 "%s: set authentication type to SHARED", __func__);
4426 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4427 break;
4428#ifdef FEATURE_WLAN_CCX
4429 case NL80211_AUTHTYPE_NETWORK_EAP:
4430 hddLog(VOS_TRACE_LEVEL_INFO,
4431 "%s: set authentication type to CCKM WPA", __func__);
4432 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4433 break;
4434#endif
4435
4436
4437 default:
4438 hddLog(VOS_TRACE_LEVEL_ERROR,
4439 "%s: Unsupported authentication type %d", __func__,
4440 auth_type);
4441 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4442 return -EINVAL;
4443 }
4444
4445 pWextState->roamProfile.AuthType.authType[0] =
4446 pHddStaCtx->conn_info.authType;
4447 return 0;
4448}
4449
4450/*
4451 * FUNCTION: wlan_hdd_set_akm_suite
4452 * This function is used to set the key mgmt type(PSK/8021x).
4453 *
4454 */
4455static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4456 u32 key_mgmt
4457 )
4458{
4459 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4460 ENTER();
4461
4462 /*set key mgmt type*/
4463 switch(key_mgmt)
4464 {
4465 case WLAN_AKM_SUITE_PSK:
4466 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4467 __func__);
4468 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4469 break;
4470
4471 case WLAN_AKM_SUITE_8021X:
4472 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4473 __func__);
4474 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4475 break;
4476#ifdef FEATURE_WLAN_CCX
4477#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4478#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4479 case WLAN_AKM_SUITE_CCKM:
4480 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4481 __func__);
4482 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4483 break;
4484#endif
4485
4486 default:
4487 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4488 __func__, key_mgmt);
4489 return -EINVAL;
4490
4491 }
4492 return 0;
4493}
4494
4495/*
4496 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4497 * This function is used to set the encryption type
4498 * (NONE/WEP40/WEP104/TKIP/CCMP).
4499 */
4500static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4501 u32 cipher,
4502 bool ucast
4503 )
4504{
4505 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4506 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4507 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4508
4509 ENTER();
4510
4511 if (!cipher)
4512 {
4513 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4514 __func__, cipher);
4515 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4516 }
4517 else
4518 {
4519
4520 /*set encryption method*/
4521 switch (cipher)
4522 {
4523 case IW_AUTH_CIPHER_NONE:
4524 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4525 break;
4526
4527 case WLAN_CIPHER_SUITE_WEP40:
4528 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4529 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4530 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4531 else
4532 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4533 break;
4534
4535 case WLAN_CIPHER_SUITE_WEP104:
4536 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4537 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4538 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4539 else
4540 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4541 break;
4542
4543 case WLAN_CIPHER_SUITE_TKIP:
4544 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4545 break;
4546
4547 case WLAN_CIPHER_SUITE_CCMP:
4548 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4549 break;
4550#ifdef FEATURE_WLAN_WAPI
4551 case WLAN_CIPHER_SUITE_SMS4:
4552 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4553 break;
4554#endif
4555
4556#ifdef FEATURE_WLAN_CCX
4557 case WLAN_CIPHER_SUITE_KRK:
4558 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4559 break;
4560#endif
4561 default:
4562 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4563 __func__, cipher);
4564 return -EOPNOTSUPP;
4565 }
4566 }
4567
4568 if (ucast)
4569 {
4570 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4571 __func__, encryptionType);
4572 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4573 pWextState->roamProfile.EncryptionType.numEntries = 1;
4574 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4575 encryptionType;
4576 }
4577 else
4578 {
4579 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4580 __func__, encryptionType);
4581 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4582 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4583 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4584 }
4585
4586 return 0;
4587}
4588
4589
4590/*
4591 * FUNCTION: wlan_hdd_cfg80211_set_ie
4592 * This function is used to parse WPA/RSN IE's.
4593 */
4594int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4595 u8 *ie,
4596 size_t ie_len
4597 )
4598{
4599 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4600 u8 *genie = ie;
4601 v_U16_t remLen = ie_len;
4602#ifdef FEATURE_WLAN_WAPI
4603 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4604 u16 *tmp;
4605 v_U16_t akmsuiteCount;
4606 int *akmlist;
4607#endif
4608 ENTER();
4609
4610 /* clear previous assocAddIE */
4611 pWextState->assocAddIE.length = 0;
4612 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4613
4614 while (remLen >= 2)
4615 {
4616 v_U16_t eLen = 0;
4617 v_U8_t elementId;
4618 elementId = *genie++;
4619 eLen = *genie++;
4620 remLen -= 2;
4621
4622 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4623 __func__, elementId, eLen);
4624
4625 switch ( elementId )
4626 {
4627 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004628 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 -07004629 {
4630 hddLog(VOS_TRACE_LEVEL_ERROR,
4631 "%s: Invalid WPA IE", __func__);
4632 return -EINVAL;
4633 }
4634 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4635 {
4636 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4637 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4638 __func__, eLen + 2);
4639
4640 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4641 {
4642 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE. "
4643 "Need bigger buffer space\n");
4644 VOS_ASSERT(0);
4645 return -ENOMEM;
4646 }
4647 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4648 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4649 pWextState->assocAddIE.length += eLen + 2;
4650
4651 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4652 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4653 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4654 }
4655 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4656 {
4657 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4658 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4659 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4660 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4661 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4662 }
4663#ifdef WLAN_FEATURE_P2P
4664 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4665 P2P_OUI_TYPE_SIZE))
4666 /*Consider P2P IE, only for P2P Client */
4667 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4668 {
4669 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4670 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4671 __func__, eLen + 2);
4672
4673 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4674 {
4675 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4676 "Need bigger buffer space\n");
4677 VOS_ASSERT(0);
4678 return -ENOMEM;
4679 }
4680 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4681 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4682 pWextState->assocAddIE.length += eLen + 2;
4683
4684 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4685 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4686 }
4687#endif
4688#ifdef WLAN_FEATURE_WFD
4689 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4690 WFD_OUI_TYPE_SIZE))
4691 /*Consider WFD IE, only for P2P Client */
4692 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4693 {
4694 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4695 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4696 __func__, eLen + 2);
4697
4698 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4699 {
4700 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4701 "Need bigger buffer space\n");
4702 VOS_ASSERT(0);
4703 return -ENOMEM;
4704 }
4705 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4706 // WPS IE + P2P IE + WFD IE
4707 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4708 pWextState->assocAddIE.length += eLen + 2;
4709
4710 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4711 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4712 }
4713#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004714 /* Appending HS 2.0 Indication Element in Assiciation Request */
4715 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004716 HS20_OUI_TYPE_SIZE)) )
4717 {
4718 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4719 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4720 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004721
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004722 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4723 {
4724 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4725 "Need bigger buffer space\n");
4726 VOS_ASSERT(0);
4727 return -ENOMEM;
4728 }
4729 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4730 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004731
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004732 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4733 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4734 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004735
Jeff Johnson295189b2012-06-20 16:38:30 -07004736 break;
4737 case DOT11F_EID_RSN:
4738 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4739 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4740 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4741 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4742 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4743 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004744 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4745 case DOT11F_EID_EXTCAP:
4746 {
4747 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4748 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4749 __func__, eLen + 2);
4750
4751 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4752 {
4753 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4754 "Need bigger buffer space\n");
4755 VOS_ASSERT(0);
4756 return -ENOMEM;
4757 }
4758 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4759 pWextState->assocAddIE.length += eLen + 2;
4760
4761 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4762 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4763 break;
4764 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004765#ifdef FEATURE_WLAN_WAPI
4766 case WLAN_EID_WAPI:
4767 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4768 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4769 pAdapter->wapi_info.nWapiMode);
4770 tmp = (u16 *)ie;
4771 tmp = tmp + 2; // Skip element Id and Len, Version
4772 akmsuiteCount = WPA_GET_LE16(tmp);
4773 tmp = tmp + 1;
4774 akmlist = (int *)(tmp);
4775 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4776 {
4777 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4778 }
4779 else
4780 {
4781 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4782 VOS_ASSERT(0);
4783 return -EINVAL;
4784 }
4785
4786 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4787 {
4788 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004789 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004790 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4791 }
4792 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4793 {
4794 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004795 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004796 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4797 }
4798 break;
4799#endif
4800 default:
4801 hddLog (VOS_TRACE_LEVEL_ERROR,
4802 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004803 /* when Unknown IE is received we should break and continue
4804 * to the next IE in the buffer instead we were returning
4805 * so changing this to break */
4806 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004807 }
4808 genie += eLen;
4809 remLen -= eLen;
4810 }
4811 EXIT();
4812 return 0;
4813}
4814
4815/*
4816 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4817 * This function is used to initialize the security
4818 * parameters during connect operation.
4819 */
4820int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4821 struct cfg80211_connect_params *req
4822 )
4823{
4824 int status = 0;
4825 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4826 ENTER();
4827
4828 /*set wpa version*/
4829 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4830
4831 if (req->crypto.wpa_versions)
4832 {
4833 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4834 && ( (req->ie_len)
4835 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4836 // Make sure that it is including a WPA IE.
4837 /* Currently NL is putting WPA version 1 even for open,
4838 * since p2p ie is also put in same buffer.
4839 * */
4840 {
4841 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4842 }
4843 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4844 {
4845 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4846 }
4847 }
4848
4849 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4850 pWextState->wpaVersion);
4851
4852 /*set authentication type*/
4853 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4854
4855 if (0 > status)
4856 {
4857 hddLog(VOS_TRACE_LEVEL_ERROR,
4858 "%s: failed to set authentication type ", __func__);
4859 return status;
4860 }
4861
4862 /*set key mgmt type*/
4863 if (req->crypto.n_akm_suites)
4864 {
4865 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4866 if (0 > status)
4867 {
4868 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4869 __func__);
4870 return status;
4871 }
4872 }
4873
4874 /*set pairwise cipher type*/
4875 if (req->crypto.n_ciphers_pairwise)
4876 {
4877 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4878 req->crypto.ciphers_pairwise[0], true);
4879 if (0 > status)
4880 {
4881 hddLog(VOS_TRACE_LEVEL_ERROR,
4882 "%s: failed to set unicast cipher type", __func__);
4883 return status;
4884 }
4885 }
4886 else
4887 {
4888 /*Reset previous cipher suite to none*/
4889 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
4890 if (0 > status)
4891 {
4892 hddLog(VOS_TRACE_LEVEL_ERROR,
4893 "%s: failed to set unicast cipher type", __func__);
4894 return status;
4895 }
4896 }
4897
4898 /*set group cipher type*/
4899 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
4900 false);
4901
4902 if (0 > status)
4903 {
4904 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
4905 __func__);
4906 return status;
4907 }
4908
4909 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
4910 if (req->ie_len)
4911 {
4912 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
4913 if ( 0 > status)
4914 {
4915 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
4916 __func__);
4917 return status;
4918 }
4919 }
4920
4921 /*incase of WEP set default key information*/
4922 if (req->key && req->key_len)
4923 {
4924 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
4925 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
4926 )
4927 {
4928 if ( IW_AUTH_KEY_MGMT_802_1X
4929 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
4930 {
4931 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
4932 __func__);
4933 return -EOPNOTSUPP;
4934 }
4935 else
4936 {
4937 u8 key_len = req->key_len;
4938 u8 key_idx = req->key_idx;
4939
4940 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
4941 && (CSR_MAX_NUM_KEY > key_idx)
4942 )
4943 {
4944 hddLog(VOS_TRACE_LEVEL_INFO,
4945 "%s: setting default wep key, key_idx = %hu key_len %hu",
4946 __func__, key_idx, key_len);
4947 vos_mem_copy(
4948 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
4949 req->key, key_len);
4950 pWextState->roamProfile.Keys.KeyLength[key_idx] =
4951 (u8)key_len;
4952 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
4953 }
4954 }
4955 }
4956 }
4957
4958 return status;
4959}
4960
4961/*
4962 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4963 * This function is used to initialize the security
4964 * parameters during connect operation.
4965 */
4966static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
4967 struct net_device *ndev,
4968 struct cfg80211_connect_params *req
4969 )
4970{
4971 int status = 0;
4972 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
4973 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
4974 hdd_context_t *pHddCtx = NULL;
4975
4976 ENTER();
4977
4978 hddLog(VOS_TRACE_LEVEL_INFO,
4979 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4980
4981 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4982 {
4983 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4984 "%s:LOGP in Progress. Ignore!!!", __func__);
4985 return -EAGAIN;
4986 }
4987
4988#ifdef WLAN_BTAMP_FEATURE
4989 //Infra connect not supported when AMP traffic is on.
4990 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
4991 {
4992 hddLog(VOS_TRACE_LEVEL_ERROR,
4993 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004994 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07004995 }
4996#endif
4997 /*initialise security parameters*/
4998 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
4999
5000 if ( 0 > status)
5001 {
5002 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5003 __func__);
5004 return status;
5005 }
5006
5007 //If Device Mode is Station Concurrent Sessions Exit BMps
5008 //P2P Mode will be taken care in Open/close adaptor
5009 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5010 (vos_concurrent_sessions_running()))
5011 {
5012 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5013
5014 if (NULL != pVosContext)
5015 {
5016 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5017 if(NULL != pHddCtx)
5018 {
5019 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5020 }
5021 }
5022 }
5023
Mohit Khanna765234a2012-09-11 15:08:35 -07005024 if ( req->channel )
5025 {
5026 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5027 req->ssid_len, req->bssid,
5028 req->channel->hw_value);
5029 }
5030 else
5031 {
5032 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5033 req->ssid_len, req->bssid,
5034 0);
5035 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005036
5037 if (0 > status)
5038 {
5039 //ReEnable BMPS if disabled
5040 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5041 (NULL != pHddCtx))
5042 {
5043 //ReEnable Bmps and Imps back
5044 hdd_enable_bmps_imps(pHddCtx);
5045 }
5046
5047 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5048 return status;
5049 }
5050 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5051 EXIT();
5052 return status;
5053}
5054
5055
5056/*
5057 * FUNCTION: wlan_hdd_cfg80211_disconnect
5058 * This function is used to issue a disconnect request to SME
5059 */
5060static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5061 struct net_device *dev,
5062 u16 reason
5063 )
5064{
5065 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5066 tCsrRoamProfile *pRoamProfile =
5067 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5068 int status = 0;
5069 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5070
5071 ENTER();
5072
5073 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5074 __func__,pAdapter->device_mode);
5075
5076 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5077 __func__, reason);
5078
5079 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5080 {
5081 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5082 "%s:LOGP in Progress. Ignore!!!",__func__);
5083 return -EAGAIN;
5084 }
5085 if (NULL != pRoamProfile)
5086 {
5087 /*issue disconnect request to SME, if station is in connected state*/
5088 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5089 {
5090 eCsrRoamDisconnectReason reasonCode =
5091 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5092 switch(reason)
5093 {
5094 case WLAN_REASON_MIC_FAILURE:
5095 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5096 break;
5097
5098 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5099 case WLAN_REASON_DISASSOC_AP_BUSY:
5100 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5101 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5102 break;
5103
5104 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5105 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5106 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5107 break;
5108
5109 case WLAN_REASON_DEAUTH_LEAVING:
5110 default:
5111 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5112 break;
5113 }
5114 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5115 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5116 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5117
5118 /*issue disconnect*/
5119 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5120 pAdapter->sessionId, reasonCode);
5121
5122 if ( 0 != status)
5123 {
5124 hddLog(VOS_TRACE_LEVEL_ERROR,
5125 "%s csrRoamDisconnect failure, returned %d \n",
5126 __func__, (int)status );
5127 return -EINVAL;
5128 }
5129
5130 wait_for_completion_interruptible_timeout(
5131 &pAdapter->disconnect_comp_var,
5132 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5133
5134
5135 /*stop tx queues*/
5136 netif_tx_disable(dev);
5137 netif_carrier_off(dev);
5138 }
5139 }
5140 else
5141 {
5142 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5143 }
5144
5145 return status;
5146}
5147
5148/*
5149 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5150 * This function is used to initialize the security
5151 * settings in IBSS mode.
5152 */
5153static int wlan_hdd_cfg80211_set_privacy_ibss(
5154 hdd_adapter_t *pAdapter,
5155 struct cfg80211_ibss_params *params
5156 )
5157{
5158 int status = 0;
5159 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5160 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5161 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5162
5163 ENTER();
5164
5165 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5166
5167 if (params->ie_len && ( NULL != params->ie) )
5168 {
5169 if (WLAN_EID_RSN == params->ie[0])
5170 {
5171 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5172 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5173 }
5174 else
5175 {
5176 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5177 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5178 }
5179 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5180
5181 if (0 > status)
5182 {
5183 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5184 __func__);
5185 return status;
5186 }
5187 }
5188
5189 pWextState->roamProfile.AuthType.authType[0] =
5190 pHddStaCtx->conn_info.authType =
5191 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5192
5193 if (params->privacy)
5194 {
5195 /* Security enabled IBSS, At this time there is no information available
5196 * about the security paramters, so initialise the encryption type to
5197 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5198 * The correct security parameters will be updated later in
5199 * wlan_hdd_cfg80211_add_key */
5200 /* Hal expects encryption type to be set inorder
5201 *enable privacy bit in beacons */
5202
5203 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5204 }
5205
5206 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5207 pWextState->roamProfile.EncryptionType.numEntries = 1;
5208 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5209
5210 return status;
5211}
5212
5213/*
5214 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5215 * This function is used to create/join an IBSS
5216 */
5217static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5218 struct net_device *dev,
5219 struct cfg80211_ibss_params *params
5220 )
5221{
5222 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5223 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5224 tCsrRoamProfile *pRoamProfile;
5225 int status;
5226 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5227
5228 ENTER();
5229
5230 hddLog(VOS_TRACE_LEVEL_INFO,
5231 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5232
5233 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5234 {
5235 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5236 "%s:LOGP in Progress. Ignore!!!", __func__);
5237 return -EAGAIN;
5238 }
5239
5240 if (NULL == pWextState)
5241 {
5242 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5243 __func__);
5244 return -EIO;
5245 }
5246
5247 pRoamProfile = &pWextState->roamProfile;
5248
5249 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5250 {
5251 hddLog (VOS_TRACE_LEVEL_ERROR,
5252 "%s Interface type is not set to IBSS \n", __func__);
5253 return -EINVAL;
5254 }
5255
5256 /* Set Channel */
5257 if (NULL != params->channel)
5258 {
5259 u8 channelNum;
5260 if (IEEE80211_BAND_5GHZ == params->channel->band)
5261 {
5262 hddLog(VOS_TRACE_LEVEL_ERROR,
5263 "%s: IBSS join is called with unsupported band %d",
5264 __func__, params->channel->band);
5265 return -EOPNOTSUPP;
5266 }
5267
5268 /* Get channel number */
5269 channelNum =
5270 ieee80211_frequency_to_channel(params->channel->center_freq);
5271
5272 /*TODO: use macro*/
5273 if (14 >= channelNum)
5274 {
5275 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5276 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5277 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5278 int indx;
5279
5280 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5281 validChan, &numChans))
5282 {
5283 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5284 __func__);
5285 return -EOPNOTSUPP;
5286 }
5287
5288 for (indx = 0; indx < numChans; indx++)
5289 {
5290 if (channelNum == validChan[indx])
5291 {
5292 break;
5293 }
5294 }
5295 if (indx >= numChans)
5296 {
5297 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5298 __func__, channelNum);
5299 return -EINVAL;
5300 }
5301 /* Set the Operational Channel */
5302 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5303 channelNum);
5304 pRoamProfile->ChannelInfo.numOfChannels = 1;
5305 pHddStaCtx->conn_info.operationChannel = channelNum;
5306 pRoamProfile->ChannelInfo.ChannelList =
5307 &pHddStaCtx->conn_info.operationChannel;
5308 }
5309 else
5310 {
5311 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5312 __func__, channelNum);
5313 return -EINVAL;
5314 }
5315 }
5316
5317 /* Initialize security parameters */
5318 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5319 if (status < 0)
5320 {
5321 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5322 __func__);
5323 return status;
5324 }
5325
5326 /* Issue connect start */
5327 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005328 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005329
5330 if (0 > status)
5331 {
5332 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5333 return status;
5334 }
5335
5336 return 0;
5337}
5338
5339/*
5340 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5341 * This function is used to leave an IBSS
5342 */
5343static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5344 struct net_device *dev
5345 )
5346{
5347 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5348 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5349 tCsrRoamProfile *pRoamProfile;
5350
5351 ENTER();
5352
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005353 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5354 {
5355 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5356 "%s:LOGP in Progress. Ignore!!!", __func__);
5357 return -EAGAIN;
5358 }
5359
Jeff Johnson295189b2012-06-20 16:38:30 -07005360 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5361 if (NULL == pWextState)
5362 {
5363 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5364 __func__);
5365 return -EIO;
5366 }
5367
5368 pRoamProfile = &pWextState->roamProfile;
5369
5370 /* Issue disconnect only if interface type is set to IBSS */
5371 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5372 {
5373 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5374 __func__);
5375 return -EINVAL;
5376 }
5377
5378 /* Issue Disconnect request */
5379 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5380 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5381 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5382
5383 return 0;
5384}
5385
5386/*
5387 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5388 * This function is used to set the phy parameters
5389 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5390 */
5391static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5392 u32 changed)
5393{
5394 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5395 tHalHandle hHal = pHddCtx->hHal;
5396
5397 ENTER();
5398
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005399 if ( pHddCtx->isLogpInProgress )
5400 {
5401 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5402 "%s:LOGP in Progress. Ignore!!!", __func__);
5403 return -EAGAIN;
5404 }
5405
Jeff Johnson295189b2012-06-20 16:38:30 -07005406 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5407 {
5408 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5409 WNI_CFG_RTS_THRESHOLD_STAMAX :
5410 wiphy->rts_threshold;
5411
5412 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5413 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5414 {
5415 hddLog(VOS_TRACE_LEVEL_ERROR,
5416 "%s: Invalid RTS Threshold value %hu",
5417 __func__, rts_threshold);
5418 return -EINVAL;
5419 }
5420
5421 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5422 rts_threshold, ccmCfgSetCallback,
5423 eANI_BOOLEAN_TRUE))
5424 {
5425 hddLog(VOS_TRACE_LEVEL_ERROR,
5426 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5427 __func__, rts_threshold);
5428 return -EIO;
5429 }
5430
5431 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5432 rts_threshold);
5433 }
5434
5435 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5436 {
5437 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5438 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5439 wiphy->frag_threshold;
5440
5441 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5442 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5443 {
5444 hddLog(VOS_TRACE_LEVEL_ERROR,
5445 "%s: Invalid frag_threshold value %hu", __func__,
5446 frag_threshold);
5447 return -EINVAL;
5448 }
5449
5450 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5451 frag_threshold, ccmCfgSetCallback,
5452 eANI_BOOLEAN_TRUE))
5453 {
5454 hddLog(VOS_TRACE_LEVEL_ERROR,
5455 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5456 __func__, frag_threshold);
5457 return -EIO;
5458 }
5459
5460 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5461 frag_threshold);
5462 }
5463
5464 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5465 || (changed & WIPHY_PARAM_RETRY_LONG))
5466 {
5467 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5468 wiphy->retry_short :
5469 wiphy->retry_long;
5470
5471 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5472 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5473 {
5474 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5475 __func__, retry_value);
5476 return -EINVAL;
5477 }
5478
5479 if (changed & WIPHY_PARAM_RETRY_SHORT)
5480 {
5481 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5482 retry_value, ccmCfgSetCallback,
5483 eANI_BOOLEAN_TRUE))
5484 {
5485 hddLog(VOS_TRACE_LEVEL_ERROR,
5486 "%s: ccmCfgSetInt failed for long retry count %hu",
5487 __func__, retry_value);
5488 return -EIO;
5489 }
5490 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5491 __func__, retry_value);
5492 }
5493 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5494 {
5495 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5496 retry_value, ccmCfgSetCallback,
5497 eANI_BOOLEAN_TRUE))
5498 {
5499 hddLog(VOS_TRACE_LEVEL_ERROR,
5500 "%s: ccmCfgSetInt failed for short retry count %hu",
5501 __func__, retry_value);
5502 return -EIO;
5503 }
5504 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5505 __func__, retry_value);
5506 }
5507 }
5508
5509 return 0;
5510}
5511
5512/*
5513 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5514 * This function is used to set the txpower
5515 */
5516static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5517#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5518 enum tx_power_setting type,
5519#else
5520 enum nl80211_tx_power_setting type,
5521#endif
5522 int dbm)
5523{
5524 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5525 tHalHandle hHal = pHddCtx->hHal;
5526 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5527 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5528
5529 ENTER();
5530
5531 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5532 dbm, ccmCfgSetCallback,
5533 eANI_BOOLEAN_TRUE))
5534 {
5535 hddLog(VOS_TRACE_LEVEL_ERROR,
5536 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5537 return -EIO;
5538 }
5539
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005540 if ( pHddCtx->isLogpInProgress )
5541 {
5542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5543 "%s:LOGP in Progress. Ignore!!!", __func__);
5544 return -EAGAIN;
5545 }
5546
Jeff Johnson295189b2012-06-20 16:38:30 -07005547 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5548 dbm);
5549
5550 switch(type)
5551 {
5552 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5553 /* Fall through */
5554 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5555 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5556 {
5557 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5558 __func__);
5559 return -EIO;
5560 }
5561 break;
5562 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5563 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5564 __func__);
5565 return -EOPNOTSUPP;
5566 break;
5567 default:
5568 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5569 __func__, type);
5570 return -EIO;
5571 }
5572
5573 return 0;
5574}
5575
5576/*
5577 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5578 * This function is used to read the txpower
5579 */
5580static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5581{
5582
5583 hdd_adapter_t *pAdapter;
5584 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5585
Jeff Johnsone7245742012-09-05 17:12:55 -07005586 ENTER();
5587
Jeff Johnson295189b2012-06-20 16:38:30 -07005588 if (NULL == pHddCtx)
5589 {
5590 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5591 *dbm = 0;
5592 return -ENOENT;
5593 }
5594
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005595 if ( pHddCtx->isLogpInProgress )
5596 {
5597 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5598 "%s:LOGP in Progress. Ignore!!!", __func__);
5599 return -EAGAIN;
5600 }
5601
Jeff Johnson295189b2012-06-20 16:38:30 -07005602 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5603 if (NULL == pAdapter)
5604 {
5605 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5606 return -ENOENT;
5607 }
5608
5609 wlan_hdd_get_classAstats(pAdapter);
5610 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5611
Jeff Johnsone7245742012-09-05 17:12:55 -07005612 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005613 return 0;
5614}
5615
5616static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5617 u8* mac, struct station_info *sinfo)
5618{
5619 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5620 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5621 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5622 tANI_U8 rate_flags;
5623
5624 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5625 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5626 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5627
5628 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5629 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5630 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5631 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5632 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5633 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5634 tANI_U16 maxRate = 0;
5635 tANI_U16 myRate;
5636 tANI_U16 currentRate = 0;
5637 tANI_U8 maxSpeedMCS = 0;
5638 tANI_U8 maxMCSIdx = 0;
5639 tANI_U8 rateFlag = 1;
5640 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005641 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005642
Jeff Johnsone7245742012-09-05 17:12:55 -07005643 ENTER();
5644
Jeff Johnson295189b2012-06-20 16:38:30 -07005645 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5646 (0 == ssidlen))
5647 {
5648 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5649 " Invalid ssidlen, %d", __func__, ssidlen);
5650 /*To keep GUI happy*/
5651 return 0;
5652 }
5653
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005654 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5655 {
5656 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5657 "%s:LOGP in Progress. Ignore!!!", __func__);
5658 return -EAGAIN;
5659 }
5660
Jeff Johnson295189b2012-06-20 16:38:30 -07005661 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5662 sinfo->filled |= STATION_INFO_SIGNAL;
5663
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005664 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005665 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5666
5667 //convert to the UI units of 100kbps
5668 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5669
5670#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005671 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 -07005672 sinfo->signal,
5673 pCfg->reportMaxLinkSpeed,
5674 myRate,
5675 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005676 (int) pCfg->linkSpeedRssiMid,
5677 (int) pCfg->linkSpeedRssiLow,
5678 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005679#endif //LINKSPEED_DEBUG_ENABLED
5680
5681 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5682 {
5683 // we do not want to necessarily report the current speed
5684 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5685 {
5686 // report the max possible speed
5687 rssidx = 0;
5688 }
5689 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5690 {
5691 // report the max possible speed with RSSI scaling
5692 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5693 {
5694 // report the max possible speed
5695 rssidx = 0;
5696 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005697 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005698 {
5699 // report middle speed
5700 rssidx = 1;
5701 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005702 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5703 {
5704 // report middle speed
5705 rssidx = 2;
5706 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005707 else
5708 {
5709 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005710 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005711 }
5712 }
5713 else
5714 {
5715 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5716 hddLog(VOS_TRACE_LEVEL_ERROR,
5717 "%s: Invalid value for reportMaxLinkSpeed: %u",
5718 __func__, pCfg->reportMaxLinkSpeed);
5719 rssidx = 0;
5720 }
5721
5722 maxRate = 0;
5723
5724 /* Get Basic Rate Set */
5725 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5726 for (i = 0; i < ORLeng; i++)
5727 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005728 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005729 {
5730 /* Validate Rate Set */
5731 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5732 {
5733 currentRate = supported_data_rate[j].supported_rate[rssidx];
5734 break;
5735 }
5736 }
5737 /* Update MAX rate */
5738 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5739 }
5740
5741 /* Get Extended Rate Set */
5742 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5743 for (i = 0; i < ERLeng; i++)
5744 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005745 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005746 {
5747 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5748 {
5749 currentRate = supported_data_rate[j].supported_rate[rssidx];
5750 break;
5751 }
5752 }
5753 /* Update MAX rate */
5754 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5755 }
5756
5757 /* Get MCS Rate Set -- but only if we are connected at MCS
5758 rates or if we are always reporting max speed or if we have
5759 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005760 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005761 {
5762 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5763 rateFlag = 0;
5764 if (rate_flags & eHAL_TX_RATE_HT40)
5765 {
5766 rateFlag |= 1;
5767 }
5768 if (rate_flags & eHAL_TX_RATE_SGI)
5769 {
5770 rateFlag |= 2;
5771 }
5772
5773 for (i = 0; i < MCSLeng; i++)
5774 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005775 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5776 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005777 {
5778 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5779 {
5780 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5781 break;
5782 }
5783 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005784 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005785 {
5786 maxRate = currentRate;
5787 maxSpeedMCS = 1;
5788 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5789 }
5790 }
5791 }
5792
5793 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005794 if (((maxRate < myRate) && (0 == rssidx)) ||
5795 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005796 {
5797 maxRate = myRate;
5798 if (rate_flags & eHAL_TX_RATE_LEGACY)
5799 {
5800 maxSpeedMCS = 0;
5801 }
5802 else
5803 {
5804 maxSpeedMCS = 1;
5805 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5806 }
5807 }
5808
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005809 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005810 {
5811 sinfo->txrate.legacy = maxRate;
5812#ifdef LINKSPEED_DEBUG_ENABLED
5813 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5814#endif //LINKSPEED_DEBUG_ENABLED
5815 }
5816 else
5817 {
5818 sinfo->txrate.mcs = maxMCSIdx;
5819 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5820 if (rate_flags & eHAL_TX_RATE_SGI)
5821 {
5822 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5823 }
5824 if (rate_flags & eHAL_TX_RATE_HT40)
5825 {
5826 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5827 }
5828#ifdef LINKSPEED_DEBUG_ENABLED
5829 pr_info("Reporting MCS rate %d flags %x\n",
5830 sinfo->txrate.mcs,
5831 sinfo->txrate.flags );
5832#endif //LINKSPEED_DEBUG_ENABLED
5833 }
5834 }
5835 else
5836 {
5837 // report current rate instead of max rate
5838
5839 if (rate_flags & eHAL_TX_RATE_LEGACY)
5840 {
5841 //provide to the UI in units of 100kbps
5842 sinfo->txrate.legacy = myRate;
5843#ifdef LINKSPEED_DEBUG_ENABLED
5844 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5845#endif //LINKSPEED_DEBUG_ENABLED
5846 }
5847 else
5848 {
5849 //must be MCS
5850 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5851 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5852 if (rate_flags & eHAL_TX_RATE_SGI)
5853 {
5854 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5855 }
5856 if (rate_flags & eHAL_TX_RATE_HT40)
5857 {
5858 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5859 }
5860#ifdef LINKSPEED_DEBUG_ENABLED
5861 pr_info("Reporting actual MCS rate %d flags %x\n",
5862 sinfo->txrate.mcs,
5863 sinfo->txrate.flags );
5864#endif //LINKSPEED_DEBUG_ENABLED
5865 }
5866 }
5867 sinfo->filled |= STATION_INFO_TX_BITRATE;
5868
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005869 sinfo->tx_packets =
5870 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5871 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5872 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5873 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5874
5875 sinfo->tx_retries =
5876 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
5877 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
5878 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
5879 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
5880
5881 sinfo->tx_failed =
5882 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
5883 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
5884 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
5885 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
5886
5887 sinfo->filled |=
5888 STATION_INFO_TX_PACKETS |
5889 STATION_INFO_TX_RETRIES |
5890 STATION_INFO_TX_FAILED;
5891
5892 EXIT();
5893 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005894}
5895
5896static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
5897 struct net_device *dev, bool mode, v_SINT_t timeout)
5898{
5899 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5900 VOS_STATUS vos_status;
5901
Jeff Johnsone7245742012-09-05 17:12:55 -07005902 ENTER();
5903
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 if (NULL == pAdapter)
5905 {
5906 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5907 return -ENODEV;
5908 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005909 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5910 {
5911 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5912 "%s:LOGP in Progress. Ignore!!!", __func__);
5913 return -EAGAIN;
5914 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005915
5916 /**The get power cmd from the supplicant gets updated by the nl only
5917 *on successful execution of the function call
5918 *we are oppositely mapped w.r.t mode in the driver
5919 **/
5920 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
5921
Jeff Johnsone7245742012-09-05 17:12:55 -07005922 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005923 if (VOS_STATUS_E_FAILURE == vos_status)
5924 {
5925 return -EINVAL;
5926 }
5927 return 0;
5928}
5929
5930
5931#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5932static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
5933 struct net_device *netdev,
5934 u8 key_index)
5935{
Jeff Johnsone7245742012-09-05 17:12:55 -07005936 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005937 return 0;
5938}
5939#endif //LINUX_VERSION_CODE
5940
5941#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5942static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5943 struct net_device *dev,
5944 struct ieee80211_txq_params *params)
5945{
Jeff Johnsone7245742012-09-05 17:12:55 -07005946 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 return 0;
5948}
5949#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5950static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5951 struct ieee80211_txq_params *params)
5952{
Jeff Johnsone7245742012-09-05 17:12:55 -07005953 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 return 0;
5955}
5956#endif //LINUX_VERSION_CODE
5957
5958static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
5959 struct net_device *dev, u8 *mac)
5960{
5961 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5962
Jeff Johnsone7245742012-09-05 17:12:55 -07005963 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005964 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5965 {
5966 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5967 return -EINVAL;
5968 }
5969
5970 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5971 {
5972 hddLog( LOGE,
5973 "%s: Wlan Load/Unload is in progress", __func__);
5974 return -EBUSY;
5975 }
5976
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005977 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5978 {
5979 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5980 "%s:LOGP in Progress. Ignore!!!", __func__);
5981 return -EAGAIN;
5982 }
5983
Jeff Johnson295189b2012-06-20 16:38:30 -07005984 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
5985#ifdef WLAN_FEATURE_P2P
5986 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5987#endif
5988 )
5989 {
5990 if( NULL == mac )
5991 {
5992 v_U16_t i;
5993 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
5994 {
5995 if(pAdapter->aStaInfo[i].isUsed)
5996 {
5997 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
5998 hddLog(VOS_TRACE_LEVEL_INFO,
5999 "%s: Delete STA with MAC::"
6000 "%02x:%02x:%02x:%02x:%02x:%02x",
6001 __func__,
6002 macAddr[0], macAddr[1], macAddr[2],
6003 macAddr[3], macAddr[4], macAddr[5]);
6004 hdd_softap_sta_deauth(pAdapter, macAddr);
6005 }
6006 }
6007 }
6008 else
6009 {
6010 hddLog(VOS_TRACE_LEVEL_INFO,
6011 "%s: Delete STA with MAC::"
6012 "%02x:%02x:%02x:%02x:%02x:%02x",
6013 __func__,
6014 mac[0], mac[1], mac[2],
6015 mac[3], mac[4], mac[5]);
6016 hdd_softap_sta_deauth(pAdapter, mac);
6017 }
6018 }
6019
6020 EXIT();
6021
6022 return 0;
6023}
6024
6025static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6026 struct net_device *dev, u8 *mac, struct station_parameters *params)
6027{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006028#ifdef FEATURE_WLAN_TDLS
6029 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6030 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6031 u32 mask, set;
6032 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006033 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006034
6035 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6036 {
6037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6038 "Invalid arguments");
6039 return -EINVAL;
6040 }
6041
6042 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6043 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6044 {
6045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6046 "TDLS Disabled in INI OR not enabled in FW.\
6047 Cannot process TDLS commands \n");
6048 return -ENOTSUPP;
6049 }
6050
6051 mask = params->sta_flags_mask;
6052
6053 set = params->sta_flags_set;
6054
6055
6056 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6057 "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
6058
6059 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6060 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6062 "Add TDLS peer");
6063
6064
6065 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6066 pAdapter->sessionId, mac);
6067
6068 if (VOS_STATUS_SUCCESS != status) {
6069 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6070 "%s: sme_AddTdlsPeerSta failed!", __func__);
6071 }
6072 }
6073 }
6074#endif
6075
Jeff Johnson295189b2012-06-20 16:38:30 -07006076 return 0;
6077}
6078
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006079
6080#ifdef FEATURE_WLAN_LFR
6081static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006082 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006083{
6084#define MAX_PMKSAIDS_IN_CACHE 8
6085 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006086 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006087 tANI_U32 j=0;
6088 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6089 tHalHandle halHandle;
6090 eHalStatus result;
6091 tANI_U8 BSSIDMatched = 0;
6092
Jeff Johnsone7245742012-09-05 17:12:55 -07006093 ENTER();
6094
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006095 // Validate pAdapter
6096 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6097 {
6098 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6099 return -EINVAL;
6100 }
6101
6102 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6103 {
6104 hddLog( LOGE,
6105 "%s: Wlan Load/Unload is in progress", __func__);
6106 return -EBUSY;
6107 }
6108
6109 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6110 {
6111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6112 "%s:LOGP in Progress. Ignore!!!", __func__);
6113 return -EAGAIN;
6114 }
6115
6116 // Retrieve halHandle
6117 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6118
6119 for (j = 0; j < i; j++)
6120 {
6121 if(vos_mem_compare(PMKIDCache[j].BSSID,
6122 pmksa->bssid, WNI_CFG_BSSID_LEN))
6123 {
6124 /* BSSID matched previous entry. Overwrite it. */
6125 BSSIDMatched = 1;
6126 vos_mem_copy(PMKIDCache[j].BSSID,
6127 pmksa->bssid, WNI_CFG_BSSID_LEN);
6128 vos_mem_copy(PMKIDCache[j].PMKID,
6129 pmksa->pmkid,
6130 CSR_RSN_PMKID_SIZE);
6131 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006132 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006133 dump_bssid(pmksa->bssid);
6134 dump_pmkid(halHandle, pmksa->pmkid);
6135 break;
6136 }
6137 }
6138
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006139 /* Check we compared all entries,if then take the first slot now */
6140 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6141
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006142 if (!BSSIDMatched)
6143 {
6144 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6145 vos_mem_copy(PMKIDCache[i].BSSID,
6146 pmksa->bssid, ETHER_ADDR_LEN);
6147 vos_mem_copy(PMKIDCache[i].PMKID,
6148 pmksa->pmkid,
6149 CSR_RSN_PMKID_SIZE);
6150 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006151 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006152 dump_bssid(pmksa->bssid);
6153 dump_pmkid(halHandle, pmksa->pmkid);
6154 // Increment the HDD Local Cache index
6155 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6156 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6157 }
6158
6159
6160 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6161 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006162 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006163 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006164 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006165 // Finally set the PMKSA ID Cache in CSR
6166 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6167 PMKIDCache,
6168 i );
6169 return 0;
6170}
6171
6172
6173static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006174 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006175{
Jeff Johnsone7245742012-09-05 17:12:55 -07006176 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006177 // TODO: Implement this later.
6178 return 0;
6179}
6180
6181static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6182{
Jeff Johnsone7245742012-09-05 17:12:55 -07006183 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006184 // TODO: Implement this later.
6185 return 0;
6186}
6187#endif
6188
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006189#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6190static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6191 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6192{
6193 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6194 hdd_station_ctx_t *pHddStaCtx;
6195
6196 if (NULL == pAdapter)
6197 {
6198 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6199 return -ENODEV;
6200 }
6201
6202 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6203
6204 // Added for debug on reception of Re-assoc Req.
6205 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6206 {
6207 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6208 ftie->ie_len);
6209 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6210 }
6211
6212#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6213 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6214 ftie->ie_len);
6215#endif
6216
6217 // Pass the received FT IEs to SME
6218 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6219 ftie->ie_len);
6220 return 0;
6221}
6222#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006223
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006224#ifdef FEATURE_WLAN_TDLS
6225static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6226 u8 *peer, u8 action_code, u8 dialog_token,
6227 u16 status_code, const u8 *buf, size_t len)
6228{
6229
6230 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6231 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6232 u8 *buf_1;
6233 size_t len_1 = len;
6234 u8 peerMac[6];
6235 VOS_STATUS status;
6236
6237 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6238 {
6239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6240 "Invalid arguments");
6241 return -EINVAL;
6242 }
6243
6244 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6245 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6246 {
6247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6248 "TDLS Disabled in INI OR not enabled in FW.\
6249 Cannot process TDLS commands \n");
6250 return -ENOTSUPP;
6251 }
6252 vos_mem_copy( peerMac, peer, 6);
6253
6254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6255 "Request to send TDLS management: action = %d, status = %d, \
6256 len = %d", action_code, status_code, len);
6257
6258 buf_1 = vos_mem_malloc(len);
6259 if(buf_1 == NULL) {
6260 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6261 "%s: malloc failed!", __func__);
6262 return -ENOMEM;
6263 }
6264 vos_mem_copy(buf_1, buf, len);
6265
6266 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6267 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6268
6269 if (VOS_STATUS_SUCCESS != status) {
6270 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6271 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6272 }
6273
6274 vos_mem_free(buf_1);
6275
6276 return 0;
6277}
6278
6279static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6280 u8 *peer, enum nl80211_tdls_operation oper)
6281{
6282 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6283 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6284
6285 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6286 {
6287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6288 "Invalid arguments");
6289 return -EINVAL;
6290 }
6291
6292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6293 "Request for TDLS oper: %d", (int)oper);
6294
6295 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6296 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6297 {
6298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6299 "TDLS Disabled in INI OR not enabled in FW.\
6300 Cannot process TDLS commands \n");
6301 return -ENOTSUPP;
6302 }
6303
6304 switch (oper) {
6305 case NL80211_TDLS_ENABLE_LINK:
6306 {
6307 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6308 v_U8_t my_peer[6];
6309 v_U8_t ucSTAId;
6310 VOS_STATUS status;
6311
6312 if (peer) {
6313 vos_mem_copy(my_peer, peer, 6);
6314 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6315
6316 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6317 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6318 __func__, peer[0], peer[1],
6319 peer[2], peer[3],
6320 peer[4], peer[5] );
6321
6322 if (-1 == ucSTAId ) {
6323 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
6324 return 0;
6325 }
6326
6327 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6328 WLANTL_STA_AUTHENTICATED );
6329
6330 if (0 != status) {
6331 hddLog(VOS_TRACE_LEVEL_ERROR,
6332 "%s: WLANTL_ChangeSTAState failed, returned %d",
6333 __func__, status);
6334 return status;
6335 }
6336 } else {
6337 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6338 }
6339 }
6340 break;
6341 case NL80211_TDLS_DISABLE_LINK:
6342 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6343 pAdapter->sessionId, peer );
6344 return 0;
6345 case NL80211_TDLS_TEARDOWN:
6346 case NL80211_TDLS_SETUP:
6347 case NL80211_TDLS_DISCOVERY_REQ:
6348 /* We don't support in-driver setup/teardown/discovery */
6349 return -ENOTSUPP;
6350 default:
6351 return -ENOTSUPP;
6352 }
6353 return 0;
6354}
6355#endif
6356
Jeff Johnson295189b2012-06-20 16:38:30 -07006357/* cfg80211_ops */
6358static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6359{
6360 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6361 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6362 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6363 .change_station = wlan_hdd_change_station,
6364#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6365 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6366 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6367 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006368#else
6369 .start_ap = wlan_hdd_cfg80211_start_ap,
6370 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6371 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006372#endif
6373 .change_bss = wlan_hdd_cfg80211_change_bss,
6374 .add_key = wlan_hdd_cfg80211_add_key,
6375 .get_key = wlan_hdd_cfg80211_get_key,
6376 .del_key = wlan_hdd_cfg80211_del_key,
6377 .set_default_key = wlan_hdd_cfg80211_set_default_key,
6378 .set_channel = wlan_hdd_cfg80211_set_channel,
6379 .scan = wlan_hdd_cfg80211_scan,
6380 .connect = wlan_hdd_cfg80211_connect,
6381 .disconnect = wlan_hdd_cfg80211_disconnect,
6382 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6383 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6384 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6385 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6386 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6387#ifdef WLAN_FEATURE_P2P
6388 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6389 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6390 .mgmt_tx = wlan_hdd_action,
6391#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6392 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6393 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6394 .set_txq_params = wlan_hdd_set_txq_params,
6395#endif
6396#endif
6397 .get_station = wlan_hdd_cfg80211_get_station,
6398 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6399 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006400 .add_station = wlan_hdd_cfg80211_add_station,
6401#ifdef FEATURE_WLAN_LFR
6402 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6403 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6404 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6405#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006406#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6407 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6408#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006409#ifdef FEATURE_WLAN_TDLS
6410 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6411 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6412#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006413};
6414
6415#endif // CONFIG_CFG80211