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