blob: e024861bb3e91802b6c949b3ae7f798262517d0e [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");
Jeff Johnsone7245742012-09-05 17:12:55 -07003508 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003509 }
3510
3511 /*
3512 * setting up 0, just in case.
3513 */
3514 req->n_ssids = 0;
3515 req->n_channels = 0;
3516 req->ie = 0;
3517
3518 /*
3519 * cfg80211_scan_done informing NL80211 about completion
3520 * of scanning
3521 */
3522 cfg80211_scan_done(req, false);
3523 complete(&pAdapter->abortscan_event_var);
3524 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003525 /* Scan is no longer pending */
3526 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003527
3528#ifdef WLAN_FEATURE_P2P
3529 /* Flush out scan result after p2p_serach is done */
Jeff Johnsone7245742012-09-05 17:12:55 -07003530 if(pScanInfo->flushP2pScanResults)
Jeff Johnson295189b2012-06-20 16:38:30 -07003531 {
3532 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -07003533 sme_ScanFlushResult(WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId);
Jeff Johnsone7245742012-09-05 17:12:55 -07003534 pScanInfo->flushP2pScanResults = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003535 }
3536#endif
3537
Jeff Johnsone7245742012-09-05 17:12:55 -07003538allow_suspend:
3539 /* release the wake lock */
3540 if((eConnectionState_NotConnected ==
3541 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
3542 {
3543 hdd_allow_suspend();
3544 }
3545
Jeff Johnson295189b2012-06-20 16:38:30 -07003546 EXIT();
3547 return 0;
3548}
3549
3550/*
3551 * FUNCTION: wlan_hdd_cfg80211_scan
3552 * this scan respond to scan trigger and update cfg80211 scan database
3553 * later, scan dump command can be used to recieve scan results
3554 */
3555int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3556 struct cfg80211_scan_request *request)
3557{
3558 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3559 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3560 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3561 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3562 tCsrScanRequest scanRequest;
3563 tANI_U8 *channelList = NULL, i;
3564 v_U32_t scanId = 0;
3565 int status = 0;
3566 hdd_scaninfo_t *pScanInfo = &pAdapter->scan_info;
Jeff Johnsone7245742012-09-05 17:12:55 -07003567 v_U8_t preventSuspend = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003568#ifdef WLAN_FEATURE_P2P
3569 v_U8_t* pP2pIe = NULL;
3570#endif
3571
3572 ENTER();
3573
3574 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3575 __func__,pAdapter->device_mode);
3576#ifdef WLAN_BTAMP_FEATURE
3577 //Scan not supported when AMP traffic is on.
3578 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
3579 {
3580 hddLog(VOS_TRACE_LEVEL_ERROR,
3581 "%s: No scanning when AMP is on", __func__);
3582 return -EOPNOTSUPP;
3583 }
3584#endif
3585 //Scan on any other interface is not supported.
3586 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
3587 {
3588 hddLog(VOS_TRACE_LEVEL_ERROR,
3589 "%s: Not scanning on device_mode = %d",
3590 __func__, pAdapter->device_mode);
3591 return -EOPNOTSUPP;
3592 }
3593
3594 if (TRUE == pScanInfo->mScanPending)
3595 {
3596 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
3597 return -EBUSY;
3598 }
3599
3600 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3601 {
3602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3603 "%s:LOGP in Progress. Ignore!!!", __func__);
3604 return -EAGAIN;
3605 }
3606
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07003607 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
3608 {
3609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3610 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
3611 return -EAGAIN;
3612 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07003613 //Don't Allow Scan and return busy if Remain On
3614 //Channel and action frame is pending
3615 //Otherwise Cancel Remain On Channel and allow Scan
3616 //If no action frame pending
3617 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
3618 {
3619 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
3620 return -EBUSY;
3621 }
3622
Jeff Johnson295189b2012-06-20 16:38:30 -07003623 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
3624 {
3625 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
3626 "%s: Aquire lock fail", __func__);
3627 return -EAGAIN;
3628 }
3629 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
3630 {
3631 hddLog(VOS_TRACE_LEVEL_WARN,
3632 "%s: MAX TM Level Scan not allowed", __func__);
3633 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3634 return -EBUSY;
3635 }
3636 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3637
3638 vos_mem_zero( &scanRequest, sizeof(scanRequest));
3639
3640 if (NULL != request)
3641 {
3642 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
3643 (int)request->n_ssids);
3644
3645 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
3646 * Becasue of this, driver is assuming that this is not wildcard scan and so
3647 * is not aging out the scan results.
3648 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07003649 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07003650 {
3651 request->n_ssids = 0;
3652 }
3653
3654 if (0 < request->n_ssids)
3655 {
3656 tCsrSSIDInfo *SsidInfo;
3657 int j;
3658 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
3659 /* Allocate num_ssid tCsrSSIDInfo structure */
3660 SsidInfo = scanRequest.SSIDs.SSIDList =
3661 ( tCsrSSIDInfo *)vos_mem_malloc(
3662 request->n_ssids*sizeof(tCsrSSIDInfo));
3663
3664 if(NULL == scanRequest.SSIDs.SSIDList)
3665 {
3666 hddLog(VOS_TRACE_LEVEL_ERROR,
3667 "memory alloc failed SSIDInfo buffer");
3668 return -ENOMEM;
3669 }
3670
3671 /* copy all the ssid's and their length */
3672 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
3673 {
3674 /* get the ssid length */
3675 SsidInfo->SSID.length = request->ssids[j].ssid_len;
3676 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
3677 SsidInfo->SSID.length);
3678 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
3679 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
3680 j, SsidInfo->SSID.ssId);
3681 }
3682 /* set the scan type to active */
3683 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3684 }
3685 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
3686 {
3687 /* set the scan type to active */
3688 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3689 }
3690 else
3691 {
3692 /*Set the scan type to default type, in this case it is ACTIVE*/
3693 scanRequest.scanType = pScanInfo->scan_mode;
3694 }
3695 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
3696 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
3697 }
3698 else
3699 {
3700 /* set the scan type to active */
3701 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3702 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
3703
3704 /* set min and max channel time to zero */
3705 scanRequest.minChnTime = 0;
3706 scanRequest.maxChnTime = 0;
3707 }
3708
3709 /* set BSSType to default type */
3710 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
3711
3712 /*TODO: scan the requested channels only*/
3713
3714 /*Right now scanning all the channels */
3715 if( request )
3716 {
3717 if( request->n_channels )
3718 {
3719 channelList = vos_mem_malloc( request->n_channels );
3720 if( NULL == channelList )
3721 {
3722 status = -ENOMEM;
3723 goto free_mem;
3724 }
3725
3726 for( i = 0 ; i < request->n_channels ; i++ )
3727 channelList[i] = request->channels[i]->hw_value;
3728 }
3729
3730 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
3731 scanRequest.ChannelInfo.ChannelList = channelList;
3732
3733 /* set requestType to full scan */
3734 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3735
3736 if( request->ie_len )
3737 {
3738 /* save this for future association (join requires this) */
3739 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
3740 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
3741 pScanInfo->scanAddIE.length = request->ie_len;
3742
3743 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07003744 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3745 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07003746 )
3747 {
3748 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
3749 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
3750 }
3751
3752 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
3753 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
3754
3755#ifdef WLAN_FEATURE_P2P
3756 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
3757 request->ie_len);
3758 if (pP2pIe != NULL)
3759 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003760 /* no_cck will be set during p2p find to disable 11b rates */
3761 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07003762 {
3763 tANI_U8 sessionId = pAdapter->sessionId;
3764 hddLog(VOS_TRACE_LEVEL_INFO,
3765 "%s: This is a P2P Search", __func__);
3766 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07003767
3768 /* Flush the scan results only for P2P search.
3769 P2P search happens on 3 social channels (1, 6, 11) */
3770 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
3771 {
3772 pScanInfo->flushP2pScanResults = 1;
3773 sme_ScanFlushResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
3774 sessionId );
3775 }
3776
3777 /*
3778 Skip Dfs Channel in case of P2P Search
3779 if it is set in ini file
3780 */
3781 if(cfg_param->skipDfsChnlInP2pSearch)
3782 {
3783 scanRequest.skipDfsChnlInP2pSearch = 1;
3784 }
3785 else
3786 {
3787 scanRequest.skipDfsChnlInP2pSearch = 0;
3788 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003789
3790 /* set requestType to P2P Discovery */
3791 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnson295189b2012-06-20 16:38:30 -07003792 }
3793 }
3794#endif
3795 }
3796 }
3797
3798 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
3799
Jeff Johnsone7245742012-09-05 17:12:55 -07003800 /*If the station is not connected and recieved a scan request, acquire the
3801 * wake lock to not request the suspend from Android*/
3802 if((eConnectionState_NotConnected ==
3803 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003805 preventSuspend = 1;
3806 hdd_prevent_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07003807 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003808
3809 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 pAdapter->sessionId, &scanRequest, &scanId,
3811 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07003812
Jeff Johnson295189b2012-06-20 16:38:30 -07003813 if (eHAL_STATUS_SUCCESS != status)
3814 {
3815 hddLog(VOS_TRACE_LEVEL_ERROR,
3816 "%s: sme_ScanRequest returned error %d", __func__, status);
3817 complete(&pScanInfo->scan_req_completion_event);
3818 status = -EIO;
Jeff Johnsone7245742012-09-05 17:12:55 -07003819 if(preventSuspend)
3820 {
3821 hdd_allow_suspend();
3822 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003823 goto free_mem;
3824 }
3825
3826 pScanInfo->mScanPending = TRUE;
3827 pAdapter->request = request;
3828 pScanInfo->scanId = scanId;
3829
3830 complete(&pScanInfo->scan_req_completion_event);
3831
3832free_mem:
3833 if( scanRequest.SSIDs.SSIDList )
3834 {
3835 vos_mem_free(scanRequest.SSIDs.SSIDList);
3836 }
3837
3838 if( channelList )
3839 vos_mem_free( channelList );
3840
3841 EXIT();
3842
3843 return status;
3844}
3845
3846/*
3847 * FUNCTION: wlan_hdd_cfg80211_connect_start
3848 * This function is used to start the association process
3849 */
3850int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07003851 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07003852{
3853 int status = 0;
3854 hdd_wext_state_t *pWextState;
3855 v_U32_t roamId;
3856 tCsrRoamProfile *pRoamProfile;
3857 eMib_dot11DesiredBssType connectedBssType;
3858 eCsrAuthType RSNAuthType;
3859
3860 ENTER();
3861
3862 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3863
3864 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
3865 {
3866 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
3867 return -EINVAL;
3868 }
3869
3870 pRoamProfile = &pWextState->roamProfile;
3871
3872 if (pRoamProfile)
3873 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003874 int ret = 0;
3875 hdd_station_ctx_t *pHddStaCtx;
3876 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3877 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
3878
3879 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
3880 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
3881 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07003882 {
3883 /* Issue disconnect to CSR */
3884 INIT_COMPLETION(pAdapter->disconnect_comp_var);
3885 if( eHAL_STATUS_SUCCESS ==
3886 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
3887 pAdapter->sessionId,
3888 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
3889 {
Jeff Johnsone7245742012-09-05 17:12:55 -07003890 ret = wait_for_completion_interruptible_timeout(
3891 &pAdapter->disconnect_comp_var,
3892 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3893 if (0 == ret)
3894 {
3895 VOS_ASSERT(0);
3896 }
3897 }
3898 }
3899 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
3900 {
3901 ret = wait_for_completion_interruptible_timeout(
3902 &pAdapter->disconnect_comp_var,
3903 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3904 if (0 == ret)
3905 {
3906 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07003907 }
3908 }
3909
3910 if (HDD_WMM_USER_MODE_NO_QOS ==
3911 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
3912 {
3913 /*QoS not enabled in cfg file*/
3914 pRoamProfile->uapsd_mask = 0;
3915 }
3916 else
3917 {
3918 /*QoS enabled, update uapsd mask from cfg file*/
3919 pRoamProfile->uapsd_mask =
3920 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
3921 }
3922
3923 pRoamProfile->SSIDs.numOfSSIDs = 1;
3924 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
3925 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
3926 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
3927 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
3928 ssid, ssid_len);
3929
3930 if (bssid)
3931 {
3932 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
3933 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
3934 WNI_CFG_BSSID_LEN);
3935 /* Save BSSID in seperate variable as well, as RoamProfile
3936 BSSID is getting zeroed out in the association process. And in
3937 case of join failure we should send valid BSSID to supplicant
3938 */
3939 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
3940 WNI_CFG_BSSID_LEN);
3941 }
3942
3943 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
3944 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
3945 {
3946 /*set gen ie*/
3947 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
3948 /*set auth*/
3949 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
3950 }
3951 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
3952 eCSR_AUTH_TYPE_OPEN_SYSTEM)
3953 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3954 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
3955 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
3956 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
3957 )
3958 {
3959 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
3960 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
3961 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
3962 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
3963 eCSR_AUTH_TYPE_AUTOSWITCH;
3964 pWextState->roamProfile.AuthType.authType[0] =
3965 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
3966 }
3967#ifdef FEATURE_WLAN_WAPI
3968 if (pAdapter->wapi_info.nWapiMode)
3969 {
3970 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __FUNCTION__);
3971 switch (pAdapter->wapi_info.wapiAuthMode)
3972 {
3973 case WAPI_AUTH_MODE_PSK:
3974 {
3975 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __FUNCTION__,
3976 pAdapter->wapi_info.wapiAuthMode);
3977 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
3978 break;
3979 }
3980 case WAPI_AUTH_MODE_CERT:
3981 {
3982 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __FUNCTION__,
3983 pAdapter->wapi_info.wapiAuthMode);
3984 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
3985 break;
3986 }
3987 } // End of switch
3988 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
3989 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
3990 {
3991 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __FUNCTION__);
3992 pRoamProfile->AuthType.numEntries = 1;
3993 pRoamProfile->EncryptionType.numEntries = 1;
3994 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
3995 pRoamProfile->mcEncryptionType.numEntries = 1;
3996 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
3997 }
3998 }
3999#endif /* FEATURE_WLAN_WAPI */
4000 pRoamProfile->csrPersona = pAdapter->device_mode;
4001
Jeff Johnson32d95a32012-09-10 13:15:23 -07004002 if( operatingChannel )
4003 {
4004 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4005 pRoamProfile->ChannelInfo.numOfChannels = 1;
4006 }
4007
Jeff Johnson295189b2012-06-20 16:38:30 -07004008 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4009 pAdapter->sessionId, pRoamProfile, &roamId);
4010
Jeff Johnson32d95a32012-09-10 13:15:23 -07004011 pRoamProfile->ChannelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004012 pRoamProfile->ChannelInfo.numOfChannels = 0;
4013 }
4014 else
4015 {
4016 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4017 return -EINVAL;
4018 }
4019 EXIT();
4020 return status;
4021}
4022
4023/*
4024 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4025 * This function is used to set the authentication type (OPEN/SHARED).
4026 *
4027 */
4028static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4029 enum nl80211_auth_type auth_type)
4030{
4031 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4032 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4033
4034 ENTER();
4035
4036 /*set authentication type*/
4037 switch (auth_type)
4038 {
4039 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4040 case NL80211_AUTHTYPE_AUTOMATIC:
4041 hddLog(VOS_TRACE_LEVEL_INFO,
4042 "%s: set authentication type to OPEN", __func__);
4043 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4044 break;
4045
4046 case NL80211_AUTHTYPE_SHARED_KEY:
4047 hddLog(VOS_TRACE_LEVEL_INFO,
4048 "%s: set authentication type to SHARED", __func__);
4049 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4050 break;
4051#ifdef FEATURE_WLAN_CCX
4052 case NL80211_AUTHTYPE_NETWORK_EAP:
4053 hddLog(VOS_TRACE_LEVEL_INFO,
4054 "%s: set authentication type to CCKM WPA", __func__);
4055 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4056 break;
4057#endif
4058
4059
4060 default:
4061 hddLog(VOS_TRACE_LEVEL_ERROR,
4062 "%s: Unsupported authentication type %d", __func__,
4063 auth_type);
4064 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4065 return -EINVAL;
4066 }
4067
4068 pWextState->roamProfile.AuthType.authType[0] =
4069 pHddStaCtx->conn_info.authType;
4070 return 0;
4071}
4072
4073/*
4074 * FUNCTION: wlan_hdd_set_akm_suite
4075 * This function is used to set the key mgmt type(PSK/8021x).
4076 *
4077 */
4078static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4079 u32 key_mgmt
4080 )
4081{
4082 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4083 ENTER();
4084
4085 /*set key mgmt type*/
4086 switch(key_mgmt)
4087 {
4088 case WLAN_AKM_SUITE_PSK:
4089 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4090 __func__);
4091 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4092 break;
4093
4094 case WLAN_AKM_SUITE_8021X:
4095 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4096 __func__);
4097 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4098 break;
4099#ifdef FEATURE_WLAN_CCX
4100#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4101#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4102 case WLAN_AKM_SUITE_CCKM:
4103 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4104 __func__);
4105 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4106 break;
4107#endif
4108
4109 default:
4110 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4111 __func__, key_mgmt);
4112 return -EINVAL;
4113
4114 }
4115 return 0;
4116}
4117
4118/*
4119 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4120 * This function is used to set the encryption type
4121 * (NONE/WEP40/WEP104/TKIP/CCMP).
4122 */
4123static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4124 u32 cipher,
4125 bool ucast
4126 )
4127{
4128 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4129 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4130 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4131
4132 ENTER();
4133
4134 if (!cipher)
4135 {
4136 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4137 __func__, cipher);
4138 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4139 }
4140 else
4141 {
4142
4143 /*set encryption method*/
4144 switch (cipher)
4145 {
4146 case IW_AUTH_CIPHER_NONE:
4147 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4148 break;
4149
4150 case WLAN_CIPHER_SUITE_WEP40:
4151 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4152 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4153 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4154 else
4155 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4156 break;
4157
4158 case WLAN_CIPHER_SUITE_WEP104:
4159 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4160 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4161 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4162 else
4163 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4164 break;
4165
4166 case WLAN_CIPHER_SUITE_TKIP:
4167 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4168 break;
4169
4170 case WLAN_CIPHER_SUITE_CCMP:
4171 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4172 break;
4173#ifdef FEATURE_WLAN_WAPI
4174 case WLAN_CIPHER_SUITE_SMS4:
4175 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4176 break;
4177#endif
4178
4179#ifdef FEATURE_WLAN_CCX
4180 case WLAN_CIPHER_SUITE_KRK:
4181 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4182 break;
4183#endif
4184 default:
4185 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4186 __func__, cipher);
4187 return -EOPNOTSUPP;
4188 }
4189 }
4190
4191 if (ucast)
4192 {
4193 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4194 __func__, encryptionType);
4195 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4196 pWextState->roamProfile.EncryptionType.numEntries = 1;
4197 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4198 encryptionType;
4199 }
4200 else
4201 {
4202 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4203 __func__, encryptionType);
4204 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4205 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4206 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4207 }
4208
4209 return 0;
4210}
4211
4212
4213/*
4214 * FUNCTION: wlan_hdd_cfg80211_set_ie
4215 * This function is used to parse WPA/RSN IE's.
4216 */
4217int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4218 u8 *ie,
4219 size_t ie_len
4220 )
4221{
4222 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4223 u8 *genie = ie;
4224 v_U16_t remLen = ie_len;
4225#ifdef FEATURE_WLAN_WAPI
4226 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4227 u16 *tmp;
4228 v_U16_t akmsuiteCount;
4229 int *akmlist;
4230#endif
4231 ENTER();
4232
4233 /* clear previous assocAddIE */
4234 pWextState->assocAddIE.length = 0;
4235 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4236
4237 while (remLen >= 2)
4238 {
4239 v_U16_t eLen = 0;
4240 v_U8_t elementId;
4241 elementId = *genie++;
4242 eLen = *genie++;
4243 remLen -= 2;
4244
4245 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4246 __func__, elementId, eLen);
4247
4248 switch ( elementId )
4249 {
4250 case DOT11F_EID_WPA:
4251 if ((2+4) > eLen) /* should have at least OUI */
4252 {
4253 hddLog(VOS_TRACE_LEVEL_ERROR,
4254 "%s: Invalid WPA IE", __func__);
4255 return -EINVAL;
4256 }
4257 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4258 {
4259 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4260 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4261 __func__, eLen + 2);
4262
4263 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4264 {
4265 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE. "
4266 "Need bigger buffer space\n");
4267 VOS_ASSERT(0);
4268 return -ENOMEM;
4269 }
4270 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4271 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4272 pWextState->assocAddIE.length += eLen + 2;
4273
4274 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4275 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4276 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4277 }
4278 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4279 {
4280 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4281 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4282 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4283 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4284 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4285 }
4286#ifdef WLAN_FEATURE_P2P
4287 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4288 P2P_OUI_TYPE_SIZE))
4289 /*Consider P2P IE, only for P2P Client */
4290 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4291 {
4292 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4293 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4294 __func__, eLen + 2);
4295
4296 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4297 {
4298 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4299 "Need bigger buffer space\n");
4300 VOS_ASSERT(0);
4301 return -ENOMEM;
4302 }
4303 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4304 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4305 pWextState->assocAddIE.length += eLen + 2;
4306
4307 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4308 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4309 }
4310#endif
4311#ifdef WLAN_FEATURE_WFD
4312 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4313 WFD_OUI_TYPE_SIZE))
4314 /*Consider WFD IE, only for P2P Client */
4315 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4316 {
4317 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4318 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4319 __func__, eLen + 2);
4320
4321 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4322 {
4323 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4324 "Need bigger buffer space\n");
4325 VOS_ASSERT(0);
4326 return -ENOMEM;
4327 }
4328 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4329 // WPS IE + P2P IE + WFD IE
4330 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4331 pWextState->assocAddIE.length += eLen + 2;
4332
4333 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4334 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4335 }
4336#endif
4337 break;
4338 case DOT11F_EID_RSN:
4339 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4340 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4341 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4342 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4343 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4344 break;
4345#ifdef FEATURE_WLAN_WAPI
4346 case WLAN_EID_WAPI:
4347 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4348 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4349 pAdapter->wapi_info.nWapiMode);
4350 tmp = (u16 *)ie;
4351 tmp = tmp + 2; // Skip element Id and Len, Version
4352 akmsuiteCount = WPA_GET_LE16(tmp);
4353 tmp = tmp + 1;
4354 akmlist = (int *)(tmp);
4355 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4356 {
4357 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4358 }
4359 else
4360 {
4361 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4362 VOS_ASSERT(0);
4363 return -EINVAL;
4364 }
4365
4366 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4367 {
4368 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
4369 __FUNCTION__);
4370 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4371 }
4372 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4373 {
4374 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
4375 __FUNCTION__);
4376 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4377 }
4378 break;
4379#endif
4380 default:
4381 hddLog (VOS_TRACE_LEVEL_ERROR,
4382 "%s Set UNKNOWN IE %X", __func__, elementId);
4383 return 0;
4384 }
4385 genie += eLen;
4386 remLen -= eLen;
4387 }
4388 EXIT();
4389 return 0;
4390}
4391
4392/*
4393 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4394 * This function is used to initialize the security
4395 * parameters during connect operation.
4396 */
4397int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4398 struct cfg80211_connect_params *req
4399 )
4400{
4401 int status = 0;
4402 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4403 ENTER();
4404
4405 /*set wpa version*/
4406 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4407
4408 if (req->crypto.wpa_versions)
4409 {
4410 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4411 && ( (req->ie_len)
4412 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4413 // Make sure that it is including a WPA IE.
4414 /* Currently NL is putting WPA version 1 even for open,
4415 * since p2p ie is also put in same buffer.
4416 * */
4417 {
4418 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4419 }
4420 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4421 {
4422 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4423 }
4424 }
4425
4426 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4427 pWextState->wpaVersion);
4428
4429 /*set authentication type*/
4430 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4431
4432 if (0 > status)
4433 {
4434 hddLog(VOS_TRACE_LEVEL_ERROR,
4435 "%s: failed to set authentication type ", __func__);
4436 return status;
4437 }
4438
4439 /*set key mgmt type*/
4440 if (req->crypto.n_akm_suites)
4441 {
4442 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4443 if (0 > status)
4444 {
4445 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4446 __func__);
4447 return status;
4448 }
4449 }
4450
4451 /*set pairwise cipher type*/
4452 if (req->crypto.n_ciphers_pairwise)
4453 {
4454 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4455 req->crypto.ciphers_pairwise[0], true);
4456 if (0 > status)
4457 {
4458 hddLog(VOS_TRACE_LEVEL_ERROR,
4459 "%s: failed to set unicast cipher type", __func__);
4460 return status;
4461 }
4462 }
4463 else
4464 {
4465 /*Reset previous cipher suite to none*/
4466 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
4467 if (0 > status)
4468 {
4469 hddLog(VOS_TRACE_LEVEL_ERROR,
4470 "%s: failed to set unicast cipher type", __func__);
4471 return status;
4472 }
4473 }
4474
4475 /*set group cipher type*/
4476 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
4477 false);
4478
4479 if (0 > status)
4480 {
4481 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
4482 __func__);
4483 return status;
4484 }
4485
4486 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
4487 if (req->ie_len)
4488 {
4489 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
4490 if ( 0 > status)
4491 {
4492 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
4493 __func__);
4494 return status;
4495 }
4496 }
4497
4498 /*incase of WEP set default key information*/
4499 if (req->key && req->key_len)
4500 {
4501 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
4502 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
4503 )
4504 {
4505 if ( IW_AUTH_KEY_MGMT_802_1X
4506 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
4507 {
4508 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
4509 __func__);
4510 return -EOPNOTSUPP;
4511 }
4512 else
4513 {
4514 u8 key_len = req->key_len;
4515 u8 key_idx = req->key_idx;
4516
4517 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
4518 && (CSR_MAX_NUM_KEY > key_idx)
4519 )
4520 {
4521 hddLog(VOS_TRACE_LEVEL_INFO,
4522 "%s: setting default wep key, key_idx = %hu key_len %hu",
4523 __func__, key_idx, key_len);
4524 vos_mem_copy(
4525 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
4526 req->key, key_len);
4527 pWextState->roamProfile.Keys.KeyLength[key_idx] =
4528 (u8)key_len;
4529 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
4530 }
4531 }
4532 }
4533 }
4534
4535 return status;
4536}
4537
4538/*
4539 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4540 * This function is used to initialize the security
4541 * parameters during connect operation.
4542 */
4543static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
4544 struct net_device *ndev,
4545 struct cfg80211_connect_params *req
4546 )
4547{
4548 int status = 0;
4549 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
4550 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
4551 hdd_context_t *pHddCtx = NULL;
4552
4553 ENTER();
4554
4555 hddLog(VOS_TRACE_LEVEL_INFO,
4556 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4557
4558 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4559 {
4560 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4561 "%s:LOGP in Progress. Ignore!!!", __func__);
4562 return -EAGAIN;
4563 }
4564
4565#ifdef WLAN_BTAMP_FEATURE
4566 //Infra connect not supported when AMP traffic is on.
4567 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
4568 {
4569 hddLog(VOS_TRACE_LEVEL_ERROR,
4570 "%s: No connection when AMP is on", __func__);
4571 return -1;
4572 }
4573#endif
4574 /*initialise security parameters*/
4575 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
4576
4577 if ( 0 > status)
4578 {
4579 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
4580 __func__);
4581 return status;
4582 }
4583
4584 //If Device Mode is Station Concurrent Sessions Exit BMps
4585 //P2P Mode will be taken care in Open/close adaptor
4586 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4587 (vos_concurrent_sessions_running()))
4588 {
4589 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4590
4591 if (NULL != pVosContext)
4592 {
4593 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4594 if(NULL != pHddCtx)
4595 {
4596 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
4597 }
4598 }
4599 }
4600
Mohit Khanna765234a2012-09-11 15:08:35 -07004601 if ( req->channel )
4602 {
4603 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
4604 req->ssid_len, req->bssid,
4605 req->channel->hw_value);
4606 }
4607 else
4608 {
4609 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
4610 req->ssid_len, req->bssid,
4611 0);
4612 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004613
4614 if (0 > status)
4615 {
4616 //ReEnable BMPS if disabled
4617 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
4618 (NULL != pHddCtx))
4619 {
4620 //ReEnable Bmps and Imps back
4621 hdd_enable_bmps_imps(pHddCtx);
4622 }
4623
4624 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
4625 return status;
4626 }
4627 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
4628 EXIT();
4629 return status;
4630}
4631
4632
4633/*
4634 * FUNCTION: wlan_hdd_cfg80211_disconnect
4635 * This function is used to issue a disconnect request to SME
4636 */
4637static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
4638 struct net_device *dev,
4639 u16 reason
4640 )
4641{
4642 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4643 tCsrRoamProfile *pRoamProfile =
4644 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
4645 int status = 0;
4646 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4647
4648 ENTER();
4649
4650 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4651 __func__,pAdapter->device_mode);
4652
4653 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
4654 __func__, reason);
4655
4656 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4657 {
4658 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4659 "%s:LOGP in Progress. Ignore!!!",__func__);
4660 return -EAGAIN;
4661 }
4662 if (NULL != pRoamProfile)
4663 {
4664 /*issue disconnect request to SME, if station is in connected state*/
4665 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
4666 {
4667 eCsrRoamDisconnectReason reasonCode =
4668 eCSR_DISCONNECT_REASON_UNSPECIFIED;
4669 switch(reason)
4670 {
4671 case WLAN_REASON_MIC_FAILURE:
4672 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
4673 break;
4674
4675 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
4676 case WLAN_REASON_DISASSOC_AP_BUSY:
4677 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
4678 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
4679 break;
4680
4681 case WLAN_REASON_PREV_AUTH_NOT_VALID:
4682 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
4683 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
4684 break;
4685
4686 case WLAN_REASON_DEAUTH_LEAVING:
4687 default:
4688 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
4689 break;
4690 }
4691 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4692 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
4693 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4694
4695 /*issue disconnect*/
4696 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4697 pAdapter->sessionId, reasonCode);
4698
4699 if ( 0 != status)
4700 {
4701 hddLog(VOS_TRACE_LEVEL_ERROR,
4702 "%s csrRoamDisconnect failure, returned %d \n",
4703 __func__, (int)status );
4704 return -EINVAL;
4705 }
4706
4707 wait_for_completion_interruptible_timeout(
4708 &pAdapter->disconnect_comp_var,
4709 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4710
4711
4712 /*stop tx queues*/
4713 netif_tx_disable(dev);
4714 netif_carrier_off(dev);
4715 }
4716 }
4717 else
4718 {
4719 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
4720 }
4721
4722 return status;
4723}
4724
4725/*
4726 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
4727 * This function is used to initialize the security
4728 * settings in IBSS mode.
4729 */
4730static int wlan_hdd_cfg80211_set_privacy_ibss(
4731 hdd_adapter_t *pAdapter,
4732 struct cfg80211_ibss_params *params
4733 )
4734{
4735 int status = 0;
4736 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4737 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4738 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4739
4740 ENTER();
4741
4742 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4743
4744 if (params->ie_len && ( NULL != params->ie) )
4745 {
4746 if (WLAN_EID_RSN == params->ie[0])
4747 {
4748 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4749 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4750 }
4751 else
4752 {
4753 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4754 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4755 }
4756 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
4757
4758 if (0 > status)
4759 {
4760 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
4761 __func__);
4762 return status;
4763 }
4764 }
4765
4766 pWextState->roamProfile.AuthType.authType[0] =
4767 pHddStaCtx->conn_info.authType =
4768 eCSR_AUTH_TYPE_OPEN_SYSTEM;
4769
4770 if (params->privacy)
4771 {
4772 /* Security enabled IBSS, At this time there is no information available
4773 * about the security paramters, so initialise the encryption type to
4774 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
4775 * The correct security parameters will be updated later in
4776 * wlan_hdd_cfg80211_add_key */
4777 /* Hal expects encryption type to be set inorder
4778 *enable privacy bit in beacons */
4779
4780 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4781 }
4782
4783 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4784 pWextState->roamProfile.EncryptionType.numEntries = 1;
4785 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
4786
4787 return status;
4788}
4789
4790/*
4791 * FUNCTION: wlan_hdd_cfg80211_join_ibss
4792 * This function is used to create/join an IBSS
4793 */
4794static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
4795 struct net_device *dev,
4796 struct cfg80211_ibss_params *params
4797 )
4798{
4799 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4800 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4801 tCsrRoamProfile *pRoamProfile;
4802 int status;
4803 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4804
4805 ENTER();
4806
4807 hddLog(VOS_TRACE_LEVEL_INFO,
4808 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4809
4810 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4811 {
4812 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4813 "%s:LOGP in Progress. Ignore!!!", __func__);
4814 return -EAGAIN;
4815 }
4816
4817 if (NULL == pWextState)
4818 {
4819 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
4820 __func__);
4821 return -EIO;
4822 }
4823
4824 pRoamProfile = &pWextState->roamProfile;
4825
4826 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
4827 {
4828 hddLog (VOS_TRACE_LEVEL_ERROR,
4829 "%s Interface type is not set to IBSS \n", __func__);
4830 return -EINVAL;
4831 }
4832
4833 /* Set Channel */
4834 if (NULL != params->channel)
4835 {
4836 u8 channelNum;
4837 if (IEEE80211_BAND_5GHZ == params->channel->band)
4838 {
4839 hddLog(VOS_TRACE_LEVEL_ERROR,
4840 "%s: IBSS join is called with unsupported band %d",
4841 __func__, params->channel->band);
4842 return -EOPNOTSUPP;
4843 }
4844
4845 /* Get channel number */
4846 channelNum =
4847 ieee80211_frequency_to_channel(params->channel->center_freq);
4848
4849 /*TODO: use macro*/
4850 if (14 >= channelNum)
4851 {
4852 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
4853 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
4854 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4855 int indx;
4856
4857 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
4858 validChan, &numChans))
4859 {
4860 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
4861 __func__);
4862 return -EOPNOTSUPP;
4863 }
4864
4865 for (indx = 0; indx < numChans; indx++)
4866 {
4867 if (channelNum == validChan[indx])
4868 {
4869 break;
4870 }
4871 }
4872 if (indx >= numChans)
4873 {
4874 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
4875 __func__, channelNum);
4876 return -EINVAL;
4877 }
4878 /* Set the Operational Channel */
4879 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
4880 channelNum);
4881 pRoamProfile->ChannelInfo.numOfChannels = 1;
4882 pHddStaCtx->conn_info.operationChannel = channelNum;
4883 pRoamProfile->ChannelInfo.ChannelList =
4884 &pHddStaCtx->conn_info.operationChannel;
4885 }
4886 else
4887 {
4888 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
4889 __func__, channelNum);
4890 return -EINVAL;
4891 }
4892 }
4893
4894 /* Initialize security parameters */
4895 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
4896 if (status < 0)
4897 {
4898 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
4899 __func__);
4900 return status;
4901 }
4902
4903 /* Issue connect start */
4904 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004905 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004906
4907 if (0 > status)
4908 {
4909 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
4910 return status;
4911 }
4912
4913 return 0;
4914}
4915
4916/*
4917 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
4918 * This function is used to leave an IBSS
4919 */
4920static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
4921 struct net_device *dev
4922 )
4923{
4924 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4925 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4926 tCsrRoamProfile *pRoamProfile;
4927
4928 ENTER();
4929
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004930 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4931 {
4932 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4933 "%s:LOGP in Progress. Ignore!!!", __func__);
4934 return -EAGAIN;
4935 }
4936
Jeff Johnson295189b2012-06-20 16:38:30 -07004937 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4938 if (NULL == pWextState)
4939 {
4940 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
4941 __func__);
4942 return -EIO;
4943 }
4944
4945 pRoamProfile = &pWextState->roamProfile;
4946
4947 /* Issue disconnect only if interface type is set to IBSS */
4948 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
4949 {
4950 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
4951 __func__);
4952 return -EINVAL;
4953 }
4954
4955 /* Issue Disconnect request */
4956 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4957 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
4958 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4959
4960 return 0;
4961}
4962
4963/*
4964 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
4965 * This function is used to set the phy parameters
4966 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
4967 */
4968static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
4969 u32 changed)
4970{
4971 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4972 tHalHandle hHal = pHddCtx->hHal;
4973
4974 ENTER();
4975
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004976 if ( pHddCtx->isLogpInProgress )
4977 {
4978 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4979 "%s:LOGP in Progress. Ignore!!!", __func__);
4980 return -EAGAIN;
4981 }
4982
Jeff Johnson295189b2012-06-20 16:38:30 -07004983 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
4984 {
4985 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
4986 WNI_CFG_RTS_THRESHOLD_STAMAX :
4987 wiphy->rts_threshold;
4988
4989 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
4990 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
4991 {
4992 hddLog(VOS_TRACE_LEVEL_ERROR,
4993 "%s: Invalid RTS Threshold value %hu",
4994 __func__, rts_threshold);
4995 return -EINVAL;
4996 }
4997
4998 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
4999 rts_threshold, ccmCfgSetCallback,
5000 eANI_BOOLEAN_TRUE))
5001 {
5002 hddLog(VOS_TRACE_LEVEL_ERROR,
5003 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5004 __func__, rts_threshold);
5005 return -EIO;
5006 }
5007
5008 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5009 rts_threshold);
5010 }
5011
5012 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5013 {
5014 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5015 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5016 wiphy->frag_threshold;
5017
5018 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5019 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5020 {
5021 hddLog(VOS_TRACE_LEVEL_ERROR,
5022 "%s: Invalid frag_threshold value %hu", __func__,
5023 frag_threshold);
5024 return -EINVAL;
5025 }
5026
5027 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5028 frag_threshold, ccmCfgSetCallback,
5029 eANI_BOOLEAN_TRUE))
5030 {
5031 hddLog(VOS_TRACE_LEVEL_ERROR,
5032 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5033 __func__, frag_threshold);
5034 return -EIO;
5035 }
5036
5037 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5038 frag_threshold);
5039 }
5040
5041 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5042 || (changed & WIPHY_PARAM_RETRY_LONG))
5043 {
5044 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5045 wiphy->retry_short :
5046 wiphy->retry_long;
5047
5048 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5049 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5050 {
5051 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5052 __func__, retry_value);
5053 return -EINVAL;
5054 }
5055
5056 if (changed & WIPHY_PARAM_RETRY_SHORT)
5057 {
5058 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5059 retry_value, ccmCfgSetCallback,
5060 eANI_BOOLEAN_TRUE))
5061 {
5062 hddLog(VOS_TRACE_LEVEL_ERROR,
5063 "%s: ccmCfgSetInt failed for long retry count %hu",
5064 __func__, retry_value);
5065 return -EIO;
5066 }
5067 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5068 __func__, retry_value);
5069 }
5070 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5071 {
5072 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5073 retry_value, ccmCfgSetCallback,
5074 eANI_BOOLEAN_TRUE))
5075 {
5076 hddLog(VOS_TRACE_LEVEL_ERROR,
5077 "%s: ccmCfgSetInt failed for short retry count %hu",
5078 __func__, retry_value);
5079 return -EIO;
5080 }
5081 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5082 __func__, retry_value);
5083 }
5084 }
5085
5086 return 0;
5087}
5088
5089/*
5090 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5091 * This function is used to set the txpower
5092 */
5093static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5094#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5095 enum tx_power_setting type,
5096#else
5097 enum nl80211_tx_power_setting type,
5098#endif
5099 int dbm)
5100{
5101 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5102 tHalHandle hHal = pHddCtx->hHal;
5103 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5104 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5105
5106 ENTER();
5107
5108 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5109 dbm, ccmCfgSetCallback,
5110 eANI_BOOLEAN_TRUE))
5111 {
5112 hddLog(VOS_TRACE_LEVEL_ERROR,
5113 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5114 return -EIO;
5115 }
5116
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005117 if ( pHddCtx->isLogpInProgress )
5118 {
5119 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5120 "%s:LOGP in Progress. Ignore!!!", __func__);
5121 return -EAGAIN;
5122 }
5123
Jeff Johnson295189b2012-06-20 16:38:30 -07005124 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5125 dbm);
5126
5127 switch(type)
5128 {
5129 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5130 /* Fall through */
5131 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5132 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5133 {
5134 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5135 __func__);
5136 return -EIO;
5137 }
5138 break;
5139 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5140 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5141 __func__);
5142 return -EOPNOTSUPP;
5143 break;
5144 default:
5145 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5146 __func__, type);
5147 return -EIO;
5148 }
5149
5150 return 0;
5151}
5152
5153/*
5154 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5155 * This function is used to read the txpower
5156 */
5157static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5158{
5159
5160 hdd_adapter_t *pAdapter;
5161 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5162
Jeff Johnsone7245742012-09-05 17:12:55 -07005163 ENTER();
5164
Jeff Johnson295189b2012-06-20 16:38:30 -07005165 if (NULL == pHddCtx)
5166 {
5167 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5168 *dbm = 0;
5169 return -ENOENT;
5170 }
5171
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005172 if ( pHddCtx->isLogpInProgress )
5173 {
5174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5175 "%s:LOGP in Progress. Ignore!!!", __func__);
5176 return -EAGAIN;
5177 }
5178
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5180 if (NULL == pAdapter)
5181 {
5182 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5183 return -ENOENT;
5184 }
5185
5186 wlan_hdd_get_classAstats(pAdapter);
5187 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5188
Jeff Johnsone7245742012-09-05 17:12:55 -07005189 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005190 return 0;
5191}
5192
5193static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5194 u8* mac, struct station_info *sinfo)
5195{
5196 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5197 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5198 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5199 tANI_U8 rate_flags;
5200
5201 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5202 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5203 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5204
5205 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5206 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5207 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5208 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5209 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5210 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5211 tANI_U16 maxRate = 0;
5212 tANI_U16 myRate;
5213 tANI_U16 currentRate = 0;
5214 tANI_U8 maxSpeedMCS = 0;
5215 tANI_U8 maxMCSIdx = 0;
5216 tANI_U8 rateFlag = 1;
5217 tANI_U8 i, j, rssidx;
5218
Jeff Johnsone7245742012-09-05 17:12:55 -07005219 ENTER();
5220
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5222 (0 == ssidlen))
5223 {
5224 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5225 " Invalid ssidlen, %d", __func__, ssidlen);
5226 /*To keep GUI happy*/
5227 return 0;
5228 }
5229
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005230 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5231 {
5232 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5233 "%s:LOGP in Progress. Ignore!!!", __func__);
5234 return -EAGAIN;
5235 }
5236
Jeff Johnson295189b2012-06-20 16:38:30 -07005237 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5238 sinfo->filled |= STATION_INFO_SIGNAL;
5239
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005240 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005241 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5242
5243 //convert to the UI units of 100kbps
5244 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5245
5246#ifdef LINKSPEED_DEBUG_ENABLED
5247 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi low %d\n",
5248 sinfo->signal,
5249 pCfg->reportMaxLinkSpeed,
5250 myRate,
5251 (int) pCfg->linkSpeedRssiHigh,
5252 (int) pCfg->linkSpeedRssiLow);
5253#endif //LINKSPEED_DEBUG_ENABLED
5254
5255 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5256 {
5257 // we do not want to necessarily report the current speed
5258 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5259 {
5260 // report the max possible speed
5261 rssidx = 0;
5262 }
5263 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5264 {
5265 // report the max possible speed with RSSI scaling
5266 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5267 {
5268 // report the max possible speed
5269 rssidx = 0;
5270 }
5271 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5272 {
5273 // report middle speed
5274 rssidx = 1;
5275 }
5276 else
5277 {
5278 // report actual speed
5279 rssidx = 2;
5280 }
5281 }
5282 else
5283 {
5284 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5285 hddLog(VOS_TRACE_LEVEL_ERROR,
5286 "%s: Invalid value for reportMaxLinkSpeed: %u",
5287 __func__, pCfg->reportMaxLinkSpeed);
5288 rssidx = 0;
5289 }
5290
5291 maxRate = 0;
5292
5293 /* Get Basic Rate Set */
5294 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5295 for (i = 0; i < ORLeng; i++)
5296 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005297 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005298 {
5299 /* Validate Rate Set */
5300 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5301 {
5302 currentRate = supported_data_rate[j].supported_rate[rssidx];
5303 break;
5304 }
5305 }
5306 /* Update MAX rate */
5307 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5308 }
5309
5310 /* Get Extended Rate Set */
5311 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5312 for (i = 0; i < ERLeng; i++)
5313 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005314 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005315 {
5316 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5317 {
5318 currentRate = supported_data_rate[j].supported_rate[rssidx];
5319 break;
5320 }
5321 }
5322 /* Update MAX rate */
5323 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5324 }
5325
5326 /* Get MCS Rate Set -- but only if we are connected at MCS
5327 rates or if we are always reporting max speed or if we have
5328 good rssi */
5329 if ((0 == rssidx) || !(rate_flags & eHAL_TX_RATE_LEGACY))
5330 {
5331 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5332 rateFlag = 0;
5333 if (rate_flags & eHAL_TX_RATE_HT40)
5334 {
5335 rateFlag |= 1;
5336 }
5337 if (rate_flags & eHAL_TX_RATE_SGI)
5338 {
5339 rateFlag |= 2;
5340 }
5341
5342 for (i = 0; i < MCSLeng; i++)
5343 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005344 for (j = 0; j < (sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0])); j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005345 {
5346 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5347 {
5348 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5349 break;
5350 }
5351 }
5352 if (currentRate > maxRate)
5353 {
5354 maxRate = currentRate;
5355 maxSpeedMCS = 1;
5356 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5357 }
5358 }
5359 }
5360
5361 // make sure we report a value at least as big as our current rate
5362 if (maxRate < myRate)
5363 {
5364 maxRate = myRate;
5365 if (rate_flags & eHAL_TX_RATE_LEGACY)
5366 {
5367 maxSpeedMCS = 0;
5368 }
5369 else
5370 {
5371 maxSpeedMCS = 1;
5372 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5373 }
5374 }
5375
5376 if (!maxSpeedMCS)
5377 {
5378 sinfo->txrate.legacy = maxRate;
5379#ifdef LINKSPEED_DEBUG_ENABLED
5380 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5381#endif //LINKSPEED_DEBUG_ENABLED
5382 }
5383 else
5384 {
5385 sinfo->txrate.mcs = maxMCSIdx;
5386 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5387 if (rate_flags & eHAL_TX_RATE_SGI)
5388 {
5389 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5390 }
5391 if (rate_flags & eHAL_TX_RATE_HT40)
5392 {
5393 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5394 }
5395#ifdef LINKSPEED_DEBUG_ENABLED
5396 pr_info("Reporting MCS rate %d flags %x\n",
5397 sinfo->txrate.mcs,
5398 sinfo->txrate.flags );
5399#endif //LINKSPEED_DEBUG_ENABLED
5400 }
5401 }
5402 else
5403 {
5404 // report current rate instead of max rate
5405
5406 if (rate_flags & eHAL_TX_RATE_LEGACY)
5407 {
5408 //provide to the UI in units of 100kbps
5409 sinfo->txrate.legacy = myRate;
5410#ifdef LINKSPEED_DEBUG_ENABLED
5411 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5412#endif //LINKSPEED_DEBUG_ENABLED
5413 }
5414 else
5415 {
5416 //must be MCS
5417 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5418 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5419 if (rate_flags & eHAL_TX_RATE_SGI)
5420 {
5421 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5422 }
5423 if (rate_flags & eHAL_TX_RATE_HT40)
5424 {
5425 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5426 }
5427#ifdef LINKSPEED_DEBUG_ENABLED
5428 pr_info("Reporting actual MCS rate %d flags %x\n",
5429 sinfo->txrate.mcs,
5430 sinfo->txrate.flags );
5431#endif //LINKSPEED_DEBUG_ENABLED
5432 }
5433 }
5434 sinfo->filled |= STATION_INFO_TX_BITRATE;
5435
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005436 sinfo->tx_packets =
5437 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5438 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5439 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5440 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5441
5442 sinfo->tx_retries =
5443 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
5444 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
5445 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
5446 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
5447
5448 sinfo->tx_failed =
5449 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
5450 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
5451 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
5452 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
5453
5454 sinfo->filled |=
5455 STATION_INFO_TX_PACKETS |
5456 STATION_INFO_TX_RETRIES |
5457 STATION_INFO_TX_FAILED;
5458
5459 EXIT();
5460 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005461}
5462
5463static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
5464 struct net_device *dev, bool mode, v_SINT_t timeout)
5465{
5466 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5467 VOS_STATUS vos_status;
5468
Jeff Johnsone7245742012-09-05 17:12:55 -07005469 ENTER();
5470
Jeff Johnson295189b2012-06-20 16:38:30 -07005471 if (NULL == pAdapter)
5472 {
5473 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5474 return -ENODEV;
5475 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005476 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5477 {
5478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5479 "%s:LOGP in Progress. Ignore!!!", __func__);
5480 return -EAGAIN;
5481 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005482
5483 /**The get power cmd from the supplicant gets updated by the nl only
5484 *on successful execution of the function call
5485 *we are oppositely mapped w.r.t mode in the driver
5486 **/
5487 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
5488
Jeff Johnsone7245742012-09-05 17:12:55 -07005489 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005490 if (VOS_STATUS_E_FAILURE == vos_status)
5491 {
5492 return -EINVAL;
5493 }
5494 return 0;
5495}
5496
5497
5498#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5499static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
5500 struct net_device *netdev,
5501 u8 key_index)
5502{
Jeff Johnsone7245742012-09-05 17:12:55 -07005503 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005504 return 0;
5505}
5506#endif //LINUX_VERSION_CODE
5507
5508#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5509static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5510 struct net_device *dev,
5511 struct ieee80211_txq_params *params)
5512{
Jeff Johnsone7245742012-09-05 17:12:55 -07005513 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005514 return 0;
5515}
5516#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5517static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5518 struct ieee80211_txq_params *params)
5519{
Jeff Johnsone7245742012-09-05 17:12:55 -07005520 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005521 return 0;
5522}
5523#endif //LINUX_VERSION_CODE
5524
5525static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
5526 struct net_device *dev, u8 *mac)
5527{
5528 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5529
Jeff Johnsone7245742012-09-05 17:12:55 -07005530 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005531 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5532 {
5533 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5534 return -EINVAL;
5535 }
5536
5537 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5538 {
5539 hddLog( LOGE,
5540 "%s: Wlan Load/Unload is in progress", __func__);
5541 return -EBUSY;
5542 }
5543
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005544 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5545 {
5546 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5547 "%s:LOGP in Progress. Ignore!!!", __func__);
5548 return -EAGAIN;
5549 }
5550
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
5552#ifdef WLAN_FEATURE_P2P
5553 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5554#endif
5555 )
5556 {
5557 if( NULL == mac )
5558 {
5559 v_U16_t i;
5560 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
5561 {
5562 if(pAdapter->aStaInfo[i].isUsed)
5563 {
5564 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
5565 hddLog(VOS_TRACE_LEVEL_INFO,
5566 "%s: Delete STA with MAC::"
5567 "%02x:%02x:%02x:%02x:%02x:%02x",
5568 __func__,
5569 macAddr[0], macAddr[1], macAddr[2],
5570 macAddr[3], macAddr[4], macAddr[5]);
5571 hdd_softap_sta_deauth(pAdapter, macAddr);
5572 }
5573 }
5574 }
5575 else
5576 {
5577 hddLog(VOS_TRACE_LEVEL_INFO,
5578 "%s: Delete STA with MAC::"
5579 "%02x:%02x:%02x:%02x:%02x:%02x",
5580 __func__,
5581 mac[0], mac[1], mac[2],
5582 mac[3], mac[4], mac[5]);
5583 hdd_softap_sta_deauth(pAdapter, mac);
5584 }
5585 }
5586
5587 EXIT();
5588
5589 return 0;
5590}
5591
5592static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
5593 struct net_device *dev, u8 *mac, struct station_parameters *params)
5594{
5595 // TODO: Implement this later.
Jeff Johnsone7245742012-09-05 17:12:55 -07005596 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005597 return 0;
5598}
5599
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005600
5601#ifdef FEATURE_WLAN_LFR
5602static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005603 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005604{
5605#define MAX_PMKSAIDS_IN_CACHE 8
5606 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
5607 static tANI_U32 i = 0; // HDD Local Cache index
5608 tANI_U32 j=0;
5609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5610 tHalHandle halHandle;
5611 eHalStatus result;
5612 tANI_U8 BSSIDMatched = 0;
5613
Jeff Johnsone7245742012-09-05 17:12:55 -07005614 ENTER();
5615
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005616 // Validate pAdapter
5617 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5618 {
5619 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5620 return -EINVAL;
5621 }
5622
5623 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5624 {
5625 hddLog( LOGE,
5626 "%s: Wlan Load/Unload is in progress", __func__);
5627 return -EBUSY;
5628 }
5629
5630 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5631 {
5632 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5633 "%s:LOGP in Progress. Ignore!!!", __func__);
5634 return -EAGAIN;
5635 }
5636
5637 // Retrieve halHandle
5638 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
5639
5640 for (j = 0; j < i; j++)
5641 {
5642 if(vos_mem_compare(PMKIDCache[j].BSSID,
5643 pmksa->bssid, WNI_CFG_BSSID_LEN))
5644 {
5645 /* BSSID matched previous entry. Overwrite it. */
5646 BSSIDMatched = 1;
5647 vos_mem_copy(PMKIDCache[j].BSSID,
5648 pmksa->bssid, WNI_CFG_BSSID_LEN);
5649 vos_mem_copy(PMKIDCache[j].PMKID,
5650 pmksa->pmkid,
5651 CSR_RSN_PMKID_SIZE);
5652 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
5653 __FUNCTION__, j );
5654 dump_bssid(pmksa->bssid);
5655 dump_pmkid(halHandle, pmksa->pmkid);
5656 break;
5657 }
5658 }
5659
5660 if (!BSSIDMatched)
5661 {
5662 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
5663 vos_mem_copy(PMKIDCache[i].BSSID,
5664 pmksa->bssid, ETHER_ADDR_LEN);
5665 vos_mem_copy(PMKIDCache[i].PMKID,
5666 pmksa->pmkid,
5667 CSR_RSN_PMKID_SIZE);
5668 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
5669 __FUNCTION__, i );
5670 dump_bssid(pmksa->bssid);
5671 dump_pmkid(halHandle, pmksa->pmkid);
5672 // Increment the HDD Local Cache index
5673 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
5674 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
5675 }
5676
5677
5678 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
5679 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
5680 // __FUNCTION__, i );
5681 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
5682 __FUNCTION__, i );
5683 // Finally set the PMKSA ID Cache in CSR
5684 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
5685 PMKIDCache,
5686 i );
5687 return 0;
5688}
5689
5690
5691static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07005692 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005693{
Jeff Johnsone7245742012-09-05 17:12:55 -07005694 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005695 // TODO: Implement this later.
5696 return 0;
5697}
5698
5699static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5700{
Jeff Johnsone7245742012-09-05 17:12:55 -07005701 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005702 // TODO: Implement this later.
5703 return 0;
5704}
5705#endif
5706
5707
Jeff Johnson295189b2012-06-20 16:38:30 -07005708/* cfg80211_ops */
5709static struct cfg80211_ops wlan_hdd_cfg80211_ops =
5710{
5711 .add_virtual_intf = wlan_hdd_add_virtual_intf,
5712 .del_virtual_intf = wlan_hdd_del_virtual_intf,
5713 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
5714 .change_station = wlan_hdd_change_station,
5715#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
5716 .add_beacon = wlan_hdd_cfg80211_add_beacon,
5717 .del_beacon = wlan_hdd_cfg80211_del_beacon,
5718 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005719#else
5720 .start_ap = wlan_hdd_cfg80211_start_ap,
5721 .change_beacon = wlan_hdd_cfg80211_change_beacon,
5722 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07005723#endif
5724 .change_bss = wlan_hdd_cfg80211_change_bss,
5725 .add_key = wlan_hdd_cfg80211_add_key,
5726 .get_key = wlan_hdd_cfg80211_get_key,
5727 .del_key = wlan_hdd_cfg80211_del_key,
5728 .set_default_key = wlan_hdd_cfg80211_set_default_key,
5729 .set_channel = wlan_hdd_cfg80211_set_channel,
5730 .scan = wlan_hdd_cfg80211_scan,
5731 .connect = wlan_hdd_cfg80211_connect,
5732 .disconnect = wlan_hdd_cfg80211_disconnect,
5733 .join_ibss = wlan_hdd_cfg80211_join_ibss,
5734 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
5735 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
5736 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
5737 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
5738#ifdef WLAN_FEATURE_P2P
5739 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
5740 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
5741 .mgmt_tx = wlan_hdd_action,
5742#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5743 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
5744 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
5745 .set_txq_params = wlan_hdd_set_txq_params,
5746#endif
5747#endif
5748 .get_station = wlan_hdd_cfg80211_get_station,
5749 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
5750 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005751 .add_station = wlan_hdd_cfg80211_add_station,
5752#ifdef FEATURE_WLAN_LFR
5753 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
5754 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
5755 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
5756#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005757};
5758
5759#endif // CONFIG_CFG80211