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