blob: 77ba0922cbfffb273a2012977acf05bb3ccf24bf [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"
79#ifdef WLAN_BTAMP_FEATURE
80#include "bap_hdd_misc.h"
81#endif
82#include <qc_sap_ioctl.h>
83
84#define g_mode_rates_size (12)
85#define a_mode_rates_size (8)
86#define FREQ_BASE_80211G (2407)
87#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070088#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -070089#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
90 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
91
92#define HDD2GHZCHAN(freq, chan, flag) { \
93 .band = IEEE80211_BAND_2GHZ, \
94 .center_freq = (freq), \
95 .hw_value = (chan),\
96 .flags = (flag), \
97 .max_antenna_gain = 0 ,\
98 .max_power = 30, \
99}
100
101#define HDD5GHZCHAN(freq, chan, flag) { \
102 .band = IEEE80211_BAND_5GHZ, \
103 .center_freq = (freq), \
104 .hw_value = (chan),\
105 .flags = (flag), \
106 .max_antenna_gain = 0 ,\
107 .max_power = 30, \
108}
109
110#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
111{\
112 .bitrate = rate, \
113 .hw_value = rate_id, \
114 .flags = flag, \
115}
116
117static const u32 hdd_cipher_suites[] =
118{
119 WLAN_CIPHER_SUITE_WEP40,
120 WLAN_CIPHER_SUITE_WEP104,
121 WLAN_CIPHER_SUITE_TKIP,
122#ifdef FEATURE_WLAN_CCX
123#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
124 WLAN_CIPHER_SUITE_KRK,
125 WLAN_CIPHER_SUITE_CCMP,
126#else
127 WLAN_CIPHER_SUITE_CCMP,
128#endif
129#ifdef FEATURE_WLAN_WAPI
130 WLAN_CIPHER_SUITE_SMS4,
131#endif
132};
133
134static inline int is_broadcast_ether_addr(const u8 *addr)
135{
136 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
137 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
138}
139
140static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
141{
142 HDD2GHZCHAN(2412, 1, 0) ,
143 HDD2GHZCHAN(2417, 2, 0) ,
144 HDD2GHZCHAN(2422, 3, 0) ,
145 HDD2GHZCHAN(2427, 4, 0) ,
146 HDD2GHZCHAN(2432, 5, 0) ,
147 HDD2GHZCHAN(2437, 6, 0) ,
148 HDD2GHZCHAN(2442, 7, 0) ,
149 HDD2GHZCHAN(2447, 8, 0) ,
150 HDD2GHZCHAN(2452, 9, 0) ,
151 HDD2GHZCHAN(2457, 10, 0) ,
152 HDD2GHZCHAN(2462, 11, 0) ,
153 HDD2GHZCHAN(2467, 12, 0) ,
154 HDD2GHZCHAN(2472, 13, 0) ,
155 HDD2GHZCHAN(2484, 14, 0) ,
156};
157
158#ifdef WLAN_FEATURE_P2P
159static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
160{
161 HDD2GHZCHAN(2412, 1, 0) ,
162 HDD2GHZCHAN(2437, 6, 0) ,
163 HDD2GHZCHAN(2462, 11, 0) ,
164};
165#endif
166
167static struct ieee80211_channel hdd_channels_5_GHZ[] =
168{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700169 HDD5GHZCHAN(4920, 240, 0) ,
170 HDD5GHZCHAN(4940, 244, 0) ,
171 HDD5GHZCHAN(4960, 248, 0) ,
172 HDD5GHZCHAN(4980, 252, 0) ,
173 HDD5GHZCHAN(5040, 208, 0) ,
174 HDD5GHZCHAN(5060, 212, 0) ,
175 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700176 HDD5GHZCHAN(5180, 36, 0) ,
177 HDD5GHZCHAN(5200, 40, 0) ,
178 HDD5GHZCHAN(5220, 44, 0) ,
179 HDD5GHZCHAN(5240, 48, 0) ,
180 HDD5GHZCHAN(5260, 52, 0) ,
181 HDD5GHZCHAN(5280, 56, 0) ,
182 HDD5GHZCHAN(5300, 60, 0) ,
183 HDD5GHZCHAN(5320, 64, 0) ,
184 HDD5GHZCHAN(5500,100, 0) ,
185 HDD5GHZCHAN(5520,104, 0) ,
186 HDD5GHZCHAN(5540,108, 0) ,
187 HDD5GHZCHAN(5560,112, 0) ,
188 HDD5GHZCHAN(5580,116, 0) ,
189 HDD5GHZCHAN(5600,120, 0) ,
190 HDD5GHZCHAN(5620,124, 0) ,
191 HDD5GHZCHAN(5640,128, 0) ,
192 HDD5GHZCHAN(5660,132, 0) ,
193 HDD5GHZCHAN(5680,136, 0) ,
194 HDD5GHZCHAN(5700,140, 0) ,
195 HDD5GHZCHAN(5745,149, 0) ,
196 HDD5GHZCHAN(5765,153, 0) ,
197 HDD5GHZCHAN(5785,157, 0) ,
198 HDD5GHZCHAN(5805,161, 0) ,
199 HDD5GHZCHAN(5825,165, 0) ,
200};
201
202static struct ieee80211_rate g_mode_rates[] =
203{
204 HDD_G_MODE_RATETAB(10, 0x1, 0),
205 HDD_G_MODE_RATETAB(20, 0x2, 0),
206 HDD_G_MODE_RATETAB(55, 0x4, 0),
207 HDD_G_MODE_RATETAB(110, 0x8, 0),
208 HDD_G_MODE_RATETAB(60, 0x10, 0),
209 HDD_G_MODE_RATETAB(90, 0x20, 0),
210 HDD_G_MODE_RATETAB(120, 0x40, 0),
211 HDD_G_MODE_RATETAB(180, 0x80, 0),
212 HDD_G_MODE_RATETAB(240, 0x100, 0),
213 HDD_G_MODE_RATETAB(360, 0x200, 0),
214 HDD_G_MODE_RATETAB(480, 0x400, 0),
215 HDD_G_MODE_RATETAB(540, 0x800, 0),
216};
217
218static struct ieee80211_rate a_mode_rates[] =
219{
220 HDD_G_MODE_RATETAB(60, 0x10, 0),
221 HDD_G_MODE_RATETAB(90, 0x20, 0),
222 HDD_G_MODE_RATETAB(120, 0x40, 0),
223 HDD_G_MODE_RATETAB(180, 0x80, 0),
224 HDD_G_MODE_RATETAB(240, 0x100, 0),
225 HDD_G_MODE_RATETAB(360, 0x200, 0),
226 HDD_G_MODE_RATETAB(480, 0x400, 0),
227 HDD_G_MODE_RATETAB(540, 0x800, 0),
228};
229
230static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
231{
232 .channels = hdd_channels_2_4_GHZ,
233 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
234 .band = IEEE80211_BAND_2GHZ,
235 .bitrates = g_mode_rates,
236 .n_bitrates = g_mode_rates_size,
237 .ht_cap.ht_supported = 1,
238 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
239 | IEEE80211_HT_CAP_GRN_FLD
240 | IEEE80211_HT_CAP_DSSSCCK40
241 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
242 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
243 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
244 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
245 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
246 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
247};
248
249#ifdef WLAN_FEATURE_P2P
250static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
251{
252 .channels = hdd_social_channels_2_4_GHZ,
253 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
254 .band = IEEE80211_BAND_2GHZ,
255 .bitrates = g_mode_rates,
256 .n_bitrates = g_mode_rates_size,
257 .ht_cap.ht_supported = 1,
258 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
259 | IEEE80211_HT_CAP_GRN_FLD
260 | IEEE80211_HT_CAP_DSSSCCK40
261 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
262 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
263 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
264 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
265 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
266 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
267};
268#endif
269
270static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
271{
272 .channels = hdd_channels_5_GHZ,
273 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
274 .band = IEEE80211_BAND_5GHZ,
275 .bitrates = a_mode_rates,
276 .n_bitrates = a_mode_rates_size,
277 .ht_cap.ht_supported = 1,
278 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
279 | IEEE80211_HT_CAP_GRN_FLD
280 | IEEE80211_HT_CAP_DSSSCCK40
281 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
282 | IEEE80211_HT_CAP_SGI_40
283 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
284 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
285 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
286 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
287 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
288 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
289};
290
291/* This structure contain information what kind of frame are expected in
292 TX/RX direction for each kind of interface */
293static const struct ieee80211_txrx_stypes
294wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
295 [NL80211_IFTYPE_STATION] = {
296 .tx = 0xffff,
297 .rx = BIT(SIR_MAC_MGMT_ACTION) |
298 BIT(SIR_MAC_MGMT_PROBE_REQ),
299 },
300 [NL80211_IFTYPE_AP] = {
301 .tx = 0xffff,
302 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
303 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
304 BIT(SIR_MAC_MGMT_PROBE_REQ) |
305 BIT(SIR_MAC_MGMT_DISASSOC) |
306 BIT(SIR_MAC_MGMT_AUTH) |
307 BIT(SIR_MAC_MGMT_DEAUTH) |
308 BIT(SIR_MAC_MGMT_ACTION),
309 },
310#ifdef WLAN_FEATURE_P2P
311 [NL80211_IFTYPE_P2P_CLIENT] = {
312 .tx = 0xffff,
313 .rx = BIT(SIR_MAC_MGMT_ACTION) |
314 BIT(SIR_MAC_MGMT_PROBE_REQ),
315 },
316 [NL80211_IFTYPE_P2P_GO] = {
317 /* This is also same as for SoftAP */
318 .tx = 0xffff,
319 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ) |
322 BIT(SIR_MAC_MGMT_DISASSOC) |
323 BIT(SIR_MAC_MGMT_AUTH) |
324 BIT(SIR_MAC_MGMT_DEAUTH) |
325 BIT(SIR_MAC_MGMT_ACTION),
326 },
327#endif
328};
329
330static struct cfg80211_ops wlan_hdd_cfg80211_ops;
331
332/* Data rate 100KBPS based on IE Index */
333struct index_data_rate_type
334{
335 v_U8_t beacon_rate_index;
336 v_U16_t supported_rate[4];
337};
338
339/* 11B, 11G Rate table include Basic rate and Extended rate
340 The IDX field is the rate index
341 The HI field is the rate when RSSI is strong or being ignored
342 (in this case we report actual rate)
343 The MID field is the rate when RSSI is moderate
344 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
345 The LO field is the rate when RSSI is low
346 (in this case we don't report rates, actual current rate used)
347 */
348static const struct
349{
350 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700351 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700352} supported_data_rate[] =
353{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700354/* IDX HI HM LM LO (RSSI-based index */
355 {2, { 10, 10, 10, 0}},
356 {4, { 20, 20, 10, 0}},
357 {11, { 55, 20, 10, 0}},
358 {12, { 60, 55, 20, 0}},
359 {18, { 90, 55, 20, 0}},
360 {22, {110, 55, 20, 0}},
361 {24, {120, 90, 60, 0}},
362 {36, {180, 120, 60, 0}},
363 {44, {220, 180, 60, 0}},
364 {48, {240, 180, 90, 0}},
365 {66, {330, 180, 90, 0}},
366 {72, {360, 240, 90, 0}},
367 {96, {480, 240, 120, 0}},
368 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700369};
370
371/* MCS Based rate table */
372static struct index_data_rate_type supported_mcs_rate[] =
373{
374/* MCS L20 L40 S20 S40 */
375 {0, {65, 135, 72, 150}},
376 {1, {130, 270, 144, 300}},
377 {2, {195, 405, 217, 450}},
378 {3, {260, 540, 289, 600}},
379 {4, {390, 810, 433, 900}},
380 {5, {520, 1080, 578, 1200}},
381 {6, {585, 1215, 650, 1350}},
382 {7, {650, 1350, 722, 1500}}
383};
384
385extern struct net_device_ops net_ops_struct;
386
387/*
388 * FUNCTION: wlan_hdd_cfg80211_init
389 * This function is called by hdd_wlan_startup()
390 * during initialization.
391 * This function is used to initialize and register wiphy structure.
392 */
393struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
394{
395 struct wiphy *wiphy;
396 ENTER();
397
398 /*
399 * Create wiphy device
400 */
401 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
402
403 if (!wiphy)
404 {
405 /* Print error and jump into err label and free the memory */
406 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
407 return NULL;
408 }
409
410 return wiphy;
411}
412
413/*
414 * FUNCTION: wlan_hdd_cfg80211_update_band
415 * This function is called from the supplicant through a
416 * private ioctl to change the band value
417 */
418int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
419{
Jeff Johnsone7245742012-09-05 17:12:55 -0700420 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700421 switch(eBand)
422 {
423 case eCSR_BAND_24:
424 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
425 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
426 break;
427 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700428#ifdef WLAN_FEATURE_P2P
429 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
430#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700431 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700432#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700433 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
434 break;
435 case eCSR_BAND_ALL:
436 default:
437 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
438 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
439 }
440 return 0;
441}
442/*
443 * FUNCTION: wlan_hdd_cfg80211_init
444 * This function is called by hdd_wlan_startup()
445 * during initialization.
446 * This function is used to initialize and register wiphy structure.
447 */
448int wlan_hdd_cfg80211_register(struct device *dev,
449 struct wiphy *wiphy,
450 hdd_config_t *pCfg
451 )
452{
Jeff Johnsone7245742012-09-05 17:12:55 -0700453 ENTER();
454
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 /* Now bind the underlying wlan device with wiphy */
456 set_wiphy_dev(wiphy, dev);
457
458 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
459
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700460 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700461
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700462#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700463 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
464 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
465 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700466 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700467#endif
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700468 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
469 driver can still register regulatory callback and
470 it will get CRDA setting in wiphy->band[], but
471 driver need to determine what to do with both
472 regulatory settings */
473 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700474
Jeff Johnson295189b2012-06-20 16:38:30 -0700475 wiphy->max_scan_ssids = MAX_SCAN_SSID;
476
477 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
478
479 /* Supports STATION & AD-HOC modes right now */
480 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
481 | BIT(NL80211_IFTYPE_ADHOC)
482#ifdef WLAN_FEATURE_P2P
483 | BIT(NL80211_IFTYPE_P2P_CLIENT)
484 | BIT(NL80211_IFTYPE_P2P_GO)
485#endif
486 | BIT(NL80211_IFTYPE_AP);
487
488 /* Before registering we need to update the ht capabilitied based
489 * on ini values*/
490 if( !pCfg->ShortGI20MhzEnable )
491 {
492 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
493 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
494 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
495 }
496
497 if( !pCfg->ShortGI40MhzEnable )
498 {
499 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
500 }
501
502 if( !pCfg->nChannelBondingMode5GHz )
503 {
504 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
505 }
506
507 /*Initialize band capability*/
508 switch(pCfg->nBandCapability)
509 {
510 case eCSR_BAND_24:
511 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
512 break;
513 case eCSR_BAND_5G:
514#ifdef WLAN_FEATURE_P2P
515 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
516#endif
517 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
518 break;
519 case eCSR_BAND_ALL:
520 default:
521 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
522 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
523 }
524 /*Initialise the supported cipher suite details*/
525 wiphy->cipher_suites = hdd_cipher_suites;
526 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
527
528 /*signal strength in mBm (100*dBm) */
529 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
530
531#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
532#ifdef WLAN_FEATURE_P2P
533 wiphy->max_remain_on_channel_duration = 1000;
534#endif
535#endif
536
537 /* Register our wiphy dev with cfg80211 */
538 if (0 > wiphy_register(wiphy))
539 {
540 /* print eror */
541 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
542 return -EIO;
543 }
544
545 EXIT();
546 return 0;
547}
548
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700549/* In this function we will try to get default country code from crda.
550 If the gCrdaDefaultCountryCode is configured in ini file,
551 we will try to call user space crda to get the regulatory settings for
552 that country. We will timeout if we can't get it from crda.
553 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
554*/
555int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
556{
557 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
558 if (memcmp(pCfg->crdaDefaultCountryCode,
559 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
560 {
561 init_completion(&pHddCtx->driver_crda_req);
562 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
563 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
564 CRDA_WAIT_TIME);
565 }
566 return 0;
567}
568
Jeff Johnson295189b2012-06-20 16:38:30 -0700569/* In this function we will do all post VOS start initialization.
570 In this function we will register for all frame in which supplicant
571 is interested.
572*/
573void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
574{
575#ifdef WLAN_FEATURE_P2P
576 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
577 /* Register for all P2P action, public action etc frames */
578 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
579
Jeff Johnsone7245742012-09-05 17:12:55 -0700580 ENTER();
581
Jeff Johnson295189b2012-06-20 16:38:30 -0700582 /* Right now we are registering these frame when driver is getting
583 initialized. Once we will move to 2.6.37 kernel, in which we have
584 frame register ops, we will move this code as a part of that */
585 /* GAS Initial Request */
586 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
587 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
588
589 /* GAS Initial Response */
590 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
591 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
592
593 /* GAS Comeback Request */
594 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
595 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
596
597 /* GAS Comeback Response */
598 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
599 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
600
601 /* P2P Public Action */
602 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
603 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
604 P2P_PUBLIC_ACTION_FRAME_SIZE );
605
606 /* P2P Action */
607 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
608 (v_U8_t*)P2P_ACTION_FRAME,
609 P2P_ACTION_FRAME_SIZE );
610#endif /* WLAN_FEATURE_P2P */
611}
612
613void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
614{
615#ifdef WLAN_FEATURE_P2P
616 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
617 /* Register for all P2P action, public action etc frames */
618 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
619
Jeff Johnsone7245742012-09-05 17:12:55 -0700620 ENTER();
621
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 /* Right now we are registering these frame when driver is getting
623 initialized. Once we will move to 2.6.37 kernel, in which we have
624 frame register ops, we will move this code as a part of that */
625 /* GAS Initial Request */
626
627 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
628 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
629
630 /* GAS Initial Response */
631 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
632 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
633
634 /* GAS Comeback Request */
635 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
636 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
637
638 /* GAS Comeback Response */
639 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
640 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
641
642 /* P2P Public Action */
643 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
644 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
645 P2P_PUBLIC_ACTION_FRAME_SIZE );
646
647 /* P2P Action */
648 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
649 (v_U8_t*)P2P_ACTION_FRAME,
650 P2P_ACTION_FRAME_SIZE );
651#endif /* WLAN_FEATURE_P2P */
652}
653
654#ifdef FEATURE_WLAN_WAPI
655void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
656 const u8 *mac_addr, u8 *key , int key_Len)
657{
658 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
659 tCsrRoamSetKey setKey;
660 v_BOOL_t isConnected = TRUE;
661 int status = 0;
662 v_U32_t roamId= 0xFF;
663 tANI_U8 *pKeyPtr = NULL;
664 int n = 0;
665
666 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
667 __func__,pAdapter->device_mode);
668
669 setKey.keyId = key_index; // Store Key ID
670 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
671 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
672 setKey.paeRole = 0 ; // the PAE role
673 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
674 {
675 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
676 }
677 else
678 {
679 isConnected = hdd_connIsConnected(pHddStaCtx);
680 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
681 }
682 setKey.keyLength = key_Len;
683 pKeyPtr = setKey.Key;
684 memcpy( pKeyPtr, key, key_Len);
685
686 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
687 __func__, key_Len);
688 for (n = 0 ; n < key_Len; n++)
689 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
690 __func__,n,setKey.Key[n]);
691
692 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
693 if ( isConnected )
694 {
695 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
696 pAdapter->sessionId, &setKey, &roamId );
697 }
698 if ( status != 0 )
699 {
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
701 "[%4d] sme_RoamSetKey returned ERROR status= %d",
702 __LINE__, status );
703 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
704 }
705}
706#endif /* FEATURE_WLAN_WAPI*/
707
708#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
709int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
710 beacon_data_t **ppBeacon,
711 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700712#else
713int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
714 beacon_data_t **ppBeacon,
715 struct cfg80211_beacon_data *params,
716 int dtim_period)
717#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700718{
719 int size;
720 beacon_data_t *beacon = NULL;
721 beacon_data_t *old = NULL;
722 int head_len,tail_len;
723
Jeff Johnsone7245742012-09-05 17:12:55 -0700724 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700725 if (params->head && !params->head_len)
726 return -EINVAL;
727
728 old = pAdapter->sessionCtx.ap.beacon;
729
730 if (!params->head && !old)
731 return -EINVAL;
732
733 if (params->tail && !params->tail_len)
734 return -EINVAL;
735
736#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
737 /* Kernel 3.0 is not updating dtim_period for set beacon */
738 if (!params->dtim_period)
739 return -EINVAL;
740#endif
741
742 if(params->head)
743 head_len = params->head_len;
744 else
745 head_len = old->head_len;
746
747 if(params->tail || !old)
748 tail_len = params->tail_len;
749 else
750 tail_len = old->tail_len;
751
752 size = sizeof(beacon_data_t) + head_len + tail_len;
753
754 beacon = kzalloc(size, GFP_KERNEL);
755
756 if( beacon == NULL )
757 return -ENOMEM;
758
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700759#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700760 if(params->dtim_period || !old )
761 beacon->dtim_period = params->dtim_period;
762 else
763 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700764#else
765 if(dtim_period || !old )
766 beacon->dtim_period = dtim_period;
767 else
768 beacon->dtim_period = old->dtim_period;
769#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700770
771 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
772 beacon->tail = beacon->head + head_len;
773 beacon->head_len = head_len;
774 beacon->tail_len = tail_len;
775
776 if(params->head) {
777 memcpy (beacon->head,params->head,beacon->head_len);
778 }
779 else {
780 if(old)
781 memcpy (beacon->head,old->head,beacon->head_len);
782 }
783
784 if(params->tail) {
785 memcpy (beacon->tail,params->tail,beacon->tail_len);
786 }
787 else {
788 if(old)
789 memcpy (beacon->tail,old->tail,beacon->tail_len);
790 }
791
792 *ppBeacon = beacon;
793
794 kfree(old);
795
796 return 0;
797
798}
Jeff Johnson295189b2012-06-20 16:38:30 -0700799
800v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
801{
802 int left = length;
803 v_U8_t *ptr = pIes;
804 v_U8_t elem_id,elem_len;
805
806 while(left >= 2)
807 {
808 elem_id = ptr[0];
809 elem_len = ptr[1];
810 left -= 2;
811 if(elem_len > left)
812 {
813 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700814 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700815 eid,elem_len,left);
816 return NULL;
817 }
818 if (elem_id == eid)
819 {
820 return ptr;
821 }
822
823 left -= elem_len;
824 ptr += (elem_len + 2);
825 }
826 return NULL;
827}
828
Jeff Johnson295189b2012-06-20 16:38:30 -0700829/* Check if rate is 11g rate or not */
830static int wlan_hdd_rate_is_11g(u8 rate)
831{
832 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
833 u8 i;
834 for (i = 0; i < 8; i++)
835 {
836 if(rate == gRateArray[i])
837 return TRUE;
838 }
839 return FALSE;
840}
841
842/* Check for 11g rate and set proper 11g only mode */
843static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
844 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
845{
846 u8 i, num_rates = pIe[0];
847
848 pIe += 1;
849 for ( i = 0; i < num_rates; i++)
850 {
851 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
852 {
853 /* If rate set have 11g rate than change the mode to 11G */
854 *pSapHw_mode = eSAP_DOT11_MODE_11g;
855 if (pIe[i] & BASIC_RATE_MASK)
856 {
857 /* If we have 11g rate as basic rate, it means mode
858 is 11g only mode.
859 */
860 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
861 *pCheckRatesfor11g = FALSE;
862 }
863 }
864 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
865 {
866 *require_ht = TRUE;
867 }
868 }
869 return;
870}
871
872static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
873{
874 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
875 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
876 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
877 u8 checkRatesfor11g = TRUE;
878 u8 require_ht = FALSE;
879 u8 *pIe=NULL;
880
881 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
882
883 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
884 pBeacon->head_len, WLAN_EID_SUPP_RATES);
885 if (pIe != NULL)
886 {
887 pIe += 1;
888 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
889 &pConfig->SapHw_mode);
890 }
891
892 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
893 WLAN_EID_EXT_SUPP_RATES);
894 if (pIe != NULL)
895 {
896
897 pIe += 1;
898 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
899 &pConfig->SapHw_mode);
900 }
901
902 if( pConfig->channel > 14 )
903 {
904 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
905 }
906
907 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
908 WLAN_EID_HT_CAPABILITY);
909
910 if(pIe)
911 {
912 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
913 if(require_ht)
914 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
915 }
916}
917
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700918#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700919static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
920 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700921#else
922static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
923 struct cfg80211_beacon_data *params)
924#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700925{
926 v_U8_t *genie;
927 v_U8_t total_ielen = 0, ielen = 0;
928 v_U8_t *pIe = NULL;
929 v_U8_t addIE[1] = {0};
930 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -0700931 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700932
933 genie = vos_mem_malloc(MAX_GENIE_LEN);
934
935 if(genie == NULL) {
936
937 return -ENOMEM;
938 }
939
940 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
941
942 if(pIe)
943 {
944 /*Copy the wps IE*/
945 ielen = pIe[1] + 2;
946 if( ielen <=MAX_GENIE_LEN)
947 {
948 vos_mem_copy(genie, pIe, ielen);
949 }
950 else
951 {
952 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700953 ret = -EINVAL;
954 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700955 }
956 total_ielen = ielen;
957 }
958
959#ifdef WLAN_FEATURE_WFD
960 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
961
962 if(pIe)
963 {
964 ielen = pIe[1] + 2;
965 if(total_ielen + ielen <= MAX_GENIE_LEN) {
966 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
967 }
968 else {
969 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700970 ret = -EINVAL;
971 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700972 }
973 total_ielen += ielen;
974 }
975#endif
976
977#ifdef WLAN_FEATURE_P2P
978 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
979
980 if(pIe)
981 {
982 ielen = pIe[1] + 2;
983 if(total_ielen + ielen <= MAX_GENIE_LEN)
984 {
985 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
986 }
987 else
988 {
989 hddLog( VOS_TRACE_LEVEL_ERROR,
990 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -0700991 ret = -EINVAL;
992 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 }
994 total_ielen += ielen;
995 }
996#endif
997
998 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
999 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1000 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1001 {
1002 hddLog(LOGE,
1003 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001004 ret = -EINVAL;
1005 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001006 }
1007
1008 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1009 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1010 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1011 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1012 ==eHAL_STATUS_FAILURE)
1013 {
1014 hddLog(LOGE,
1015 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001016 ret = -EINVAL;
1017 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001018 }
1019
1020 // Added for ProResp IE
1021 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1022 {
1023 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1024 u8 probe_rsp_ie_len[3] = {0};
1025 u8 counter = 0;
1026 /* Check Probe Resp Length if it is greater then 255 then Store
1027 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1028 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1029 Store More then 255 bytes into One Variable.
1030 */
1031 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1032 {
1033 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1034 {
1035 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1036 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1037 }
1038 else
1039 {
1040 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1041 rem_probe_resp_ie_len = 0;
1042 }
1043 }
1044
1045 rem_probe_resp_ie_len = 0;
1046
1047 if (probe_rsp_ie_len[0] > 0)
1048 {
1049 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1050 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1051 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1052 probe_rsp_ie_len[0], NULL,
1053 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1054 {
1055 hddLog(LOGE,
1056 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001057 ret = -EINVAL;
1058 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001059 }
1060 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1061 }
1062
1063 if (probe_rsp_ie_len[1] > 0)
1064 {
1065 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1066 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1067 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1068 probe_rsp_ie_len[1], NULL,
1069 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1070 {
1071 hddLog(LOGE,
1072 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001073 ret = -EINVAL;
1074 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001075 }
1076 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1077 }
1078
1079 if (probe_rsp_ie_len[2] > 0)
1080 {
1081 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1082 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1083 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1084 probe_rsp_ie_len[2], NULL,
1085 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1086 {
1087 hddLog(LOGE,
1088 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001089 ret = -EINVAL;
1090 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001091 }
1092 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1093 }
1094
1095 if (probe_rsp_ie_len[1] == 0 )
1096 {
1097 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1098 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1099 eANI_BOOLEAN_FALSE) )
1100 {
1101 hddLog(LOGE,
1102 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1103 }
1104 }
1105
1106 if (probe_rsp_ie_len[2] == 0 )
1107 {
1108 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1109 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1110 eANI_BOOLEAN_FALSE) )
1111 {
1112 hddLog(LOGE,
1113 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1114 }
1115 }
1116
1117 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1118 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1119 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1120 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1121 == eHAL_STATUS_FAILURE)
1122 {
1123 hddLog(LOGE,
1124 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001125 ret = -EINVAL;
1126 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001127 }
1128 }
1129 else
1130 {
1131 // Reset WNI_CFG_PROBE_RSP Flags
1132 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1133
1134 hddLog(VOS_TRACE_LEVEL_INFO,
1135 "%s: No Probe Response IE received in set beacon",
1136 __func__);
1137 }
1138
1139 // Added for AssocResp IE
1140 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1141 {
1142 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1143 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1144 params->assocresp_ies_len, NULL,
1145 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1146 {
1147 hddLog(LOGE,
1148 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001149 ret = -EINVAL;
1150 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001151 }
1152
1153 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1154 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1155 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1156 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1157 == eHAL_STATUS_FAILURE)
1158 {
1159 hddLog(LOGE,
1160 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001161 ret = -EINVAL;
1162 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 }
1164 }
1165 else
1166 {
1167 hddLog(VOS_TRACE_LEVEL_INFO,
1168 "%s: No Assoc Response IE received in set beacon",
1169 __func__);
1170
1171 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1172 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1173 eANI_BOOLEAN_FALSE) )
1174 {
1175 hddLog(LOGE,
1176 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1177 }
1178 }
1179
Jeff Johnsone7245742012-09-05 17:12:55 -07001180done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001181 vos_mem_free(genie);
1182 return 0;
1183}
Jeff Johnson295189b2012-06-20 16:38:30 -07001184
1185/*
1186 * FUNCTION: wlan_hdd_validate_operation_channel
1187 * called by wlan_hdd_cfg80211_start_bss() and
1188 * wlan_hdd_cfg80211_set_channel()
1189 * This function validates whether given channel is part of valid
1190 * channel list.
1191 */
1192static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1193{
1194
1195 v_U32_t num_ch = 0;
1196 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1197 u32 indx = 0;
1198 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1199
1200 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1201
1202 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1203 valid_ch, &num_ch))
1204 {
1205 hddLog(VOS_TRACE_LEVEL_ERROR,
1206 "%s: failed to get valid channel list\n", __func__);
1207 return VOS_STATUS_E_FAILURE;
1208 }
1209
1210 for (indx = 0; indx < num_ch; indx++)
1211 {
1212 if (channel == valid_ch[indx])
1213 {
1214 break;
1215 }
1216 }
1217
1218 if (indx >= num_ch)
1219 {
1220 hddLog(VOS_TRACE_LEVEL_ERROR,
1221 "%s: Invalid Channel [%d] \n", __func__, channel);
1222 return VOS_STATUS_E_FAILURE;
1223 }
1224 return VOS_STATUS_SUCCESS;
1225
1226}
1227
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001228
Jeff Johnson295189b2012-06-20 16:38:30 -07001229#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1230static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1231 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001232#else
1233static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1234 struct cfg80211_beacon_data *params,
1235 const u8 *ssid, size_t ssid_len,
1236 enum nl80211_hidden_ssid hidden_ssid)
1237#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001238{
1239 tsap_Config_t *pConfig;
1240 beacon_data_t *pBeacon = NULL;
1241 struct ieee80211_mgmt *pMgmt_frame;
1242 v_U8_t *pIe=NULL;
1243 v_U16_t capab_info;
1244 eCsrAuthType RSNAuthType;
1245 eCsrEncryptionType RSNEncryptType;
1246 eCsrEncryptionType mcRSNEncryptType;
1247 int status = VOS_STATUS_SUCCESS;
1248 tpWLAN_SAPEventCB pSapEventCallback;
1249 hdd_hostapd_state_t *pHostapdState;
1250 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1251 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1252 struct qc_mac_acl_entry *acl_entry = NULL;
1253 v_SINT_t i;
1254
1255 ENTER();
1256
1257 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1258
1259 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1260
1261 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1262
1263 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1264
1265 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1266
1267 //channel is already set in the set_channel Call back
1268 //pConfig->channel = pCommitConfig->channel;
1269
1270 /*Protection parameter to enable or disable*/
1271 pConfig->protEnabled =
1272 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1273
1274 pConfig->dtim_period = pBeacon->dtim_period;
1275
1276 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1277 pConfig->dtim_period);
1278
1279
Jeff Johnson32d95a32012-09-10 13:15:23 -07001280 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
1281 {
1282 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001284 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001285 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001286 tANI_BOOLEAN restartNeeded;
1287 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1288 pConfig->ieee80211d = 1;
1289 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1290 sme_setRegInfo(hHal, pConfig->countryCode);
1291 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1292 /*
1293 * If auto channel is configured i.e. channel is 0,
1294 * so skip channel validation.
1295 */
1296 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001297 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001298 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1299 {
1300 hddLog(VOS_TRACE_LEVEL_ERROR,
1301 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1302 return -EINVAL;
1303 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001304 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001305 /*
1306 * Validate the given channel range for the given country code
1307 */
1308 else
1309 {
1310 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1311 WLANSAP_SetChannelRange(hHal,hdd_pConfig->apStartChannelNum,hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1312 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001313 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001314 else
1315 {
1316 pConfig->ieee80211d = 0;
1317 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001318 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001319 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 {
1321 pConfig->ieee80211d = 0;
1322 }
1323 pConfig->authType = eSAP_AUTO_SWITCH;
1324
1325 capab_info = pMgmt_frame->u.beacon.capab_info;
1326
1327 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1328 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1329
1330 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1331
1332 /*Set wps station to configured*/
1333 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1334
1335 if(pIe)
1336 {
1337 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1338 {
1339 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1340 return -EINVAL;
1341 }
1342 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1343 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001344 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001345 /* Check 15 bit of WPS IE as it contain information for wps state
1346 * WPS state
1347 */
1348 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1349 {
1350 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1351 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1352 {
1353 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1354 }
1355 }
1356 }
1357 else
1358 {
1359 pConfig->wps_state = SAP_WPS_DISABLED;
1360 }
1361 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1362
1363 pConfig->RSNWPAReqIELength = 0;
1364 pConfig->pRSNWPAReqIE = NULL;
1365 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1366 WLAN_EID_RSN);
1367 if(pIe && pIe[1])
1368 {
1369 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1370 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1371 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1372 /* The actual processing may eventually be more extensive than
1373 * this. Right now, just consume any PMKIDs that are sent in
1374 * by the app.
1375 * */
1376 status = hdd_softap_unpackIE(
1377 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1378 &RSNEncryptType,
1379 &mcRSNEncryptType,
1380 &RSNAuthType,
1381 pConfig->pRSNWPAReqIE[1]+2,
1382 pConfig->pRSNWPAReqIE );
1383
1384 if( VOS_STATUS_SUCCESS == status )
1385 {
1386 /* Now copy over all the security attributes you have
1387 * parsed out
1388 * */
1389 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1390 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1391 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1392 = RSNEncryptType;
1393 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1394 "EncryptionType = %d mcEncryptionType = %d\n"),
1395 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1396 }
1397 }
1398
1399 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1400 pBeacon->tail, pBeacon->tail_len);
1401
1402 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1403 {
1404 if (pConfig->pRSNWPAReqIE)
1405 {
1406 /*Mixed mode WPA/WPA2*/
1407 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1408 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1409 }
1410 else
1411 {
1412 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1413 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1414 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1415 status = hdd_softap_unpackIE(
1416 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1417 &RSNEncryptType,
1418 &mcRSNEncryptType,
1419 &RSNAuthType,
1420 pConfig->pRSNWPAReqIE[1]+2,
1421 pConfig->pRSNWPAReqIE );
1422
1423 if( VOS_STATUS_SUCCESS == status )
1424 {
1425 /* Now copy over all the security attributes you have
1426 * parsed out
1427 * */
1428 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1429 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1430 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1431 = RSNEncryptType;
1432 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1433 "EncryptionType = %d mcEncryptionType = %d\n"),
1434 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1435 }
1436 }
1437 }
1438
1439 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1440
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001441#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001442 if (params->ssid != NULL)
1443 {
1444 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1445 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1446 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1447 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1448 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001449#else
1450 if (ssid != NULL)
1451 {
1452 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1453 pConfig->SSIDinfo.ssid.length = ssid_len;
1454 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1455 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1456 }
1457#endif
1458
Jeff Johnson295189b2012-06-20 16:38:30 -07001459 vos_mem_copy(pConfig->self_macaddr.bytes,
1460 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1461
1462 /* default value */
1463 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1464 pConfig->num_accept_mac = 0;
1465 pConfig->num_deny_mac = 0;
1466
1467 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1468 pBeacon->tail, pBeacon->tail_len);
1469
1470 /* pIe for black list is following form:
1471 type : 1 byte
1472 length : 1 byte
1473 OUI : 4 bytes
1474 acl type : 1 byte
1475 no of mac addr in black list: 1 byte
1476 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1477 */
1478 if ((pIe != NULL) && (pIe[1] != 0))
1479 {
1480 pConfig->SapMacaddr_acl = pIe[6];
1481 pConfig->num_deny_mac = pIe[7];
1482 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1483 pIe[6], pIe[7]);
1484 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1485 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1486 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1487 for (i = 0; i < pConfig->num_deny_mac; i++)
1488 {
1489 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1490 acl_entry++;
1491 }
1492 }
1493 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1494 pBeacon->tail, pBeacon->tail_len);
1495
1496 /* pIe for white list is following form:
1497 type : 1 byte
1498 length : 1 byte
1499 OUI : 4 bytes
1500 acl type : 1 byte
1501 no of mac addr in white list: 1 byte
1502 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1503 */
1504 if ((pIe != NULL) && (pIe[1] != 0))
1505 {
1506 pConfig->SapMacaddr_acl = pIe[6];
1507 pConfig->num_accept_mac = pIe[7];
1508 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1509 pIe[6], pIe[7]);
1510 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1511 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1512 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1513 for (i = 0; i < pConfig->num_accept_mac; i++)
1514 {
1515 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1516 acl_entry++;
1517 }
1518 }
1519 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1520
Jeff Johnsone7245742012-09-05 17:12:55 -07001521#ifdef WLAN_FEATURE_11AC
1522 if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1523 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1524 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) )
1525 {
1526 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1527 }
1528#endif
1529
Jeff Johnson295189b2012-06-20 16:38:30 -07001530 // ht_capab is not what the name conveys,this is used for protection bitmap
1531 pConfig->ht_capab =
1532 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1533
1534 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1535 {
1536 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1537 return -EINVAL;
1538 }
1539
1540 //Uapsd Enabled Bit
1541 pConfig->UapsdEnable =
1542 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1543 //Enable OBSS protection
1544 pConfig->obssProtEnabled =
1545 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1546
1547 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1548 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1549 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1550 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1551 (int)pConfig->channel);
1552 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1553 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1554 pConfig->authType);
1555 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1556 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1557 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1558 pConfig->protEnabled, pConfig->obssProtEnabled);
1559
1560 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1561 {
1562 //Bss already started. just return.
1563 //TODO Probably it should update some beacon params.
1564 hddLog( LOGE, "Bss Already started...Ignore the request");
1565 EXIT();
1566 return 0;
1567 }
1568
1569 pConfig->persona = pHostapdAdapter->device_mode;
1570
1571 pSapEventCallback = hdd_hostapd_SAPEventCB;
1572 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1573 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1574 {
1575 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1576 return -EINVAL;
1577 }
1578
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001579 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001580 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1581
1582 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1583
1584 if (!VOS_IS_STATUS_SUCCESS(status))
1585 {
1586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1587 ("ERROR: HDD vos wait for single_event failed!!\n"));
1588 VOS_ASSERT(0);
1589 }
1590
1591 //Succesfully started Bss update the state bit.
1592 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1593
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001594#ifdef WLAN_FEATURE_P2P_DEBUG
1595 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1596 {
1597 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1598 {
1599 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1600 hddLog(LOGE,"[P2P State] From Go nego completed to "
1601 "Non-autonomus Group started");
1602 }
1603 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1604 {
1605 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1606 hddLog(LOGE,"[P2P State] From Inactive to "
1607 "Autonomus Group started");
1608 }
1609 }
1610#endif
1611
Jeff Johnson295189b2012-06-20 16:38:30 -07001612 pHostapdState->bCommit = TRUE;
1613 EXIT();
1614
1615 return 0;
1616}
1617
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001618#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001619static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1620 struct net_device *dev,
1621 struct beacon_parameters *params)
1622{
1623 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1624 int status=VOS_STATUS_SUCCESS;
1625
1626 ENTER();
1627
1628 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1629
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001630 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1631 {
1632 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1633 "%s:LOGP in Progress. Ignore!!!", __func__);
1634 return -EAGAIN;
1635 }
1636
Jeff Johnson295189b2012-06-20 16:38:30 -07001637 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1638#ifdef WLAN_FEATURE_P2P
1639 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1640#endif
1641 )
1642 {
1643 beacon_data_t *old,*new;
1644
1645 old = pAdapter->sessionCtx.ap.beacon;
1646
1647 if (old)
1648 return -EALREADY;
1649
1650 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1651
1652 if(status != VOS_STATUS_SUCCESS)
1653 {
1654 hddLog(VOS_TRACE_LEVEL_FATAL,
1655 "%s:Error!!! Allocating the new beacon\n",__func__);
1656 return -EINVAL;
1657 }
1658
1659 pAdapter->sessionCtx.ap.beacon = new;
1660
1661 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1662 }
1663
1664 EXIT();
1665 return status;
1666}
1667
1668static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1669 struct net_device *dev,
1670 struct beacon_parameters *params)
1671{
1672 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1673 int status=VOS_STATUS_SUCCESS;
1674
1675 ENTER();
1676
1677 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1678 __func__,pAdapter->device_mode);
1679
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001680 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1681 {
1682 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1683 "%s:LOGP in Progress. Ignore!!!", __func__);
1684 return -EAGAIN;
1685 }
1686
Jeff Johnson295189b2012-06-20 16:38:30 -07001687 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1688#ifdef WLAN_FEATURE_P2P
1689 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1690#endif
1691 )
1692 {
1693 beacon_data_t *old,*new;
1694
1695 old = pAdapter->sessionCtx.ap.beacon;
1696
1697 if (!old)
1698 return -ENOENT;
1699
1700 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1701
1702 if(status != VOS_STATUS_SUCCESS) {
1703 hddLog(VOS_TRACE_LEVEL_FATAL,
1704 "%s: Error!!! Allocating the new beacon\n",__func__);
1705 return -EINVAL;
1706 }
1707
1708 pAdapter->sessionCtx.ap.beacon = new;
1709
1710 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1711 }
1712
1713 EXIT();
1714 return status;
1715}
1716
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001717#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1718
1719#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001720static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1721 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001722#else
1723static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1724 struct net_device *dev)
1725#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001726{
1727 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001728 hdd_context_t *pHddCtx = NULL;
1729 hdd_scaninfo_t *pScanInfo = NULL;
1730 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001731 VOS_STATUS status = 0;
1732
1733 ENTER();
1734
1735 if (NULL == pAdapter)
1736 {
1737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001738 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001739 return -ENODEV;
1740 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001741 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1742 {
1743 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1744 "%s:LOGP in Progress. Ignore!!!", __func__);
1745 return -EAGAIN;
1746 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001747
1748 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1749 if (NULL == pHddCtx)
1750 {
1751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001752 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001753 return -ENODEV;
1754 }
1755
1756 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1757 if (NULL == staAdapter)
1758 {
1759 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1760 if (NULL == staAdapter)
1761 {
1762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001763 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001764 return -ENODEV;
1765 }
1766 }
1767
1768 pScanInfo = &pHddCtx->scan_info;
1769
Jeff Johnson295189b2012-06-20 16:38:30 -07001770 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1771 {
1772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1773 return -EAGAIN;
1774 }
1775
1776 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1777
1778 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1779 __func__,pAdapter->device_mode);
1780
Jeff Johnsone7245742012-09-05 17:12:55 -07001781 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1782 {
1783 INIT_COMPLETION(staAdapter->abortscan_event_var);
1784 hdd_abort_mac_scan(staAdapter->pHddCtx);
1785 status = wait_for_completion_interruptible_timeout(
1786 &staAdapter->abortscan_event_var,
1787 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1788 if (!status)
1789 {
1790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1791 "%s: Timeout occured while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001792 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001793 VOS_ASSERT(pScanInfo->mScanPending);
1794 return 0;
1795 }
1796 }
1797
Jeff Johnson295189b2012-06-20 16:38:30 -07001798 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1799#ifdef WLAN_FEATURE_P2P
1800 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1801#endif
1802 )
1803 {
1804 beacon_data_t *old;
1805
1806 old = pAdapter->sessionCtx.ap.beacon;
1807
1808 if (!old)
1809 return -ENOENT;
1810
1811#ifdef CONFIG_CFG80211
1812 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1813#endif
1814
1815 mutex_lock(&pHddCtx->sap_lock);
1816 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1817 {
1818 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
1819 {
1820 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
1821
1822 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1823
1824 if (!VOS_IS_STATUS_SUCCESS(status))
1825 {
1826 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1827 ("ERROR: HDD vos wait for single_event failed!!\n"));
1828 VOS_ASSERT(0);
1829 }
1830 }
1831 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
1832 }
1833 mutex_unlock(&pHddCtx->sap_lock);
1834
1835 if(status != VOS_STATUS_SUCCESS)
1836 {
1837 hddLog(VOS_TRACE_LEVEL_FATAL,
1838 "%s:Error!!! Stopping the BSS\n",__func__);
1839 return -EINVAL;
1840 }
1841
1842 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1843 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
1844 ==eHAL_STATUS_FAILURE)
1845 {
1846 hddLog(LOGE,
1847 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
1848 }
1849
1850 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
1851 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1852 eANI_BOOLEAN_FALSE) )
1853 {
1854 hddLog(LOGE,
1855 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1856 }
1857
1858 // Reset WNI_CFG_PROBE_RSP Flags
1859 wlan_hdd_reset_prob_rspies(pAdapter);
1860
1861 pAdapter->sessionCtx.ap.beacon = NULL;
1862 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001863#ifdef WLAN_FEATURE_P2P_DEBUG
1864 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
1865 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
1866 {
1867 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
1868 "GO got removed");
1869 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
1870 }
1871#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001872 }
1873 EXIT();
1874 return status;
1875}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001876
1877#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
1878
1879static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
1880 struct net_device *dev,
1881 struct cfg80211_ap_settings *params)
1882{
1883 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1884 int status = VOS_STATUS_SUCCESS;
1885
1886 ENTER();
1887
1888 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n", pAdapter->device_mode);
1889
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001890 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1891 {
1892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1893 return -EAGAIN;
1894 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001895 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1896#ifdef WLAN_FEATURE_P2P
1897 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1898#endif
1899 )
1900 {
1901 beacon_data_t *old,*new;
1902
1903 old = pAdapter->sessionCtx.ap.beacon;
1904
1905 if (old)
1906 return -EALREADY;
1907
1908 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
1909
1910 if(status != VOS_STATUS_SUCCESS)
1911 {
1912 hddLog(VOS_TRACE_LEVEL_FATAL,
1913 "%s:Error!!! Allocating the new beacon\n",__func__);
1914 return -EINVAL;
1915 }
1916 pAdapter->sessionCtx.ap.beacon = new;
1917 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
1918 params->ssid_len, params->hidden_ssid);
1919 }
1920
1921 EXIT();
1922 return status;
1923}
1924
1925
1926static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
1927 struct net_device *dev,
1928 struct cfg80211_beacon_data *params)
1929{
1930 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1931 int status=VOS_STATUS_SUCCESS;
1932
1933 ENTER();
1934
1935 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1936 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001937 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1938 {
1939 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1940 return -EAGAIN;
1941 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001942
1943 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1944#ifdef WLAN_FEATURE_P2P
1945 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1946#endif
1947 )
1948 {
1949 beacon_data_t *old,*new;
1950
1951 old = pAdapter->sessionCtx.ap.beacon;
1952
1953 if (!old)
1954 return -ENOENT;
1955
1956 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
1957
1958 if(status != VOS_STATUS_SUCCESS) {
1959 hddLog(VOS_TRACE_LEVEL_FATAL,
1960 "%s: Error!!! Allocating the new beacon\n",__func__);
1961 return -EINVAL;
1962 }
1963
1964 pAdapter->sessionCtx.ap.beacon = new;
1965
1966 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
1967 }
1968
1969 EXIT();
1970 return status;
1971}
1972
1973#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
1974
Jeff Johnson295189b2012-06-20 16:38:30 -07001975
1976static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
1977 struct net_device *dev,
1978 struct bss_parameters *params)
1979{
1980 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1981
1982 ENTER();
1983
1984 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1985 __func__,pAdapter->device_mode);
1986
1987 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1988#ifdef WLAN_FEATURE_P2P
1989 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1990#endif
1991 )
1992 {
1993 /* ap_isolate == -1 means that in change bss, upper layer doesn't
1994 * want to update this parameter */
1995 if (-1 != params->ap_isolate)
1996 {
1997 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
1998 }
1999 }
2000
2001 EXIT();
2002 return 0;
2003}
2004
2005/*
2006 * FUNCTION: wlan_hdd_cfg80211_change_iface
2007 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2008 */
2009int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2010 struct net_device *ndev,
2011 enum nl80211_iftype type,
2012 u32 *flags,
2013 struct vif_params *params
2014 )
2015{
2016 struct wireless_dev *wdev;
2017 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2018 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002019 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002020 tCsrRoamProfile *pRoamProfile = NULL;
2021 eCsrRoamBssType LastBSSType;
2022 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2023 eMib_dot11DesiredBssType connectedBssType;
2024 VOS_STATUS status;
2025
2026 ENTER();
2027
2028 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2029 {
2030 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2031 return -EAGAIN;
2032 }
2033
2034 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2035 __func__, pAdapter->device_mode);
2036
2037 wdev = ndev->ieee80211_ptr;
2038
2039#ifdef WLAN_BTAMP_FEATURE
2040 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2041 (NL80211_IFTYPE_ADHOC == type)||
2042 (NL80211_IFTYPE_AP == type)||
2043 (NL80211_IFTYPE_P2P_GO == type))
2044 {
2045 pHddCtx->isAmpAllowed = VOS_FALSE;
2046 // stop AMP traffic
2047 status = WLANBAP_StopAmp();
2048 if(VOS_STATUS_SUCCESS != status )
2049 {
2050 pHddCtx->isAmpAllowed = VOS_TRUE;
2051 hddLog(VOS_TRACE_LEVEL_FATAL,
2052 "%s: Failed to stop AMP", __func__);
2053 return -EINVAL;
2054 }
2055 }
2056#endif //WLAN_BTAMP_FEATURE
2057 /* Reset the current device mode bit mask*/
2058 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2059
2060 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2061#ifdef WLAN_FEATURE_P2P
2062 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002063 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002064#endif
2065 )
2066 {
2067 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2068 pRoamProfile = &pWextState->roamProfile;
2069 LastBSSType = pRoamProfile->BSSType;
2070
2071 switch (type)
2072 {
2073 case NL80211_IFTYPE_STATION:
2074#ifdef WLAN_FEATURE_P2P
2075 case NL80211_IFTYPE_P2P_CLIENT:
2076#endif
2077 hddLog(VOS_TRACE_LEVEL_INFO,
2078 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2079 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002080#ifdef WLAN_FEATURE_11AC
2081 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2082 {
2083 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2084 }
2085#endif
2086 pRoamProfile->phyMode =
2087 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002088 wdev->iftype = type;
2089#ifdef WLAN_FEATURE_P2P
2090 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2091 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2092#endif
2093 break;
2094 case NL80211_IFTYPE_ADHOC:
2095 hddLog(VOS_TRACE_LEVEL_INFO,
2096 "%s: setting interface Type to ADHOC", __func__);
2097 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2098 pRoamProfile->phyMode =
2099 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2100 wdev->iftype = type;
2101 break;
2102
2103 case NL80211_IFTYPE_AP:
2104#ifdef WLAN_FEATURE_P2P
2105 case NL80211_IFTYPE_P2P_GO:
2106#endif
2107 {
2108 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2109 "%s: setting interface Type to %s", __func__,
2110 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2111
Mohit Khanna0f232092012-09-11 14:46:08 -07002112 if (NL80211_IFTYPE_AP == type)
2113 {
2114 /* As Loading WLAN Driver one interface being created for p2p device
2115 * address. This will take one HW STA and the max number of clients
2116 * that can connect to softAP will be reduced by one. so while changing
2117 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2118 * interface as it is not required in SoftAP mode.
2119 */
2120
2121 // Get P2P Adapter
2122 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2123
2124 if (pP2pAdapter)
2125 {
2126 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2127 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2128 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2129 }
2130 }
2131
Jeff Johnson295189b2012-06-20 16:38:30 -07002132 //De-init the adapter.
2133 hdd_stop_adapter( pHddCtx, pAdapter );
2134 hdd_deinit_adapter( pHddCtx, pAdapter );
2135 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2136#ifdef WLAN_SOFTAP_FEATURE
2137#ifdef WLAN_FEATURE_P2P
2138 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2139 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2140#else
2141 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2142#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002143
2144 //Disable BMPS and IMPS if enabled
2145 //before starting Go
2146 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2147 {
2148 if(VOS_STATUS_E_FAILURE ==
2149 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2150 {
2151 //Fail to Exit BMPS
2152 VOS_ASSERT(0);
2153 }
2154 }
2155
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002156 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2157 (pConfig->apRandomBssidEnabled))
2158 {
2159 /* To meet Android requirements create a randomized
2160 MAC address of the form 02:1A:11:Fx:xx:xx */
2161 get_random_bytes(&ndev->dev_addr[3], 3);
2162 ndev->dev_addr[0] = 0x02;
2163 ndev->dev_addr[1] = 0x1A;
2164 ndev->dev_addr[2] = 0x11;
2165 ndev->dev_addr[3] |= 0xF0;
2166 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2167 VOS_MAC_ADDR_SIZE);
2168 pr_info("wlan: Generated HotSpot BSSID "
2169 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2170 ndev->dev_addr[0],
2171 ndev->dev_addr[1],
2172 ndev->dev_addr[2],
2173 ndev->dev_addr[3],
2174 ndev->dev_addr[4],
2175 ndev->dev_addr[5]);
2176 }
2177
Jeff Johnson295189b2012-06-20 16:38:30 -07002178 hdd_set_ap_ops( pAdapter->dev );
2179
2180 status = hdd_init_ap_mode(pAdapter);
2181 if(status != VOS_STATUS_SUCCESS)
2182 {
2183 hddLog(VOS_TRACE_LEVEL_FATAL,
2184 "%s: Error initializing the ap mode", __func__);
2185 return -EINVAL;
2186 }
2187 hdd_set_conparam(1);
2188
2189#endif
2190 /*interface type changed update in wiphy structure*/
2191 if(wdev)
2192 {
2193 wdev->iftype = type;
2194 pHddCtx->change_iface = type;
2195 }
2196 else
2197 {
2198 hddLog(VOS_TRACE_LEVEL_ERROR,
2199 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2200 return -EINVAL;
2201 }
2202 goto done;
2203 }
2204
2205 default:
2206 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2207 __func__);
2208 return -EOPNOTSUPP;
2209 }
2210 }
2211 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2212#ifdef WLAN_FEATURE_P2P
2213 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2214#endif
2215 )
2216 {
2217 switch(type)
2218 {
2219 case NL80211_IFTYPE_STATION:
2220#ifdef WLAN_FEATURE_P2P
2221 case NL80211_IFTYPE_P2P_CLIENT:
2222#endif
2223 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002224 hdd_stop_adapter( pHddCtx, pAdapter );
2225 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002226 wdev->iftype = type;
2227#ifdef WLAN_FEATURE_P2P
2228 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2229 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
2230#endif
2231 hdd_set_conparam(0);
2232 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002233 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2234 hdd_set_station_ops( pAdapter->dev );
2235 status = hdd_init_station_mode( pAdapter );
2236 if( VOS_STATUS_SUCCESS != status )
2237 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002238 /* In case of JB, for P2P-GO, only change interface will be called,
2239 * This is the right place to enable back bmps_imps()
2240 */
2241 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002242 goto done;
2243 case NL80211_IFTYPE_AP:
2244#ifdef WLAN_FEATURE_P2P
2245 case NL80211_IFTYPE_P2P_GO:
2246#endif
2247 wdev->iftype = type;
2248#ifdef WLAN_FEATURE_P2P
2249 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2250 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2251#endif
2252 goto done;
2253 default:
2254 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2255 __func__);
2256 return -EOPNOTSUPP;
2257
2258 }
2259
2260 }
2261 else
2262 {
2263 return -EOPNOTSUPP;
2264 }
2265
2266
2267 if(pRoamProfile)
2268 {
2269 if ( LastBSSType != pRoamProfile->BSSType )
2270 {
2271 /*interface type changed update in wiphy structure*/
2272 wdev->iftype = type;
2273
2274 /*the BSS mode changed, We need to issue disconnect
2275 if connected or in IBSS disconnect state*/
2276 if ( hdd_connGetConnectedBssType(
2277 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2278 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2279 {
2280 /*need to issue a disconnect to CSR.*/
2281 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2282 if( eHAL_STATUS_SUCCESS ==
2283 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2284 pAdapter->sessionId,
2285 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2286 {
2287 wait_for_completion_interruptible_timeout(
2288 &pAdapter->disconnect_comp_var,
2289 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2290 }
2291 }
2292 }
2293 }
2294
2295done:
2296 /*set bitmask based on updated value*/
2297 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2298#ifdef WLAN_BTAMP_FEATURE
2299 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2300 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2301 {
2302 //we are ok to do AMP
2303 pHddCtx->isAmpAllowed = VOS_TRUE;
2304 }
2305#endif //WLAN_BTAMP_FEATURE
2306 EXIT();
2307 return 0;
2308}
2309
2310static int wlan_hdd_change_station(struct wiphy *wiphy,
2311 struct net_device *dev,
2312 u8 *mac,
2313 struct station_parameters *params)
2314{
2315 VOS_STATUS status = VOS_STATUS_SUCCESS;
2316 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2317 v_MACADDR_t STAMacAddress;
2318
Jeff Johnsone7245742012-09-05 17:12:55 -07002319 ENTER();
2320
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002321 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2322 {
2323 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2324 "%s:LOGP in Progress. Ignore!!!", __func__);
2325 return -EAGAIN;
2326 }
2327
Jeff Johnson295189b2012-06-20 16:38:30 -07002328 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2329
2330 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2331#ifdef WLAN_FEATURE_P2P
2332 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2333#endif
2334 )
2335 {
2336 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2337 {
2338 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2339 WLANTL_STA_AUTHENTICATED);
2340
2341 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002342 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002343 return -EINVAL;
2344 }
2345 }
2346
Jeff Johnsone7245742012-09-05 17:12:55 -07002347 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002348 return status;
2349}
2350
2351/*
2352 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2353 * This function is used to get peer station index in IBSS mode
2354 */
2355static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2356{
2357 u8 idx = 0;
2358 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2359 ENTER();
2360 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2361 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2362 {
2363 if ( (0 !=
2364 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2365 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2366 temp, VOS_MAC_ADDR_SIZE)
2367 )
2368 {
2369 return idx;
2370 }
2371 }
2372 return idx;
2373}
2374
2375
2376/*
2377 * FUNCTION: wlan_hdd_cfg80211_add_key
2378 * This function is used to initialize the key information
2379 */
2380#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2381static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2382 struct net_device *ndev,
2383 u8 key_index, bool pairwise,
2384 const u8 *mac_addr,
2385 struct key_params *params
2386 )
2387#else
2388static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2389 struct net_device *ndev,
2390 u8 key_index, const u8 *mac_addr,
2391 struct key_params *params
2392 )
2393#endif
2394{
2395 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2396 tCsrRoamSetKey setKey;
2397 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2398 int status = 0;
2399 v_U32_t roamId= 0xFF;
2400 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2401 hdd_hostapd_state_t *pHostapdState;
2402 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002403 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002404
2405 ENTER();
2406
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002407 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2408 {
2409 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2410 "%s:LOGP in Progress. Ignore!!!", __func__);
2411 return -EAGAIN;
2412 }
2413
Jeff Johnson295189b2012-06-20 16:38:30 -07002414 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2415 __func__,pAdapter->device_mode);
2416
2417 if (CSR_MAX_NUM_KEY <= key_index)
2418 {
2419 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2420 key_index);
2421
2422 return -EINVAL;
2423 }
2424
2425 hddLog(VOS_TRACE_LEVEL_INFO,
2426 "%s: called with key index = %d & key length %d",
2427 __func__, key_index, params->key_len);
2428
2429 /*extract key idx, key len and key*/
2430 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2431 setKey.keyId = key_index;
2432 setKey.keyLength = params->key_len;
2433 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2434
2435 switch (params->cipher)
2436 {
2437 case WLAN_CIPHER_SUITE_WEP40:
2438 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2439 break;
2440
2441 case WLAN_CIPHER_SUITE_WEP104:
2442 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2443 break;
2444
2445 case WLAN_CIPHER_SUITE_TKIP:
2446 {
2447 u8 *pKey = &setKey.Key[0];
2448 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2449
2450 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2451
2452 /*Supplicant sends the 32bytes key in this order
2453
2454 |--------------|----------|----------|
2455 | Tk1 |TX-MIC | RX Mic |
2456 |--------------|----------|----------|
2457 <---16bytes---><--8bytes--><--8bytes-->
2458
2459 */
2460 /*Sme expects the 32 bytes key to be in the below order
2461
2462 |--------------|----------|----------|
2463 | Tk1 |RX-MIC | TX Mic |
2464 |--------------|----------|----------|
2465 <---16bytes---><--8bytes--><--8bytes-->
2466 */
2467 /* Copy the Temporal Key 1 (TK1) */
2468 vos_mem_copy(pKey, params->key,16);
2469
2470 /*Copy the rx mic first*/
2471 vos_mem_copy(&pKey[16],&params->key[24],8);
2472
2473 /*Copy the tx mic */
2474 vos_mem_copy(&pKey[24],&params->key[16],8);
2475
2476
2477 break;
2478 }
2479
2480 case WLAN_CIPHER_SUITE_CCMP:
2481 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2482 break;
2483
2484#ifdef FEATURE_WLAN_WAPI
2485 case WLAN_CIPHER_SUITE_SMS4:
2486 {
2487 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2488 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2489 params->key, params->key_len);
2490 return 0;
2491 }
2492#endif
2493#ifdef FEATURE_WLAN_CCX
2494 case WLAN_CIPHER_SUITE_KRK:
2495 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2496 break;
2497#endif
2498 default:
2499 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2500 __func__, params->cipher);
2501 return -EOPNOTSUPP;
2502 }
2503
2504 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2505 __func__, setKey.encType);
2506
2507
2508
2509 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2510#ifdef WLAN_FEATURE_P2P
2511 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2512#endif
2513 )
2514 {
2515
2516
2517 if (
2518#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2519 (!pairwise)
2520#else
2521 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2522#endif
2523 )
2524 {
2525 /* set group key*/
2526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2527 "%s- %d: setting Broacast key",
2528 __func__, __LINE__);
2529 setKey.keyDirection = eSIR_RX_ONLY;
2530 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2531 }
2532 else
2533 {
2534 /* set pairwise key*/
2535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2536 "%s- %d: setting pairwise key",
2537 __func__, __LINE__);
2538 setKey.keyDirection = eSIR_TX_RX;
2539 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2540 }
2541
2542 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2543 if( pHostapdState->bssState == BSS_START )
2544 {
2545 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2546
2547 if ( status != eHAL_STATUS_SUCCESS )
2548 {
2549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2550 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2551 __LINE__, status );
2552 }
2553 }
2554
2555 /* Saving WEP keys */
2556 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2557 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2558 {
2559 //Save the wep key in ap context. Issue setkey after the BSS is started.
2560 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2561 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2562 }
2563 else
2564 {
2565 //Save the key in ap context. Issue setkey after the BSS is started.
2566 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2567 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2568 }
2569 }
2570 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2571#ifdef WLAN_FEATURE_P2P
2572 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2573#endif
2574 )
2575 {
2576 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2577 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2578
2579 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2580
2581 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2582 params->key, params->key_len);
2583
2584 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2585
2586 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2587 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2588 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2589 )
2590 &&
2591 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2592 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2593 )
2594 )
2595 {
2596 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2597 * interface, copy bssid for pairwise key and group macaddr for
2598 * group key initialization*/
2599
2600 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2601
2602 pWextState->roamProfile.negotiatedUCEncryptionType =
2603 pHddStaCtx->conn_info.ucEncryptionType =
2604 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2605 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2606 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2607
2608
2609 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2610 "%s: Negotiated encryption type %d", __func__,
2611 pWextState->roamProfile.negotiatedUCEncryptionType);
2612
2613 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2614 &pWextState->roamProfile, true);
2615 setKey.keyLength = 0;
2616 setKey.keyDirection = eSIR_TX_RX;
2617
2618#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2619 if (pairwise)
2620 {
2621#endif
2622 if (mac_addr)
2623 {
2624 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2625 }
2626 else
2627 {
2628 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2629 * and peerMacAddress in case of IBSS*/
2630 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2631 {
2632 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2633 if (HDD_MAX_NUM_IBSS_STA != staidx)
2634 {
2635 vos_mem_copy(setKey.peerMac,
2636 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2637 WNI_CFG_BSSID_LEN);
2638
2639 }
2640 else
2641 {
2642 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2643 __func__);
2644 return -EOPNOTSUPP;
2645 }
2646 }
2647 else
2648 {
2649 vos_mem_copy(setKey.peerMac,
2650 &pHddStaCtx->conn_info.bssId[0],
2651 WNI_CFG_BSSID_LEN);
2652 }
2653 }
2654#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2655 }
2656 else
2657 {
2658 /* set group key*/
2659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2660 "%s- %d: setting Group key",
2661 __func__, __LINE__);
2662 setKey.keyDirection = eSIR_RX_ONLY;
2663 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2664 }
2665#endif
2666 }
2667 else if (
2668#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2669 (!pairwise)
2670#else
2671 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2672#endif
2673 )
2674 {
2675 /* set group key*/
2676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2677 "%s- %d: setting Group key",
2678 __func__, __LINE__);
2679 setKey.keyDirection = eSIR_RX_ONLY;
2680 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2681 }
2682 else
2683 {
2684 /* set pairwise key*/
2685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2686 "%s- %d: setting pairwise key",
2687 __func__, __LINE__);
2688 setKey.keyDirection = eSIR_TX_RX;
2689 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2690 }
2691
2692 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2693 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2694 __func__, setKey.peerMac[0], setKey.peerMac[1],
2695 setKey.peerMac[2], setKey.peerMac[3],
2696 setKey.peerMac[4], setKey.peerMac[5],
2697 setKey.keyDirection);
2698
2699 vos_status = wlan_hdd_check_ula_done(pAdapter);
2700
2701 if ( vos_status != VOS_STATUS_SUCCESS )
2702 {
2703 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2704 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2705 __LINE__, vos_status );
2706
2707 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2708
2709 return -EINVAL;
2710
2711 }
2712
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002713#ifdef WLAN_FEATURE_VOWIFI_11R
2714 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2715 Save the key in the UMAC and include it in the ADD BSS request */
2716 /*TODO 11r - is this used?? */
2717 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2718 if( halStatus == eHAL_STATUS_SUCCESS )
2719 {
2720 return halStatus;
2721 }
2722#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002723
2724 /* issue set key request to SME*/
2725 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2726 pAdapter->sessionId, &setKey, &roamId );
2727
2728 if ( 0 != status )
2729 {
2730 hddLog(VOS_TRACE_LEVEL_ERROR,
2731 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2732 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2733 return -EINVAL;
2734 }
2735
2736
2737 /* in case of IBSS as there was no information available about WEP keys during
2738 * IBSS join, group key intialized with NULL key, so re-initialize group key
2739 * with correct value*/
2740 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2741 !( ( IW_AUTH_KEY_MGMT_802_1X
2742 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2743 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2744 )
2745 &&
2746 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2747 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2748 )
2749 )
2750 {
2751 setKey.keyDirection = eSIR_RX_ONLY;
2752 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2753
2754 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2755 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2756 __func__, setKey.peerMac[0], setKey.peerMac[1],
2757 setKey.peerMac[2], setKey.peerMac[3],
2758 setKey.peerMac[4], setKey.peerMac[5],
2759 setKey.keyDirection);
2760
2761 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2762 pAdapter->sessionId, &setKey, &roamId );
2763
2764 if ( 0 != status )
2765 {
2766 hddLog(VOS_TRACE_LEVEL_ERROR,
2767 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
2768 __func__, status);
2769 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2770 return -EINVAL;
2771 }
2772 }
2773 }
2774
2775 return 0;
2776}
2777
2778/*
2779 * FUNCTION: wlan_hdd_cfg80211_get_key
2780 * This function is used to get the key information
2781 */
2782#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2783static int wlan_hdd_cfg80211_get_key(
2784 struct wiphy *wiphy,
2785 struct net_device *ndev,
2786 u8 key_index, bool pairwise,
2787 const u8 *mac_addr, void *cookie,
2788 void (*callback)(void *cookie, struct key_params*)
2789 )
2790#else
2791static int wlan_hdd_cfg80211_get_key(
2792 struct wiphy *wiphy,
2793 struct net_device *ndev,
2794 u8 key_index, const u8 *mac_addr, void *cookie,
2795 void (*callback)(void *cookie, struct key_params*)
2796 )
2797#endif
2798{
2799 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2800 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2801 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
2802 struct key_params params;
2803
2804 ENTER();
2805
2806 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2807 __func__,pAdapter->device_mode);
2808
2809 memset(&params, 0, sizeof(params));
2810
2811 if (CSR_MAX_NUM_KEY <= key_index)
2812 {
2813 return -EINVAL;
2814 }
2815
2816 switch(pRoamProfile->EncryptionType.encryptionType[0])
2817 {
2818 case eCSR_ENCRYPT_TYPE_NONE:
2819 params.cipher = IW_AUTH_CIPHER_NONE;
2820 break;
2821
2822 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
2823 case eCSR_ENCRYPT_TYPE_WEP40:
2824 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2825 break;
2826
2827 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
2828 case eCSR_ENCRYPT_TYPE_WEP104:
2829 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2830 break;
2831
2832 case eCSR_ENCRYPT_TYPE_TKIP:
2833 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2834 break;
2835
2836 case eCSR_ENCRYPT_TYPE_AES:
2837 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2838 break;
2839
2840 default:
2841 params.cipher = IW_AUTH_CIPHER_NONE;
2842 break;
2843 }
2844
2845 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
2846 params.seq_len = 0;
2847 params.seq = NULL;
2848 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
2849 callback(cookie, &params);
2850 return 0;
2851}
2852
2853/*
2854 * FUNCTION: wlan_hdd_cfg80211_del_key
2855 * This function is used to delete the key information
2856 */
2857#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2858static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
2859 struct net_device *ndev,
2860 u8 key_index,
2861 bool pairwise,
2862 const u8 *mac_addr
2863 )
2864#else
2865static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
2866 struct net_device *ndev,
2867 u8 key_index,
2868 const u8 *mac_addr
2869 )
2870#endif
2871{
2872 int status = 0;
2873
2874 //This code needs to be revisited. There is sme_removeKey API, we should
2875 //plan to use that. After the change to use correct index in setkey,
2876 //it is observed that this is invalidating peer
2877 //key index whenever re-key is done. This is affecting data link.
2878 //It should be ok to ignore del_key.
2879#if 0
2880 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2881 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2882 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2883 tCsrRoamSetKey setKey;
2884 v_U32_t roamId= 0xFF;
2885
2886 ENTER();
2887
2888 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
2889 __func__,pAdapter->device_mode);
2890
2891 if (CSR_MAX_NUM_KEY <= key_index)
2892 {
2893 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2894 key_index);
2895
2896 return -EINVAL;
2897 }
2898
2899 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2900 setKey.keyId = key_index;
2901
2902 if (mac_addr)
2903 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2904 else
2905 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2906
2907 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
2908
2909 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2910#ifdef WLAN_FEATURE_P2P
2911 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2912#endif
2913 )
2914 {
2915
2916 hdd_hostapd_state_t *pHostapdState =
2917 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2918 if( pHostapdState->bssState == BSS_START)
2919 {
2920 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2921
2922 if ( status != eHAL_STATUS_SUCCESS )
2923 {
2924 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2925 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2926 __LINE__, status );
2927 }
2928 }
2929 }
2930 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2931#ifdef WLAN_FEATURE_P2P
2932 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2933#endif
2934 )
2935 {
2936 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2937
2938 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2939
2940 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2941 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
2942 __func__, setKey.peerMac[0], setKey.peerMac[1],
2943 setKey.peerMac[2], setKey.peerMac[3],
2944 setKey.peerMac[4], setKey.peerMac[5]);
2945 if(pAdapter->sessionCtx.station.conn_info.connState ==
2946 eConnectionState_Associated)
2947 {
2948 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2949 pAdapter->sessionId, &setKey, &roamId );
2950
2951 if ( 0 != status )
2952 {
2953 hddLog(VOS_TRACE_LEVEL_ERROR,
2954 "%s: sme_RoamSetKey failure, returned %d",
2955 __func__, status);
2956 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2957 return -EINVAL;
2958 }
2959 }
2960 }
2961#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07002962 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002963 return status;
2964}
2965
2966/*
2967 * FUNCTION: wlan_hdd_cfg80211_set_default_key
2968 * This function is used to set the default tx key index
2969 */
2970#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2971static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
2972 struct net_device *ndev,
2973 u8 key_index,
2974 bool unicast, bool multicast)
2975#else
2976static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
2977 struct net_device *ndev,
2978 u8 key_index)
2979#endif
2980{
2981 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2982 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2983 int status = 0;
2984 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2985
2986 ENTER();
2987
2988 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
2989 __func__,pAdapter->device_mode, key_index);
2990
2991 if (CSR_MAX_NUM_KEY <= key_index)
2992 {
2993 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2994 key_index);
2995
2996 return -EINVAL;
2997 }
2998
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002999 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3000 {
3001 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3002 "%s:LOGP in Progress. Ignore!!!", __func__);
3003 return -EAGAIN;
3004 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003005
3006 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3007#ifdef WLAN_FEATURE_P2P
3008 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3009#endif
3010 )
3011 {
3012 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3013 (eCSR_ENCRYPT_TYPE_TKIP !=
3014 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3015 (eCSR_ENCRYPT_TYPE_AES !=
3016 pWextState->roamProfile.EncryptionType.encryptionType[0])
3017 )
3018 {
3019 /* if default key index is not same as previous one,
3020 * then update the default key index */
3021
3022 tCsrRoamSetKey setKey;
3023 v_U32_t roamId= 0xFF;
3024 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3025
3026 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3027 __func__, key_index);
3028
3029 Keys->defaultIndex = (u8)key_index;
3030 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3031 setKey.keyId = key_index;
3032 setKey.keyLength = Keys->KeyLength[key_index];
3033
3034 vos_mem_copy(&setKey.Key[0],
3035 &Keys->KeyMaterial[key_index][0],
3036 Keys->KeyLength[key_index]);
3037
3038 setKey.keyDirection = eSIR_TX_ONLY;
3039
3040 vos_mem_copy(setKey.peerMac,
3041 &pHddStaCtx->conn_info.bssId[0],
3042 WNI_CFG_BSSID_LEN);
3043
3044 setKey.encType =
3045 pWextState->roamProfile.EncryptionType.encryptionType[0];
3046
3047 /* issue set key request */
3048 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3049 pAdapter->sessionId, &setKey, &roamId );
3050
3051 if ( 0 != status )
3052 {
3053 hddLog(VOS_TRACE_LEVEL_ERROR,
3054 "%s: sme_RoamSetKey failed, returned %d", __func__,
3055 status);
3056 return -EINVAL;
3057 }
3058 }
3059 }
3060
3061 /* In SoftAp mode setting key direction for default mode */
3062 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3063 {
3064 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3065 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3066 (eCSR_ENCRYPT_TYPE_AES !=
3067 pWextState->roamProfile.EncryptionType.encryptionType[0])
3068 )
3069 {
3070 /* Saving key direction for default key index to TX default */
3071 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3072 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3073 }
3074 }
3075
3076 return status;
3077}
3078
3079/**
3080 * FUNCTION: wlan_hdd_cfg80211_set_channel
3081 * This function is used to set the channel number
3082 */
3083int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3084 struct ieee80211_channel *chan,
3085 enum nl80211_channel_type channel_type
3086 )
3087{
3088 v_U32_t num_ch = 0;
3089 u32 channel = 0;
3090 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3091 int freq = chan->center_freq; /* freq is in MHZ */
3092
3093 ENTER();
3094
3095 hddLog(VOS_TRACE_LEVEL_INFO,
3096 "%s: device_mode = %d freq = %d \n",__func__,
3097 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003098 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3099 {
3100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3101 return -EAGAIN;
3102 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003103
3104 /*
3105 * Do freq to chan conversion
3106 * TODO: for 11a
3107 */
3108
3109 channel = ieee80211_frequency_to_channel(freq);
3110
3111 /* Check freq range */
3112 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3113 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3114 {
3115 hddLog(VOS_TRACE_LEVEL_ERROR,
3116 "%s: Channel [%d] is outside valid range from %d to %d\n",
3117 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3118 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3119 return -EINVAL;
3120 }
3121
3122 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3123
3124 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3125#ifdef WLAN_FEATURE_P2P
3126 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3127#endif
3128 )
3129 {
3130 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3131 {
3132 hddLog(VOS_TRACE_LEVEL_ERROR,
3133 "%s: Invalid Channel [%d] \n", __func__, channel);
3134 return -EINVAL;
3135 }
3136 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3137 "%s: set channel to [%d] for device mode =%d",
3138 __func__, channel,pAdapter->device_mode);
3139 }
3140 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3141#ifdef WLAN_FEATURE_P2P
3142 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3143#endif
3144 )
3145 {
3146 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3147 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3148 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3149
3150 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3151 {
3152 /* Link is up then return cant set channel*/
3153 hddLog( VOS_TRACE_LEVEL_ERROR,
3154 "%s: IBSS Associated, can't set the channel\n", __func__);
3155 return -EINVAL;
3156 }
3157
3158 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3159 pHddStaCtx->conn_info.operationChannel = channel;
3160 pRoamProfile->ChannelInfo.ChannelList =
3161 &pHddStaCtx->conn_info.operationChannel;
3162 }
3163 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3164#ifdef WLAN_FEATURE_P2P
3165 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3166#endif
3167 )
3168 {
3169 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3170
3171 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3172 {
3173 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3174
3175 /* If auto channel selection is configured as enable/ 1 then ignore
3176 channel set by supplicant
3177 */
3178 if ( cfg_param->apAutoChannelSelection )
3179 {
3180 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3181
3182 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3183 "%s: set channel to auto channel (0) for device mode =%d",
3184 __func__, pAdapter->device_mode);
3185 }
3186 }
3187 }
3188 else
3189 {
3190 hddLog(VOS_TRACE_LEVEL_FATAL,
3191 "%s: Invalid device mode failed to set valid channel", __func__);
3192 return -EINVAL;
3193 }
3194 EXIT();
3195 return 0;
3196}
3197
3198
3199
3200/*
3201 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3202 * This function is used to inform the BSS details to nl80211 interface.
3203 */
3204static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3205 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3206{
3207 struct net_device *dev = pAdapter->dev;
3208 struct wireless_dev *wdev = dev->ieee80211_ptr;
3209 struct wiphy *wiphy = wdev->wiphy;
3210 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3211 int chan_no;
3212 int ie_length;
3213 const char *ie;
3214 unsigned int freq;
3215 struct ieee80211_channel *chan;
3216 int rssi = 0;
3217 struct cfg80211_bss *bss = NULL;
3218
3219 ENTER();
3220
3221 if( NULL == pBssDesc )
3222 {
3223 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3224 return bss;
3225 }
3226
3227 chan_no = pBssDesc->channelId;
3228 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3229 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3230
3231 if( NULL == ie )
3232 {
3233 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3234 return bss;
3235 }
3236
3237#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3238 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3239 {
3240 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3241 }
3242 else
3243 {
3244 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3245 }
3246#else
3247 freq = ieee80211_channel_to_frequency(chan_no);
3248#endif
3249
3250 chan = __ieee80211_get_channel(wiphy, freq);
3251
3252 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3253 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3254 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3255 if (bss == NULL)
3256 {
3257 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3258
3259 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3260 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3261 pBssDesc->capabilityInfo,
3262 pBssDesc->beaconInterval, ie, ie_length,
3263 rssi, GFP_KERNEL ));
3264}
3265 else
3266 {
3267 return bss;
3268 }
3269}
3270
3271
3272
3273/*
3274 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3275 * This function is used to inform the BSS details to nl80211 interface.
3276 */
3277struct cfg80211_bss*
3278wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3279 tSirBssDescription *bss_desc
3280 )
3281{
3282 /*
3283 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3284 already exists in bss data base of cfg80211 for that particular BSS ID.
3285 Using cfg80211_inform_bss_frame to update the bss entry instead of
3286 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3287 now there is no possibility to get the mgmt(probe response) frame from PE,
3288 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3289 cfg80211_inform_bss_frame.
3290 */
3291 struct net_device *dev = pAdapter->dev;
3292 struct wireless_dev *wdev = dev->ieee80211_ptr;
3293 struct wiphy *wiphy = wdev->wiphy;
3294 int chan_no = bss_desc->channelId;
3295 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
3296 const char *ie =
3297 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3298 unsigned int freq;
3299 struct ieee80211_channel *chan;
3300 struct ieee80211_mgmt *mgmt =
3301 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3302 struct cfg80211_bss *bss_status = NULL;
3303 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3304 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003305#ifdef WLAN_OPEN_SOURCE
3306 struct timespec ts;
3307#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003308
3309 ENTER();
3310
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003311 if (!mgmt)
3312 return NULL;
3313
Jeff Johnson295189b2012-06-20 16:38:30 -07003314 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003315
3316#ifdef WLAN_OPEN_SOURCE
3317 /* Android does not want the timestamp from the frame.
3318 Instead it wants a monotonic increasing value */
3319 get_monotonic_boottime(&ts);
3320 mgmt->u.probe_resp.timestamp =
3321 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3322#else
3323 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003324 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3325 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003326
3327#endif
3328
Jeff Johnson295189b2012-06-20 16:38:30 -07003329 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3330 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
3331 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3332
3333 mgmt->frame_control |=
3334 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3335
3336#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3337 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3338 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3339 {
3340 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3341 }
3342 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3343 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3344
3345 {
3346 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3347 }
3348 else
3349 {
3350 kfree(mgmt);
3351 return NULL;
3352 }
3353#else
3354 freq = ieee80211_channel_to_frequency(chan_no);
3355#endif
3356 chan = __ieee80211_get_channel(wiphy, freq);
3357
3358 /*To keep the rssi icon of the connected AP in the scan window
3359 *and the rssi icon of the wireless networks in sync
3360 * */
3361 if (( eConnectionState_Associated ==
3362 pAdapter->sessionCtx.station.conn_info.connState ) &&
3363 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3364 pAdapter->sessionCtx.station.conn_info.bssId,
3365 WNI_CFG_BSSID_LEN)))
3366 {
3367 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3368 rssi = (pAdapter->rssi * 100);
3369 }
3370 else
3371 {
3372 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3373 }
3374
3375 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3376 frame_len, rssi, GFP_KERNEL);
3377 kfree(mgmt);
3378 return bss_status;
3379}
3380
3381/*
3382 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3383 * This function is used to update the BSS data base of CFG8011
3384 */
3385struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3386 tCsrRoamInfo *pRoamInfo
3387 )
3388{
3389 tCsrRoamConnectedProfile roamProfile;
3390 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3391 struct cfg80211_bss *bss = NULL;
3392
3393 ENTER();
3394
3395 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3396 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3397
3398 if (NULL != roamProfile.pBssDesc)
3399 {
3400 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3401 &roamProfile);
3402
3403 if (NULL == bss)
3404 {
3405 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3406 __func__);
3407 }
3408
3409 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3410 }
3411 else
3412 {
3413 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3414 __func__);
3415 }
3416 return bss;
3417}
3418
3419/*
3420 * FUNCTION: wlan_hdd_cfg80211_update_bss
3421 */
3422static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3423 hdd_adapter_t *pAdapter
3424 )
3425{
3426 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3427 tCsrScanResultInfo *pScanResult;
3428 eHalStatus status = 0;
3429 tScanResultHandle pResult;
3430 struct cfg80211_bss *bss_status = NULL;
3431
3432 ENTER();
3433
3434 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3435 {
3436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3437 return -EAGAIN;
3438 }
3439
3440 /*
3441 * start getting scan results and populate cgf80211 BSS database
3442 */
3443 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3444
3445 /* no scan results */
3446 if (NULL == pResult)
3447 {
3448 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3449 return status;
3450 }
3451
3452 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3453
3454 while (pScanResult)
3455 {
3456 /*
3457 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3458 * entry already exists in bss data base of cfg80211 for that
3459 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3460 * bss entry instead of cfg80211_inform_bss, But this call expects
3461 * mgmt packet as input. As of now there is no possibility to get
3462 * the mgmt(probe response) frame from PE, converting bss_desc to
3463 * ieee80211_mgmt(probe response) and passing to c
3464 * fg80211_inform_bss_frame.
3465 * */
3466
3467 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3468 &pScanResult->BssDescriptor);
3469
3470
3471 if (NULL == bss_status)
3472 {
3473 hddLog(VOS_TRACE_LEVEL_INFO,
3474 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3475 }
3476 else
3477 {
3478 cfg80211_put_bss(bss_status);
3479 }
3480
3481 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3482 }
3483
3484 sme_ScanResultPurge(hHal, pResult);
3485
3486 return 0;
3487}
3488
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003489void
3490hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3491{
3492 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003493 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3494 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3495 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003496} /****** end hddPrintMacAddr() ******/
3497
3498void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003499hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003500{
3501 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003502 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3503 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3504 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3505 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003506} /****** end hddPrintPmkId() ******/
3507
3508//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3509//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3510
3511//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3512//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3513
3514#define dump_bssid(bssid) \
3515 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003516 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3517 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3518 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003519 }
3520
3521#define dump_pmkid(pMac, pmkid) \
3522 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003523 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3524 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3525 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003526 }
3527
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003528#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003529/*
3530 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3531 * This function is used to notify the supplicant of a new PMKSA candidate.
3532 */
3533int wlan_hdd_cfg80211_pmksa_candidate_notify(
3534 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3535 int index, bool preauth )
3536{
Jeff Johnsone7245742012-09-05 17:12:55 -07003537#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003538 struct net_device *dev = pAdapter->dev;
3539
3540 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003541 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003542
3543 if( NULL == pRoamInfo )
3544 {
3545 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3546 return -EINVAL;
3547 }
3548
3549 dump_bssid(pRoamInfo->bssid);
3550 cfg80211_pmksa_candidate_notify(dev, index,
3551 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003552#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003553 return 0;
3554}
3555#endif //FEATURE_WLAN_LFR
3556
Jeff Johnson295189b2012-06-20 16:38:30 -07003557/*
3558 * FUNCTION: hdd_cfg80211_scan_done_callback
3559 * scanning callback function, called after finishing scan
3560 *
3561 */
3562static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3563 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3564{
3565 struct net_device *dev = (struct net_device *) pContext;
3566 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3567 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003568 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3569 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003570 struct cfg80211_scan_request *req = NULL;
3571 int ret = 0;
3572
3573 ENTER();
3574
3575 hddLog(VOS_TRACE_LEVEL_INFO,
3576 "%s called with halHandle = %p, pContext = %p,"
3577 "scanID = %d, returned status = %d\n",
3578 __func__, halHandle, pContext, (int) scanId, (int) status);
3579
3580 //Block on scan req completion variable. Can't wait forever though.
3581 ret = wait_for_completion_interruptible_timeout(
3582 &pScanInfo->scan_req_completion_event,
3583 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3584 if (!ret)
3585 {
3586 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003587 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003588 }
3589
3590 if(pScanInfo->mScanPending != VOS_TRUE)
3591 {
3592 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003593 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003594 }
3595
3596 /* Check the scanId */
3597 if (pScanInfo->scanId != scanId)
3598 {
3599 hddLog(VOS_TRACE_LEVEL_INFO,
3600 "%s called with mismatched scanId pScanInfo->scanId = %d "
3601 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3602 (int) scanId);
3603 }
3604
Jeff Johnson295189b2012-06-20 16:38:30 -07003605 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3606 pAdapter);
3607
3608 if (0 > ret)
3609 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3610
3611
3612 /* If any client wait scan result through WEXT
3613 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003614 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003615 {
3616 /* The other scan request waiting for current scan finish
3617 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003618 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003619 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003620 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003621 }
3622 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003623 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003624 {
3625 struct net_device *dev = pAdapter->dev;
3626 union iwreq_data wrqu;
3627 int we_event;
3628 char *msg;
3629
3630 memset(&wrqu, '\0', sizeof(wrqu));
3631 we_event = SIOCGIWSCAN;
3632 msg = NULL;
3633 wireless_send_event(dev, we_event, &wrqu, msg);
3634 }
3635 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003636 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003637
3638 /* Get the Scan Req */
3639 req = pAdapter->request;
3640
3641 if (!req)
3642 {
3643 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003644 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003645 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003646 }
3647
3648 /*
3649 * setting up 0, just in case.
3650 */
3651 req->n_ssids = 0;
3652 req->n_channels = 0;
3653 req->ie = 0;
3654
Jeff Johnson295189b2012-06-20 16:38:30 -07003655 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003656 /* Scan is no longer pending */
3657 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003658
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003659 /*
3660 * cfg80211_scan_done informing NL80211 about completion
3661 * of scanning
3662 */
3663 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudi070e8702012-10-24 14:31:17 -07003664 complete(&pAdapter->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003665#ifdef WLAN_FEATURE_P2P
3666 /* Flush out scan result after p2p_serach is done */
Jeff Johnsone7245742012-09-05 17:12:55 -07003667 if(pScanInfo->flushP2pScanResults)
Jeff Johnson295189b2012-06-20 16:38:30 -07003668 {
3669 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudiab41d0f2012-10-31 17:17:10 -07003670 sme_ScanFlushP2PResult(WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07003671 pScanInfo->flushP2pScanResults = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003672 }
3673#endif
3674
Jeff Johnsone7245742012-09-05 17:12:55 -07003675allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003676 /* release the wake lock at the end of the scan*/
3677 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003678
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003679 /* Acquire wakelock to handle the case where APP's tries to suspend
3680 * immediatly after the driver gets connect request(i.e after scan)
3681 * from supplicant, this result in app's is suspending and not able
3682 * to process the connect request to AP */
3683 hdd_allow_suspend_timeout(100);
3684
Jeff Johnson295189b2012-06-20 16:38:30 -07003685 EXIT();
3686 return 0;
3687}
3688
3689/*
3690 * FUNCTION: wlan_hdd_cfg80211_scan
3691 * this scan respond to scan trigger and update cfg80211 scan database
3692 * later, scan dump command can be used to recieve scan results
3693 */
3694int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3695 struct cfg80211_scan_request *request)
3696{
3697 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3698 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3699 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3700 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3701 tCsrScanRequest scanRequest;
3702 tANI_U8 *channelList = NULL, i;
3703 v_U32_t scanId = 0;
3704 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003705 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003706#ifdef WLAN_FEATURE_P2P
3707 v_U8_t* pP2pIe = NULL;
3708#endif
3709
3710 ENTER();
3711
3712 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3713 __func__,pAdapter->device_mode);
3714#ifdef WLAN_BTAMP_FEATURE
3715 //Scan not supported when AMP traffic is on.
3716 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
3717 {
3718 hddLog(VOS_TRACE_LEVEL_ERROR,
3719 "%s: No scanning when AMP is on", __func__);
3720 return -EOPNOTSUPP;
3721 }
3722#endif
3723 //Scan on any other interface is not supported.
3724 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
3725 {
3726 hddLog(VOS_TRACE_LEVEL_ERROR,
3727 "%s: Not scanning on device_mode = %d",
3728 __func__, pAdapter->device_mode);
3729 return -EOPNOTSUPP;
3730 }
3731
3732 if (TRUE == pScanInfo->mScanPending)
3733 {
3734 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
3735 return -EBUSY;
3736 }
3737
3738 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3739 {
3740 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3741 "%s:LOGP in Progress. Ignore!!!", __func__);
3742 return -EAGAIN;
3743 }
3744
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07003745 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
3746 {
3747 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3748 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
3749 return -EAGAIN;
3750 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07003751 //Don't Allow Scan and return busy if Remain On
3752 //Channel and action frame is pending
3753 //Otherwise Cancel Remain On Channel and allow Scan
3754 //If no action frame pending
3755 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
3756 {
3757 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
3758 return -EBUSY;
3759 }
3760
Jeff Johnson295189b2012-06-20 16:38:30 -07003761 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
3762 {
3763 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
3764 "%s: Aquire lock fail", __func__);
3765 return -EAGAIN;
3766 }
3767 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
3768 {
3769 hddLog(VOS_TRACE_LEVEL_WARN,
3770 "%s: MAX TM Level Scan not allowed", __func__);
3771 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3772 return -EBUSY;
3773 }
3774 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3775
3776 vos_mem_zero( &scanRequest, sizeof(scanRequest));
3777
3778 if (NULL != request)
3779 {
3780 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
3781 (int)request->n_ssids);
3782
3783 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
3784 * Becasue of this, driver is assuming that this is not wildcard scan and so
3785 * is not aging out the scan results.
3786 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07003787 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07003788 {
3789 request->n_ssids = 0;
3790 }
3791
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003792 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07003793 {
3794 tCsrSSIDInfo *SsidInfo;
3795 int j;
3796 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
3797 /* Allocate num_ssid tCsrSSIDInfo structure */
3798 SsidInfo = scanRequest.SSIDs.SSIDList =
3799 ( tCsrSSIDInfo *)vos_mem_malloc(
3800 request->n_ssids*sizeof(tCsrSSIDInfo));
3801
3802 if(NULL == scanRequest.SSIDs.SSIDList)
3803 {
3804 hddLog(VOS_TRACE_LEVEL_ERROR,
3805 "memory alloc failed SSIDInfo buffer");
3806 return -ENOMEM;
3807 }
3808
3809 /* copy all the ssid's and their length */
3810 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
3811 {
3812 /* get the ssid length */
3813 SsidInfo->SSID.length = request->ssids[j].ssid_len;
3814 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
3815 SsidInfo->SSID.length);
3816 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
3817 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
3818 j, SsidInfo->SSID.ssId);
3819 }
3820 /* set the scan type to active */
3821 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3822 }
3823 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
3824 {
3825 /* set the scan type to active */
3826 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3827 }
3828 else
3829 {
3830 /*Set the scan type to default type, in this case it is ACTIVE*/
3831 scanRequest.scanType = pScanInfo->scan_mode;
3832 }
3833 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
3834 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
3835 }
3836 else
3837 {
3838 /* set the scan type to active */
3839 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3840 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
3841
3842 /* set min and max channel time to zero */
3843 scanRequest.minChnTime = 0;
3844 scanRequest.maxChnTime = 0;
3845 }
3846
3847 /* set BSSType to default type */
3848 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
3849
3850 /*TODO: scan the requested channels only*/
3851
3852 /*Right now scanning all the channels */
3853 if( request )
3854 {
3855 if( request->n_channels )
3856 {
3857 channelList = vos_mem_malloc( request->n_channels );
3858 if( NULL == channelList )
3859 {
3860 status = -ENOMEM;
3861 goto free_mem;
3862 }
3863
3864 for( i = 0 ; i < request->n_channels ; i++ )
3865 channelList[i] = request->channels[i]->hw_value;
3866 }
3867
3868 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
3869 scanRequest.ChannelInfo.ChannelList = channelList;
3870
3871 /* set requestType to full scan */
3872 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3873
3874 if( request->ie_len )
3875 {
3876 /* save this for future association (join requires this) */
3877 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
3878 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
3879 pScanInfo->scanAddIE.length = request->ie_len;
3880
3881 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07003882 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3883 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07003884 )
3885 {
3886 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
3887 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
3888 }
3889
3890 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
3891 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
3892
3893#ifdef WLAN_FEATURE_P2P
3894 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
3895 request->ie_len);
3896 if (pP2pIe != NULL)
3897 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07003898#ifdef WLAN_FEATURE_P2P_DEBUG
3899 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
3900 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
3901 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
3902 {
3903 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
3904 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
3905 "Go nego completed to Connection is started");
3906 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
3907 "for 8way Handshake");
3908 }
3909 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
3910 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
3911 {
3912 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
3913 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
3914 "Disconnected state to Connection is started");
3915 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
3916 "for 4way Handshake");
3917 }
3918#endif
3919
Jeff Johnsone7245742012-09-05 17:12:55 -07003920 /* no_cck will be set during p2p find to disable 11b rates */
3921 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 {
3923 tANI_U8 sessionId = pAdapter->sessionId;
3924 hddLog(VOS_TRACE_LEVEL_INFO,
3925 "%s: This is a P2P Search", __func__);
3926 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07003927
3928 /* Flush the scan results only for P2P search.
3929 P2P search happens on 3 social channels (1, 6, 11) */
3930 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
3931 {
3932 pScanInfo->flushP2pScanResults = 1;
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07003933 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -07003934 sessionId );
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07003935 /* set requestType to P2P Discovery */
3936 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07003937 }
3938
3939 /*
3940 Skip Dfs Channel in case of P2P Search
3941 if it is set in ini file
3942 */
3943 if(cfg_param->skipDfsChnlInP2pSearch)
3944 {
3945 scanRequest.skipDfsChnlInP2pSearch = 1;
3946 }
3947 else
3948 {
3949 scanRequest.skipDfsChnlInP2pSearch = 0;
3950 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003951
Jeff Johnson295189b2012-06-20 16:38:30 -07003952 }
3953 }
3954#endif
3955 }
3956 }
3957
3958 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
3959
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003960 /* acquire the wakelock to avoid the apps suspend during the scan. To
3961 * address the following issues.
3962 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
3963 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
3964 * for long time, this result in apps running at full power for long time.
3965 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
3966 * be stuck in full power because of resume BMPS
3967 */
3968 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003969
3970 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003971 pAdapter->sessionId, &scanRequest, &scanId,
3972 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07003973
Jeff Johnson295189b2012-06-20 16:38:30 -07003974 if (eHAL_STATUS_SUCCESS != status)
3975 {
3976 hddLog(VOS_TRACE_LEVEL_ERROR,
3977 "%s: sme_ScanRequest returned error %d", __func__, status);
3978 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07003979 if(eHAL_STATUS_RESOURCES == status)
3980 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07003981 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 -07003982 status = -EBUSY;
3983 } else {
3984 status = -EIO;
3985 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003986 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07003987 goto free_mem;
3988 }
3989
3990 pScanInfo->mScanPending = TRUE;
3991 pAdapter->request = request;
3992 pScanInfo->scanId = scanId;
3993
3994 complete(&pScanInfo->scan_req_completion_event);
3995
3996free_mem:
3997 if( scanRequest.SSIDs.SSIDList )
3998 {
3999 vos_mem_free(scanRequest.SSIDs.SSIDList);
4000 }
4001
4002 if( channelList )
4003 vos_mem_free( channelList );
4004
4005 EXIT();
4006
4007 return status;
4008}
4009
4010/*
4011 * FUNCTION: wlan_hdd_cfg80211_connect_start
4012 * This function is used to start the association process
4013 */
4014int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004015 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004016{
4017 int status = 0;
4018 hdd_wext_state_t *pWextState;
4019 v_U32_t roamId;
4020 tCsrRoamProfile *pRoamProfile;
4021 eMib_dot11DesiredBssType connectedBssType;
4022 eCsrAuthType RSNAuthType;
4023
4024 ENTER();
4025
4026 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4027
4028 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4029 {
4030 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4031 return -EINVAL;
4032 }
4033
4034 pRoamProfile = &pWextState->roamProfile;
4035
4036 if (pRoamProfile)
4037 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004038 int ret = 0;
4039 hdd_station_ctx_t *pHddStaCtx;
4040 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4041 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4042
4043 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4044 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4045 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004046 {
4047 /* Issue disconnect to CSR */
4048 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4049 if( eHAL_STATUS_SUCCESS ==
4050 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4051 pAdapter->sessionId,
4052 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4053 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004054 ret = wait_for_completion_interruptible_timeout(
4055 &pAdapter->disconnect_comp_var,
4056 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4057 if (0 == ret)
4058 {
4059 VOS_ASSERT(0);
4060 }
4061 }
4062 }
4063 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4064 {
4065 ret = wait_for_completion_interruptible_timeout(
4066 &pAdapter->disconnect_comp_var,
4067 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4068 if (0 == ret)
4069 {
4070 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004071 }
4072 }
4073
4074 if (HDD_WMM_USER_MODE_NO_QOS ==
4075 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4076 {
4077 /*QoS not enabled in cfg file*/
4078 pRoamProfile->uapsd_mask = 0;
4079 }
4080 else
4081 {
4082 /*QoS enabled, update uapsd mask from cfg file*/
4083 pRoamProfile->uapsd_mask =
4084 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4085 }
4086
4087 pRoamProfile->SSIDs.numOfSSIDs = 1;
4088 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4089 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4090 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4091 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4092 ssid, ssid_len);
4093
4094 if (bssid)
4095 {
4096 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4097 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4098 WNI_CFG_BSSID_LEN);
4099 /* Save BSSID in seperate variable as well, as RoamProfile
4100 BSSID is getting zeroed out in the association process. And in
4101 case of join failure we should send valid BSSID to supplicant
4102 */
4103 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4104 WNI_CFG_BSSID_LEN);
4105 }
4106
4107 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4108 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4109 {
4110 /*set gen ie*/
4111 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4112 /*set auth*/
4113 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4114 }
4115 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4116 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4117 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4118 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4119 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4120 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4121 )
4122 {
4123 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4124 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4125 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4126 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4127 eCSR_AUTH_TYPE_AUTOSWITCH;
4128 pWextState->roamProfile.AuthType.authType[0] =
4129 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4130 }
4131#ifdef FEATURE_WLAN_WAPI
4132 if (pAdapter->wapi_info.nWapiMode)
4133 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004134 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004135 switch (pAdapter->wapi_info.wapiAuthMode)
4136 {
4137 case WAPI_AUTH_MODE_PSK:
4138 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004139 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 pAdapter->wapi_info.wapiAuthMode);
4141 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4142 break;
4143 }
4144 case WAPI_AUTH_MODE_CERT:
4145 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004146 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 pAdapter->wapi_info.wapiAuthMode);
4148 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4149 break;
4150 }
4151 } // End of switch
4152 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4153 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4154 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004155 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004156 pRoamProfile->AuthType.numEntries = 1;
4157 pRoamProfile->EncryptionType.numEntries = 1;
4158 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4159 pRoamProfile->mcEncryptionType.numEntries = 1;
4160 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4161 }
4162 }
4163#endif /* FEATURE_WLAN_WAPI */
4164 pRoamProfile->csrPersona = pAdapter->device_mode;
4165
Jeff Johnson32d95a32012-09-10 13:15:23 -07004166 if( operatingChannel )
4167 {
4168 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4169 pRoamProfile->ChannelInfo.numOfChannels = 1;
4170 }
4171
Jeff Johnson295189b2012-06-20 16:38:30 -07004172 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4173 pAdapter->sessionId, pRoamProfile, &roamId);
4174
Jeff Johnson32d95a32012-09-10 13:15:23 -07004175 pRoamProfile->ChannelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004176 pRoamProfile->ChannelInfo.numOfChannels = 0;
4177 }
4178 else
4179 {
4180 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4181 return -EINVAL;
4182 }
4183 EXIT();
4184 return status;
4185}
4186
4187/*
4188 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4189 * This function is used to set the authentication type (OPEN/SHARED).
4190 *
4191 */
4192static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4193 enum nl80211_auth_type auth_type)
4194{
4195 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4196 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4197
4198 ENTER();
4199
4200 /*set authentication type*/
4201 switch (auth_type)
4202 {
4203 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4204 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004205#ifdef WLAN_FEATURE_VOWIFI_11R
4206 case NL80211_AUTHTYPE_FT:
4207#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004208 hddLog(VOS_TRACE_LEVEL_INFO,
4209 "%s: set authentication type to OPEN", __func__);
4210 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4211 break;
4212
4213 case NL80211_AUTHTYPE_SHARED_KEY:
4214 hddLog(VOS_TRACE_LEVEL_INFO,
4215 "%s: set authentication type to SHARED", __func__);
4216 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4217 break;
4218#ifdef FEATURE_WLAN_CCX
4219 case NL80211_AUTHTYPE_NETWORK_EAP:
4220 hddLog(VOS_TRACE_LEVEL_INFO,
4221 "%s: set authentication type to CCKM WPA", __func__);
4222 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4223 break;
4224#endif
4225
4226
4227 default:
4228 hddLog(VOS_TRACE_LEVEL_ERROR,
4229 "%s: Unsupported authentication type %d", __func__,
4230 auth_type);
4231 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4232 return -EINVAL;
4233 }
4234
4235 pWextState->roamProfile.AuthType.authType[0] =
4236 pHddStaCtx->conn_info.authType;
4237 return 0;
4238}
4239
4240/*
4241 * FUNCTION: wlan_hdd_set_akm_suite
4242 * This function is used to set the key mgmt type(PSK/8021x).
4243 *
4244 */
4245static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4246 u32 key_mgmt
4247 )
4248{
4249 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4250 ENTER();
4251
4252 /*set key mgmt type*/
4253 switch(key_mgmt)
4254 {
4255 case WLAN_AKM_SUITE_PSK:
4256 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4257 __func__);
4258 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4259 break;
4260
4261 case WLAN_AKM_SUITE_8021X:
4262 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4263 __func__);
4264 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4265 break;
4266#ifdef FEATURE_WLAN_CCX
4267#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4268#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4269 case WLAN_AKM_SUITE_CCKM:
4270 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4271 __func__);
4272 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4273 break;
4274#endif
4275
4276 default:
4277 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4278 __func__, key_mgmt);
4279 return -EINVAL;
4280
4281 }
4282 return 0;
4283}
4284
4285/*
4286 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4287 * This function is used to set the encryption type
4288 * (NONE/WEP40/WEP104/TKIP/CCMP).
4289 */
4290static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4291 u32 cipher,
4292 bool ucast
4293 )
4294{
4295 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4296 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4297 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4298
4299 ENTER();
4300
4301 if (!cipher)
4302 {
4303 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4304 __func__, cipher);
4305 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4306 }
4307 else
4308 {
4309
4310 /*set encryption method*/
4311 switch (cipher)
4312 {
4313 case IW_AUTH_CIPHER_NONE:
4314 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4315 break;
4316
4317 case WLAN_CIPHER_SUITE_WEP40:
4318 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4319 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4320 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4321 else
4322 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4323 break;
4324
4325 case WLAN_CIPHER_SUITE_WEP104:
4326 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4327 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4328 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4329 else
4330 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4331 break;
4332
4333 case WLAN_CIPHER_SUITE_TKIP:
4334 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4335 break;
4336
4337 case WLAN_CIPHER_SUITE_CCMP:
4338 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4339 break;
4340#ifdef FEATURE_WLAN_WAPI
4341 case WLAN_CIPHER_SUITE_SMS4:
4342 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4343 break;
4344#endif
4345
4346#ifdef FEATURE_WLAN_CCX
4347 case WLAN_CIPHER_SUITE_KRK:
4348 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4349 break;
4350#endif
4351 default:
4352 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4353 __func__, cipher);
4354 return -EOPNOTSUPP;
4355 }
4356 }
4357
4358 if (ucast)
4359 {
4360 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4361 __func__, encryptionType);
4362 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4363 pWextState->roamProfile.EncryptionType.numEntries = 1;
4364 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4365 encryptionType;
4366 }
4367 else
4368 {
4369 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4370 __func__, encryptionType);
4371 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4372 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4373 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4374 }
4375
4376 return 0;
4377}
4378
4379
4380/*
4381 * FUNCTION: wlan_hdd_cfg80211_set_ie
4382 * This function is used to parse WPA/RSN IE's.
4383 */
4384int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4385 u8 *ie,
4386 size_t ie_len
4387 )
4388{
4389 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4390 u8 *genie = ie;
4391 v_U16_t remLen = ie_len;
4392#ifdef FEATURE_WLAN_WAPI
4393 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4394 u16 *tmp;
4395 v_U16_t akmsuiteCount;
4396 int *akmlist;
4397#endif
4398 ENTER();
4399
4400 /* clear previous assocAddIE */
4401 pWextState->assocAddIE.length = 0;
4402 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4403
4404 while (remLen >= 2)
4405 {
4406 v_U16_t eLen = 0;
4407 v_U8_t elementId;
4408 elementId = *genie++;
4409 eLen = *genie++;
4410 remLen -= 2;
4411
4412 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4413 __func__, elementId, eLen);
4414
4415 switch ( elementId )
4416 {
4417 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004418 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 -07004419 {
4420 hddLog(VOS_TRACE_LEVEL_ERROR,
4421 "%s: Invalid WPA IE", __func__);
4422 return -EINVAL;
4423 }
4424 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4425 {
4426 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4427 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4428 __func__, eLen + 2);
4429
4430 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4431 {
4432 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE. "
4433 "Need bigger buffer space\n");
4434 VOS_ASSERT(0);
4435 return -ENOMEM;
4436 }
4437 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4438 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4439 pWextState->assocAddIE.length += eLen + 2;
4440
4441 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4442 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4443 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4444 }
4445 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4446 {
4447 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4448 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4449 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4450 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4451 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4452 }
4453#ifdef WLAN_FEATURE_P2P
4454 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4455 P2P_OUI_TYPE_SIZE))
4456 /*Consider P2P IE, only for P2P Client */
4457 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4458 {
4459 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4460 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4461 __func__, eLen + 2);
4462
4463 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4464 {
4465 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4466 "Need bigger buffer space\n");
4467 VOS_ASSERT(0);
4468 return -ENOMEM;
4469 }
4470 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4471 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4472 pWextState->assocAddIE.length += eLen + 2;
4473
4474 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4475 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4476 }
4477#endif
4478#ifdef WLAN_FEATURE_WFD
4479 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4480 WFD_OUI_TYPE_SIZE))
4481 /*Consider WFD IE, only for P2P Client */
4482 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4483 {
4484 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4485 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4486 __func__, eLen + 2);
4487
4488 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4489 {
4490 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4491 "Need bigger buffer space\n");
4492 VOS_ASSERT(0);
4493 return -ENOMEM;
4494 }
4495 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4496 // WPS IE + P2P IE + WFD IE
4497 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4498 pWextState->assocAddIE.length += eLen + 2;
4499
4500 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4501 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4502 }
4503#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004504 /* Appending HS 2.0 Indication Element in Assiciation Request */
4505 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004506 HS20_OUI_TYPE_SIZE)) )
4507 {
4508 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4509 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4510 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004511
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004512 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4513 {
4514 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4515 "Need bigger buffer space\n");
4516 VOS_ASSERT(0);
4517 return -ENOMEM;
4518 }
4519 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4520 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004521
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004522 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4523 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4524 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004525
Jeff Johnson295189b2012-06-20 16:38:30 -07004526 break;
4527 case DOT11F_EID_RSN:
4528 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4529 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4530 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4531 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4532 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4533 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004534 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4535 case DOT11F_EID_EXTCAP:
4536 {
4537 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4538 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4539 __func__, eLen + 2);
4540
4541 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4542 {
4543 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4544 "Need bigger buffer space\n");
4545 VOS_ASSERT(0);
4546 return -ENOMEM;
4547 }
4548 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4549 pWextState->assocAddIE.length += eLen + 2;
4550
4551 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4552 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4553 break;
4554 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004555#ifdef FEATURE_WLAN_WAPI
4556 case WLAN_EID_WAPI:
4557 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4558 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4559 pAdapter->wapi_info.nWapiMode);
4560 tmp = (u16 *)ie;
4561 tmp = tmp + 2; // Skip element Id and Len, Version
4562 akmsuiteCount = WPA_GET_LE16(tmp);
4563 tmp = tmp + 1;
4564 akmlist = (int *)(tmp);
4565 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4566 {
4567 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4568 }
4569 else
4570 {
4571 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4572 VOS_ASSERT(0);
4573 return -EINVAL;
4574 }
4575
4576 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4577 {
4578 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004579 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4581 }
4582 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4583 {
4584 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004585 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004586 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4587 }
4588 break;
4589#endif
4590 default:
4591 hddLog (VOS_TRACE_LEVEL_ERROR,
4592 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004593 /* when Unknown IE is received we should break and continue
4594 * to the next IE in the buffer instead we were returning
4595 * so changing this to break */
4596 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004597 }
4598 genie += eLen;
4599 remLen -= eLen;
4600 }
4601 EXIT();
4602 return 0;
4603}
4604
4605/*
4606 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4607 * This function is used to initialize the security
4608 * parameters during connect operation.
4609 */
4610int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4611 struct cfg80211_connect_params *req
4612 )
4613{
4614 int status = 0;
4615 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4616 ENTER();
4617
4618 /*set wpa version*/
4619 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4620
4621 if (req->crypto.wpa_versions)
4622 {
4623 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4624 && ( (req->ie_len)
4625 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4626 // Make sure that it is including a WPA IE.
4627 /* Currently NL is putting WPA version 1 even for open,
4628 * since p2p ie is also put in same buffer.
4629 * */
4630 {
4631 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4632 }
4633 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4634 {
4635 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4636 }
4637 }
4638
4639 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4640 pWextState->wpaVersion);
4641
4642 /*set authentication type*/
4643 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4644
4645 if (0 > status)
4646 {
4647 hddLog(VOS_TRACE_LEVEL_ERROR,
4648 "%s: failed to set authentication type ", __func__);
4649 return status;
4650 }
4651
4652 /*set key mgmt type*/
4653 if (req->crypto.n_akm_suites)
4654 {
4655 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4656 if (0 > status)
4657 {
4658 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4659 __func__);
4660 return status;
4661 }
4662 }
4663
4664 /*set pairwise cipher type*/
4665 if (req->crypto.n_ciphers_pairwise)
4666 {
4667 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4668 req->crypto.ciphers_pairwise[0], true);
4669 if (0 > status)
4670 {
4671 hddLog(VOS_TRACE_LEVEL_ERROR,
4672 "%s: failed to set unicast cipher type", __func__);
4673 return status;
4674 }
4675 }
4676 else
4677 {
4678 /*Reset previous cipher suite to none*/
4679 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
4680 if (0 > status)
4681 {
4682 hddLog(VOS_TRACE_LEVEL_ERROR,
4683 "%s: failed to set unicast cipher type", __func__);
4684 return status;
4685 }
4686 }
4687
4688 /*set group cipher type*/
4689 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
4690 false);
4691
4692 if (0 > status)
4693 {
4694 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
4695 __func__);
4696 return status;
4697 }
4698
4699 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
4700 if (req->ie_len)
4701 {
4702 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
4703 if ( 0 > status)
4704 {
4705 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
4706 __func__);
4707 return status;
4708 }
4709 }
4710
4711 /*incase of WEP set default key information*/
4712 if (req->key && req->key_len)
4713 {
4714 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
4715 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
4716 )
4717 {
4718 if ( IW_AUTH_KEY_MGMT_802_1X
4719 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
4720 {
4721 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
4722 __func__);
4723 return -EOPNOTSUPP;
4724 }
4725 else
4726 {
4727 u8 key_len = req->key_len;
4728 u8 key_idx = req->key_idx;
4729
4730 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
4731 && (CSR_MAX_NUM_KEY > key_idx)
4732 )
4733 {
4734 hddLog(VOS_TRACE_LEVEL_INFO,
4735 "%s: setting default wep key, key_idx = %hu key_len %hu",
4736 __func__, key_idx, key_len);
4737 vos_mem_copy(
4738 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
4739 req->key, key_len);
4740 pWextState->roamProfile.Keys.KeyLength[key_idx] =
4741 (u8)key_len;
4742 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
4743 }
4744 }
4745 }
4746 }
4747
4748 return status;
4749}
4750
4751/*
4752 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4753 * This function is used to initialize the security
4754 * parameters during connect operation.
4755 */
4756static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
4757 struct net_device *ndev,
4758 struct cfg80211_connect_params *req
4759 )
4760{
4761 int status = 0;
4762 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
4763 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
4764 hdd_context_t *pHddCtx = NULL;
4765
4766 ENTER();
4767
4768 hddLog(VOS_TRACE_LEVEL_INFO,
4769 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4770
4771 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4772 {
4773 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4774 "%s:LOGP in Progress. Ignore!!!", __func__);
4775 return -EAGAIN;
4776 }
4777
4778#ifdef WLAN_BTAMP_FEATURE
4779 //Infra connect not supported when AMP traffic is on.
4780 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
4781 {
4782 hddLog(VOS_TRACE_LEVEL_ERROR,
4783 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004784 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07004785 }
4786#endif
4787 /*initialise security parameters*/
4788 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
4789
4790 if ( 0 > status)
4791 {
4792 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
4793 __func__);
4794 return status;
4795 }
4796
4797 //If Device Mode is Station Concurrent Sessions Exit BMps
4798 //P2P Mode will be taken care in Open/close adaptor
4799 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4800 (vos_concurrent_sessions_running()))
4801 {
4802 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4803
4804 if (NULL != pVosContext)
4805 {
4806 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4807 if(NULL != pHddCtx)
4808 {
4809 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
4810 }
4811 }
4812 }
4813
Mohit Khanna765234a2012-09-11 15:08:35 -07004814 if ( req->channel )
4815 {
4816 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
4817 req->ssid_len, req->bssid,
4818 req->channel->hw_value);
4819 }
4820 else
4821 {
4822 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
4823 req->ssid_len, req->bssid,
4824 0);
4825 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004826
4827 if (0 > status)
4828 {
4829 //ReEnable BMPS if disabled
4830 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
4831 (NULL != pHddCtx))
4832 {
4833 //ReEnable Bmps and Imps back
4834 hdd_enable_bmps_imps(pHddCtx);
4835 }
4836
4837 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
4838 return status;
4839 }
4840 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
4841 EXIT();
4842 return status;
4843}
4844
4845
4846/*
4847 * FUNCTION: wlan_hdd_cfg80211_disconnect
4848 * This function is used to issue a disconnect request to SME
4849 */
4850static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
4851 struct net_device *dev,
4852 u16 reason
4853 )
4854{
4855 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4856 tCsrRoamProfile *pRoamProfile =
4857 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
4858 int status = 0;
4859 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4860
4861 ENTER();
4862
4863 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4864 __func__,pAdapter->device_mode);
4865
4866 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
4867 __func__, reason);
4868
4869 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4870 {
4871 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4872 "%s:LOGP in Progress. Ignore!!!",__func__);
4873 return -EAGAIN;
4874 }
4875 if (NULL != pRoamProfile)
4876 {
4877 /*issue disconnect request to SME, if station is in connected state*/
4878 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
4879 {
4880 eCsrRoamDisconnectReason reasonCode =
4881 eCSR_DISCONNECT_REASON_UNSPECIFIED;
4882 switch(reason)
4883 {
4884 case WLAN_REASON_MIC_FAILURE:
4885 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
4886 break;
4887
4888 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
4889 case WLAN_REASON_DISASSOC_AP_BUSY:
4890 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
4891 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
4892 break;
4893
4894 case WLAN_REASON_PREV_AUTH_NOT_VALID:
4895 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
4896 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
4897 break;
4898
4899 case WLAN_REASON_DEAUTH_LEAVING:
4900 default:
4901 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
4902 break;
4903 }
4904 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4905 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
4906 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4907
4908 /*issue disconnect*/
4909 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4910 pAdapter->sessionId, reasonCode);
4911
4912 if ( 0 != status)
4913 {
4914 hddLog(VOS_TRACE_LEVEL_ERROR,
4915 "%s csrRoamDisconnect failure, returned %d \n",
4916 __func__, (int)status );
4917 return -EINVAL;
4918 }
4919
4920 wait_for_completion_interruptible_timeout(
4921 &pAdapter->disconnect_comp_var,
4922 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4923
4924
4925 /*stop tx queues*/
4926 netif_tx_disable(dev);
4927 netif_carrier_off(dev);
4928 }
4929 }
4930 else
4931 {
4932 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
4933 }
4934
4935 return status;
4936}
4937
4938/*
4939 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
4940 * This function is used to initialize the security
4941 * settings in IBSS mode.
4942 */
4943static int wlan_hdd_cfg80211_set_privacy_ibss(
4944 hdd_adapter_t *pAdapter,
4945 struct cfg80211_ibss_params *params
4946 )
4947{
4948 int status = 0;
4949 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4950 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4951 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4952
4953 ENTER();
4954
4955 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4956
4957 if (params->ie_len && ( NULL != params->ie) )
4958 {
4959 if (WLAN_EID_RSN == params->ie[0])
4960 {
4961 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4962 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4963 }
4964 else
4965 {
4966 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4967 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4968 }
4969 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
4970
4971 if (0 > status)
4972 {
4973 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
4974 __func__);
4975 return status;
4976 }
4977 }
4978
4979 pWextState->roamProfile.AuthType.authType[0] =
4980 pHddStaCtx->conn_info.authType =
4981 eCSR_AUTH_TYPE_OPEN_SYSTEM;
4982
4983 if (params->privacy)
4984 {
4985 /* Security enabled IBSS, At this time there is no information available
4986 * about the security paramters, so initialise the encryption type to
4987 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
4988 * The correct security parameters will be updated later in
4989 * wlan_hdd_cfg80211_add_key */
4990 /* Hal expects encryption type to be set inorder
4991 *enable privacy bit in beacons */
4992
4993 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4994 }
4995
4996 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4997 pWextState->roamProfile.EncryptionType.numEntries = 1;
4998 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
4999
5000 return status;
5001}
5002
5003/*
5004 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5005 * This function is used to create/join an IBSS
5006 */
5007static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5008 struct net_device *dev,
5009 struct cfg80211_ibss_params *params
5010 )
5011{
5012 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5013 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5014 tCsrRoamProfile *pRoamProfile;
5015 int status;
5016 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5017
5018 ENTER();
5019
5020 hddLog(VOS_TRACE_LEVEL_INFO,
5021 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5022
5023 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5024 {
5025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5026 "%s:LOGP in Progress. Ignore!!!", __func__);
5027 return -EAGAIN;
5028 }
5029
5030 if (NULL == pWextState)
5031 {
5032 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5033 __func__);
5034 return -EIO;
5035 }
5036
5037 pRoamProfile = &pWextState->roamProfile;
5038
5039 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5040 {
5041 hddLog (VOS_TRACE_LEVEL_ERROR,
5042 "%s Interface type is not set to IBSS \n", __func__);
5043 return -EINVAL;
5044 }
5045
5046 /* Set Channel */
5047 if (NULL != params->channel)
5048 {
5049 u8 channelNum;
5050 if (IEEE80211_BAND_5GHZ == params->channel->band)
5051 {
5052 hddLog(VOS_TRACE_LEVEL_ERROR,
5053 "%s: IBSS join is called with unsupported band %d",
5054 __func__, params->channel->band);
5055 return -EOPNOTSUPP;
5056 }
5057
5058 /* Get channel number */
5059 channelNum =
5060 ieee80211_frequency_to_channel(params->channel->center_freq);
5061
5062 /*TODO: use macro*/
5063 if (14 >= channelNum)
5064 {
5065 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5066 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5067 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5068 int indx;
5069
5070 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5071 validChan, &numChans))
5072 {
5073 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5074 __func__);
5075 return -EOPNOTSUPP;
5076 }
5077
5078 for (indx = 0; indx < numChans; indx++)
5079 {
5080 if (channelNum == validChan[indx])
5081 {
5082 break;
5083 }
5084 }
5085 if (indx >= numChans)
5086 {
5087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5088 __func__, channelNum);
5089 return -EINVAL;
5090 }
5091 /* Set the Operational Channel */
5092 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5093 channelNum);
5094 pRoamProfile->ChannelInfo.numOfChannels = 1;
5095 pHddStaCtx->conn_info.operationChannel = channelNum;
5096 pRoamProfile->ChannelInfo.ChannelList =
5097 &pHddStaCtx->conn_info.operationChannel;
5098 }
5099 else
5100 {
5101 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5102 __func__, channelNum);
5103 return -EINVAL;
5104 }
5105 }
5106
5107 /* Initialize security parameters */
5108 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5109 if (status < 0)
5110 {
5111 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5112 __func__);
5113 return status;
5114 }
5115
5116 /* Issue connect start */
5117 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005118 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005119
5120 if (0 > status)
5121 {
5122 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5123 return status;
5124 }
5125
5126 return 0;
5127}
5128
5129/*
5130 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5131 * This function is used to leave an IBSS
5132 */
5133static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5134 struct net_device *dev
5135 )
5136{
5137 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5138 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5139 tCsrRoamProfile *pRoamProfile;
5140
5141 ENTER();
5142
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005143 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5144 {
5145 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5146 "%s:LOGP in Progress. Ignore!!!", __func__);
5147 return -EAGAIN;
5148 }
5149
Jeff Johnson295189b2012-06-20 16:38:30 -07005150 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5151 if (NULL == pWextState)
5152 {
5153 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5154 __func__);
5155 return -EIO;
5156 }
5157
5158 pRoamProfile = &pWextState->roamProfile;
5159
5160 /* Issue disconnect only if interface type is set to IBSS */
5161 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5162 {
5163 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5164 __func__);
5165 return -EINVAL;
5166 }
5167
5168 /* Issue Disconnect request */
5169 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5170 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5171 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5172
5173 return 0;
5174}
5175
5176/*
5177 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5178 * This function is used to set the phy parameters
5179 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5180 */
5181static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5182 u32 changed)
5183{
5184 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5185 tHalHandle hHal = pHddCtx->hHal;
5186
5187 ENTER();
5188
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005189 if ( pHddCtx->isLogpInProgress )
5190 {
5191 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5192 "%s:LOGP in Progress. Ignore!!!", __func__);
5193 return -EAGAIN;
5194 }
5195
Jeff Johnson295189b2012-06-20 16:38:30 -07005196 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5197 {
5198 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5199 WNI_CFG_RTS_THRESHOLD_STAMAX :
5200 wiphy->rts_threshold;
5201
5202 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5203 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5204 {
5205 hddLog(VOS_TRACE_LEVEL_ERROR,
5206 "%s: Invalid RTS Threshold value %hu",
5207 __func__, rts_threshold);
5208 return -EINVAL;
5209 }
5210
5211 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5212 rts_threshold, ccmCfgSetCallback,
5213 eANI_BOOLEAN_TRUE))
5214 {
5215 hddLog(VOS_TRACE_LEVEL_ERROR,
5216 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5217 __func__, rts_threshold);
5218 return -EIO;
5219 }
5220
5221 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5222 rts_threshold);
5223 }
5224
5225 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5226 {
5227 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5228 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5229 wiphy->frag_threshold;
5230
5231 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5232 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5233 {
5234 hddLog(VOS_TRACE_LEVEL_ERROR,
5235 "%s: Invalid frag_threshold value %hu", __func__,
5236 frag_threshold);
5237 return -EINVAL;
5238 }
5239
5240 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5241 frag_threshold, ccmCfgSetCallback,
5242 eANI_BOOLEAN_TRUE))
5243 {
5244 hddLog(VOS_TRACE_LEVEL_ERROR,
5245 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5246 __func__, frag_threshold);
5247 return -EIO;
5248 }
5249
5250 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5251 frag_threshold);
5252 }
5253
5254 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5255 || (changed & WIPHY_PARAM_RETRY_LONG))
5256 {
5257 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5258 wiphy->retry_short :
5259 wiphy->retry_long;
5260
5261 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5262 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5263 {
5264 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5265 __func__, retry_value);
5266 return -EINVAL;
5267 }
5268
5269 if (changed & WIPHY_PARAM_RETRY_SHORT)
5270 {
5271 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5272 retry_value, ccmCfgSetCallback,
5273 eANI_BOOLEAN_TRUE))
5274 {
5275 hddLog(VOS_TRACE_LEVEL_ERROR,
5276 "%s: ccmCfgSetInt failed for long retry count %hu",
5277 __func__, retry_value);
5278 return -EIO;
5279 }
5280 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5281 __func__, retry_value);
5282 }
5283 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5284 {
5285 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5286 retry_value, ccmCfgSetCallback,
5287 eANI_BOOLEAN_TRUE))
5288 {
5289 hddLog(VOS_TRACE_LEVEL_ERROR,
5290 "%s: ccmCfgSetInt failed for short retry count %hu",
5291 __func__, retry_value);
5292 return -EIO;
5293 }
5294 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5295 __func__, retry_value);
5296 }
5297 }
5298
5299 return 0;
5300}
5301
5302/*
5303 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5304 * This function is used to set the txpower
5305 */
5306static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5307#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5308 enum tx_power_setting type,
5309#else
5310 enum nl80211_tx_power_setting type,
5311#endif
5312 int dbm)
5313{
5314 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5315 tHalHandle hHal = pHddCtx->hHal;
5316 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5317 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5318
5319 ENTER();
5320
5321 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5322 dbm, ccmCfgSetCallback,
5323 eANI_BOOLEAN_TRUE))
5324 {
5325 hddLog(VOS_TRACE_LEVEL_ERROR,
5326 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5327 return -EIO;
5328 }
5329
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005330 if ( pHddCtx->isLogpInProgress )
5331 {
5332 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5333 "%s:LOGP in Progress. Ignore!!!", __func__);
5334 return -EAGAIN;
5335 }
5336
Jeff Johnson295189b2012-06-20 16:38:30 -07005337 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5338 dbm);
5339
5340 switch(type)
5341 {
5342 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5343 /* Fall through */
5344 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5345 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5346 {
5347 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5348 __func__);
5349 return -EIO;
5350 }
5351 break;
5352 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5353 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5354 __func__);
5355 return -EOPNOTSUPP;
5356 break;
5357 default:
5358 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5359 __func__, type);
5360 return -EIO;
5361 }
5362
5363 return 0;
5364}
5365
5366/*
5367 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5368 * This function is used to read the txpower
5369 */
5370static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5371{
5372
5373 hdd_adapter_t *pAdapter;
5374 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5375
Jeff Johnsone7245742012-09-05 17:12:55 -07005376 ENTER();
5377
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 if (NULL == pHddCtx)
5379 {
5380 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5381 *dbm = 0;
5382 return -ENOENT;
5383 }
5384
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005385 if ( pHddCtx->isLogpInProgress )
5386 {
5387 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5388 "%s:LOGP in Progress. Ignore!!!", __func__);
5389 return -EAGAIN;
5390 }
5391
Jeff Johnson295189b2012-06-20 16:38:30 -07005392 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5393 if (NULL == pAdapter)
5394 {
5395 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5396 return -ENOENT;
5397 }
5398
5399 wlan_hdd_get_classAstats(pAdapter);
5400 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5401
Jeff Johnsone7245742012-09-05 17:12:55 -07005402 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005403 return 0;
5404}
5405
5406static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5407 u8* mac, struct station_info *sinfo)
5408{
5409 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5410 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5411 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5412 tANI_U8 rate_flags;
5413
5414 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5415 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5416 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5417
5418 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5419 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5420 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5421 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5422 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5423 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5424 tANI_U16 maxRate = 0;
5425 tANI_U16 myRate;
5426 tANI_U16 currentRate = 0;
5427 tANI_U8 maxSpeedMCS = 0;
5428 tANI_U8 maxMCSIdx = 0;
5429 tANI_U8 rateFlag = 1;
5430 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005431 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005432
Jeff Johnsone7245742012-09-05 17:12:55 -07005433 ENTER();
5434
Jeff Johnson295189b2012-06-20 16:38:30 -07005435 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5436 (0 == ssidlen))
5437 {
5438 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5439 " Invalid ssidlen, %d", __func__, ssidlen);
5440 /*To keep GUI happy*/
5441 return 0;
5442 }
5443
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005444 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5445 {
5446 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5447 "%s:LOGP in Progress. Ignore!!!", __func__);
5448 return -EAGAIN;
5449 }
5450
Jeff Johnson295189b2012-06-20 16:38:30 -07005451 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5452 sinfo->filled |= STATION_INFO_SIGNAL;
5453
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005454 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005455 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5456
5457 //convert to the UI units of 100kbps
5458 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5459
5460#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005461 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 -07005462 sinfo->signal,
5463 pCfg->reportMaxLinkSpeed,
5464 myRate,
5465 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005466 (int) pCfg->linkSpeedRssiMid,
5467 (int) pCfg->linkSpeedRssiLow,
5468 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005469#endif //LINKSPEED_DEBUG_ENABLED
5470
5471 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5472 {
5473 // we do not want to necessarily report the current speed
5474 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5475 {
5476 // report the max possible speed
5477 rssidx = 0;
5478 }
5479 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5480 {
5481 // report the max possible speed with RSSI scaling
5482 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5483 {
5484 // report the max possible speed
5485 rssidx = 0;
5486 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005487 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005488 {
5489 // report middle speed
5490 rssidx = 1;
5491 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005492 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5493 {
5494 // report middle speed
5495 rssidx = 2;
5496 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 else
5498 {
5499 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005500 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005501 }
5502 }
5503 else
5504 {
5505 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5506 hddLog(VOS_TRACE_LEVEL_ERROR,
5507 "%s: Invalid value for reportMaxLinkSpeed: %u",
5508 __func__, pCfg->reportMaxLinkSpeed);
5509 rssidx = 0;
5510 }
5511
5512 maxRate = 0;
5513
5514 /* Get Basic Rate Set */
5515 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5516 for (i = 0; i < ORLeng; i++)
5517 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005518 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005519 {
5520 /* Validate Rate Set */
5521 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5522 {
5523 currentRate = supported_data_rate[j].supported_rate[rssidx];
5524 break;
5525 }
5526 }
5527 /* Update MAX rate */
5528 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5529 }
5530
5531 /* Get Extended Rate Set */
5532 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5533 for (i = 0; i < ERLeng; i++)
5534 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005535 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005536 {
5537 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5538 {
5539 currentRate = supported_data_rate[j].supported_rate[rssidx];
5540 break;
5541 }
5542 }
5543 /* Update MAX rate */
5544 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5545 }
5546
5547 /* Get MCS Rate Set -- but only if we are connected at MCS
5548 rates or if we are always reporting max speed or if we have
5549 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005550 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 {
5552 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5553 rateFlag = 0;
5554 if (rate_flags & eHAL_TX_RATE_HT40)
5555 {
5556 rateFlag |= 1;
5557 }
5558 if (rate_flags & eHAL_TX_RATE_SGI)
5559 {
5560 rateFlag |= 2;
5561 }
5562
5563 for (i = 0; i < MCSLeng; i++)
5564 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005565 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5566 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005567 {
5568 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5569 {
5570 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5571 break;
5572 }
5573 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005574 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005575 {
5576 maxRate = currentRate;
5577 maxSpeedMCS = 1;
5578 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5579 }
5580 }
5581 }
5582
5583 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005584 if (((maxRate < myRate) && (0 == rssidx)) ||
5585 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005586 {
5587 maxRate = myRate;
5588 if (rate_flags & eHAL_TX_RATE_LEGACY)
5589 {
5590 maxSpeedMCS = 0;
5591 }
5592 else
5593 {
5594 maxSpeedMCS = 1;
5595 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5596 }
5597 }
5598
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005599 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005600 {
5601 sinfo->txrate.legacy = maxRate;
5602#ifdef LINKSPEED_DEBUG_ENABLED
5603 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5604#endif //LINKSPEED_DEBUG_ENABLED
5605 }
5606 else
5607 {
5608 sinfo->txrate.mcs = maxMCSIdx;
5609 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5610 if (rate_flags & eHAL_TX_RATE_SGI)
5611 {
5612 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5613 }
5614 if (rate_flags & eHAL_TX_RATE_HT40)
5615 {
5616 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5617 }
5618#ifdef LINKSPEED_DEBUG_ENABLED
5619 pr_info("Reporting MCS rate %d flags %x\n",
5620 sinfo->txrate.mcs,
5621 sinfo->txrate.flags );
5622#endif //LINKSPEED_DEBUG_ENABLED
5623 }
5624 }
5625 else
5626 {
5627 // report current rate instead of max rate
5628
5629 if (rate_flags & eHAL_TX_RATE_LEGACY)
5630 {
5631 //provide to the UI in units of 100kbps
5632 sinfo->txrate.legacy = myRate;
5633#ifdef LINKSPEED_DEBUG_ENABLED
5634 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5635#endif //LINKSPEED_DEBUG_ENABLED
5636 }
5637 else
5638 {
5639 //must be MCS
5640 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5641 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5642 if (rate_flags & eHAL_TX_RATE_SGI)
5643 {
5644 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5645 }
5646 if (rate_flags & eHAL_TX_RATE_HT40)
5647 {
5648 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5649 }
5650#ifdef LINKSPEED_DEBUG_ENABLED
5651 pr_info("Reporting actual MCS rate %d flags %x\n",
5652 sinfo->txrate.mcs,
5653 sinfo->txrate.flags );
5654#endif //LINKSPEED_DEBUG_ENABLED
5655 }
5656 }
5657 sinfo->filled |= STATION_INFO_TX_BITRATE;
5658
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005659 sinfo->tx_packets =
5660 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5661 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5662 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5663 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5664
5665 sinfo->tx_retries =
5666 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
5667 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
5668 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
5669 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
5670
5671 sinfo->tx_failed =
5672 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
5673 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
5674 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
5675 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
5676
5677 sinfo->filled |=
5678 STATION_INFO_TX_PACKETS |
5679 STATION_INFO_TX_RETRIES |
5680 STATION_INFO_TX_FAILED;
5681
5682 EXIT();
5683 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005684}
5685
5686static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
5687 struct net_device *dev, bool mode, v_SINT_t timeout)
5688{
5689 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5690 VOS_STATUS vos_status;
5691
Jeff Johnsone7245742012-09-05 17:12:55 -07005692 ENTER();
5693
Jeff Johnson295189b2012-06-20 16:38:30 -07005694 if (NULL == pAdapter)
5695 {
5696 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5697 return -ENODEV;
5698 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005699 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5700 {
5701 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5702 "%s:LOGP in Progress. Ignore!!!", __func__);
5703 return -EAGAIN;
5704 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005705
5706 /**The get power cmd from the supplicant gets updated by the nl only
5707 *on successful execution of the function call
5708 *we are oppositely mapped w.r.t mode in the driver
5709 **/
5710 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
5711
Jeff Johnsone7245742012-09-05 17:12:55 -07005712 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005713 if (VOS_STATUS_E_FAILURE == vos_status)
5714 {
5715 return -EINVAL;
5716 }
5717 return 0;
5718}
5719
5720
5721#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5722static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
5723 struct net_device *netdev,
5724 u8 key_index)
5725{
Jeff Johnsone7245742012-09-05 17:12:55 -07005726 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005727 return 0;
5728}
5729#endif //LINUX_VERSION_CODE
5730
5731#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5732static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5733 struct net_device *dev,
5734 struct ieee80211_txq_params *params)
5735{
Jeff Johnsone7245742012-09-05 17:12:55 -07005736 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 return 0;
5738}
5739#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5740static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5741 struct ieee80211_txq_params *params)
5742{
Jeff Johnsone7245742012-09-05 17:12:55 -07005743 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005744 return 0;
5745}
5746#endif //LINUX_VERSION_CODE
5747
5748static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
5749 struct net_device *dev, u8 *mac)
5750{
5751 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5752
Jeff Johnsone7245742012-09-05 17:12:55 -07005753 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005754 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5755 {
5756 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5757 return -EINVAL;
5758 }
5759
5760 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5761 {
5762 hddLog( LOGE,
5763 "%s: Wlan Load/Unload is in progress", __func__);
5764 return -EBUSY;
5765 }
5766
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005767 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5768 {
5769 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5770 "%s:LOGP in Progress. Ignore!!!", __func__);
5771 return -EAGAIN;
5772 }
5773
Jeff Johnson295189b2012-06-20 16:38:30 -07005774 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
5775#ifdef WLAN_FEATURE_P2P
5776 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5777#endif
5778 )
5779 {
5780 if( NULL == mac )
5781 {
5782 v_U16_t i;
5783 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
5784 {
5785 if(pAdapter->aStaInfo[i].isUsed)
5786 {
5787 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
5788 hddLog(VOS_TRACE_LEVEL_INFO,
5789 "%s: Delete STA with MAC::"
5790 "%02x:%02x:%02x:%02x:%02x:%02x",
5791 __func__,
5792 macAddr[0], macAddr[1], macAddr[2],
5793 macAddr[3], macAddr[4], macAddr[5]);
5794 hdd_softap_sta_deauth(pAdapter, macAddr);
5795 }
5796 }
5797 }
5798 else
5799 {
5800 hddLog(VOS_TRACE_LEVEL_INFO,
5801 "%s: Delete STA with MAC::"
5802 "%02x:%02x:%02x:%02x:%02x:%02x",
5803 __func__,
5804 mac[0], mac[1], mac[2],
5805 mac[3], mac[4], mac[5]);
5806 hdd_softap_sta_deauth(pAdapter, mac);
5807 }
5808 }
5809
5810 EXIT();
5811
5812 return 0;
5813}
5814
5815static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
5816 struct net_device *dev, u8 *mac, struct station_parameters *params)
5817{
5818 // TODO: Implement this later.
Jeff Johnsone7245742012-09-05 17:12:55 -07005819 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005820 return 0;
5821}
5822
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005823
5824#ifdef FEATURE_WLAN_LFR
5825static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005826 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005827{
5828#define MAX_PMKSAIDS_IN_CACHE 8
5829 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07005830 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005831 tANI_U32 j=0;
5832 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5833 tHalHandle halHandle;
5834 eHalStatus result;
5835 tANI_U8 BSSIDMatched = 0;
5836
Jeff Johnsone7245742012-09-05 17:12:55 -07005837 ENTER();
5838
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005839 // Validate pAdapter
5840 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5841 {
5842 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5843 return -EINVAL;
5844 }
5845
5846 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5847 {
5848 hddLog( LOGE,
5849 "%s: Wlan Load/Unload is in progress", __func__);
5850 return -EBUSY;
5851 }
5852
5853 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5854 {
5855 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5856 "%s:LOGP in Progress. Ignore!!!", __func__);
5857 return -EAGAIN;
5858 }
5859
5860 // Retrieve halHandle
5861 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
5862
5863 for (j = 0; j < i; j++)
5864 {
5865 if(vos_mem_compare(PMKIDCache[j].BSSID,
5866 pmksa->bssid, WNI_CFG_BSSID_LEN))
5867 {
5868 /* BSSID matched previous entry. Overwrite it. */
5869 BSSIDMatched = 1;
5870 vos_mem_copy(PMKIDCache[j].BSSID,
5871 pmksa->bssid, WNI_CFG_BSSID_LEN);
5872 vos_mem_copy(PMKIDCache[j].PMKID,
5873 pmksa->pmkid,
5874 CSR_RSN_PMKID_SIZE);
5875 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005876 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005877 dump_bssid(pmksa->bssid);
5878 dump_pmkid(halHandle, pmksa->pmkid);
5879 break;
5880 }
5881 }
5882
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07005883 /* Check we compared all entries,if then take the first slot now */
5884 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
5885
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005886 if (!BSSIDMatched)
5887 {
5888 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
5889 vos_mem_copy(PMKIDCache[i].BSSID,
5890 pmksa->bssid, ETHER_ADDR_LEN);
5891 vos_mem_copy(PMKIDCache[i].PMKID,
5892 pmksa->pmkid,
5893 CSR_RSN_PMKID_SIZE);
5894 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005895 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005896 dump_bssid(pmksa->bssid);
5897 dump_pmkid(halHandle, pmksa->pmkid);
5898 // Increment the HDD Local Cache index
5899 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
5900 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
5901 }
5902
5903
5904 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
5905 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005906 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005907 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005908 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005909 // Finally set the PMKSA ID Cache in CSR
5910 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
5911 PMKIDCache,
5912 i );
5913 return 0;
5914}
5915
5916
5917static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005918 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005919{
Jeff Johnsone7245742012-09-05 17:12:55 -07005920 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005921 // TODO: Implement this later.
5922 return 0;
5923}
5924
5925static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5926{
Jeff Johnsone7245742012-09-05 17:12:55 -07005927 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005928 // TODO: Implement this later.
5929 return 0;
5930}
5931#endif
5932
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07005933#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
5934static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
5935 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
5936{
5937 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5938 hdd_station_ctx_t *pHddStaCtx;
5939
5940 if (NULL == pAdapter)
5941 {
5942 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5943 return -ENODEV;
5944 }
5945
5946 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5947
5948 // Added for debug on reception of Re-assoc Req.
5949 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5950 {
5951 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
5952 ftie->ie_len);
5953 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
5954 }
5955
5956#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
5957 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
5958 ftie->ie_len);
5959#endif
5960
5961 // Pass the received FT IEs to SME
5962 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
5963 ftie->ie_len);
5964 return 0;
5965}
5966#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005967
Jeff Johnson295189b2012-06-20 16:38:30 -07005968/* cfg80211_ops */
5969static struct cfg80211_ops wlan_hdd_cfg80211_ops =
5970{
5971 .add_virtual_intf = wlan_hdd_add_virtual_intf,
5972 .del_virtual_intf = wlan_hdd_del_virtual_intf,
5973 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
5974 .change_station = wlan_hdd_change_station,
5975#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
5976 .add_beacon = wlan_hdd_cfg80211_add_beacon,
5977 .del_beacon = wlan_hdd_cfg80211_del_beacon,
5978 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005979#else
5980 .start_ap = wlan_hdd_cfg80211_start_ap,
5981 .change_beacon = wlan_hdd_cfg80211_change_beacon,
5982 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07005983#endif
5984 .change_bss = wlan_hdd_cfg80211_change_bss,
5985 .add_key = wlan_hdd_cfg80211_add_key,
5986 .get_key = wlan_hdd_cfg80211_get_key,
5987 .del_key = wlan_hdd_cfg80211_del_key,
5988 .set_default_key = wlan_hdd_cfg80211_set_default_key,
5989 .set_channel = wlan_hdd_cfg80211_set_channel,
5990 .scan = wlan_hdd_cfg80211_scan,
5991 .connect = wlan_hdd_cfg80211_connect,
5992 .disconnect = wlan_hdd_cfg80211_disconnect,
5993 .join_ibss = wlan_hdd_cfg80211_join_ibss,
5994 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
5995 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
5996 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
5997 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
5998#ifdef WLAN_FEATURE_P2P
5999 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6000 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6001 .mgmt_tx = wlan_hdd_action,
6002#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6003 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6004 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6005 .set_txq_params = wlan_hdd_set_txq_params,
6006#endif
6007#endif
6008 .get_station = wlan_hdd_cfg80211_get_station,
6009 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6010 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006011 .add_station = wlan_hdd_cfg80211_add_station,
6012#ifdef FEATURE_WLAN_LFR
6013 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6014 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6015 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6016#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006017#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6018 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6019#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006020};
6021
6022#endif // CONFIG_CFG80211