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