blob: 44d72bcba4eb23ec77e7186fc7d84ac31b88216f [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 */
1242static VOS_STATUS wlan_hdd_select_cbmode(hdd_adapter_t *pAdapter,tsap_Config_t *pSapConfig )
1243{
1244 tSmeConfigParams smeConfig;
1245 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter->pHddCtx;
1246 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter->pHddCtx))->cfg_ini;
1247 v_U8_t channel;
1248
1249 if(
1250#ifdef WLAN_FEATURE_11AC
1251 pSapConfig->SapHw_mode != eSAP_DOT11_MODE_11ac &&
1252 pSapConfig->SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
1253#endif
1254 pSapConfig->SapHw_mode != eSAP_DOT11_MODE_11n &&
1255 pSapConfig->SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
1256 )
1257 {
1258 return VOS_STATUS_SUCCESS;
1259 }
1260
1261 if (!pConfigIni->nChannelBondingMode5GHz) {
1262 return VOS_STATUS_SUCCESS;
1263 }
1264
1265 channel = pSapConfig->channel;
1266 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1267
1268 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1269
1270#ifdef WLAN_FEATURE_11AC
1271
1272 if ( pSapConfig->SapHw_mode == eSAP_DOT11_MODE_11ac ||
1273 pSapConfig->SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
1274 {
1275 if ( channel== 36 || channel == 52 || channel == 100 ||
1276 channel == 116 || channel == 149 )
1277 {
1278 smeConfig.csrConfig.channelBondingMode5GHz =
1279 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1280 }
1281 else if ( channel == 40 || channel == 56 || channel == 104 ||
1282 channel == 120 || channel == 153 )
1283 {
1284 smeConfig.csrConfig.channelBondingMode5GHz =
1285 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1286 }
1287 else if ( channel == 44 || channel == 60 || channel == 108 ||
1288 channel == 124 || channel == 157 )
1289 {
1290 smeConfig.csrConfig.channelBondingMode5GHz =
1291 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1292 }
1293 else if ( channel == 48 || channel == 64 || channel == 112 ||
1294 channel == 128 || channel == 161 )
1295 {
1296 smeConfig.csrConfig.channelBondingMode5GHz =
1297 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1298 }
1299 else
1300 {
1301 smeConfig.csrConfig.channelBondingMode5GHz=0;
1302 }
1303 }
1304#endif
1305 if ( pSapConfig->SapHw_mode == eSAP_DOT11_MODE_11n ||
1306 pSapConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
1307 {
1308 if ( channel== 40 || channel == 48 || channel == 56 ||
1309 channel == 64 || channel == 104 || channel == 112 ||
1310 channel == 120 || channel == 128 || channel == 136 ||
1311 channel == 144 || channel == 153 || channel == 161 )
1312 {
1313 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1314 }
1315 else if ( channel== 36 || channel == 44 || channel == 52 ||
1316 channel == 60 || channel == 100 || channel == 108 ||
1317 channel == 116 || channel == 124 || channel == 132 ||
1318 channel == 140 || channel == 149 || channel == 157 )
1319 {
1320 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1321 }
1322 else
1323 {
1324 smeConfig.csrConfig.channelBondingMode5GHz=0;
1325 }
1326 }
1327 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1328
1329 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1330 return VOS_STATUS_SUCCESS;
1331}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001332
Jeff Johnson295189b2012-06-20 16:38:30 -07001333#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1334static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1335 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001336#else
1337static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1338 struct cfg80211_beacon_data *params,
1339 const u8 *ssid, size_t ssid_len,
1340 enum nl80211_hidden_ssid hidden_ssid)
1341#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001342{
1343 tsap_Config_t *pConfig;
1344 beacon_data_t *pBeacon = NULL;
1345 struct ieee80211_mgmt *pMgmt_frame;
1346 v_U8_t *pIe=NULL;
1347 v_U16_t capab_info;
1348 eCsrAuthType RSNAuthType;
1349 eCsrEncryptionType RSNEncryptType;
1350 eCsrEncryptionType mcRSNEncryptType;
1351 int status = VOS_STATUS_SUCCESS;
1352 tpWLAN_SAPEventCB pSapEventCallback;
1353 hdd_hostapd_state_t *pHostapdState;
1354 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1355 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1356 struct qc_mac_acl_entry *acl_entry = NULL;
1357 v_SINT_t i;
1358
1359 ENTER();
1360
1361 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1362
1363 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1364
1365 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1366
1367 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1368
1369 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1370
1371 //channel is already set in the set_channel Call back
1372 //pConfig->channel = pCommitConfig->channel;
1373
1374 /*Protection parameter to enable or disable*/
1375 pConfig->protEnabled =
1376 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1377
1378 pConfig->dtim_period = pBeacon->dtim_period;
1379
1380 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1381 pConfig->dtim_period);
1382
1383
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001384 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001385 {
1386 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001387 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001388 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001389 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001390 tANI_BOOLEAN restartNeeded;
1391 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1392 pConfig->ieee80211d = 1;
1393 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1394 sme_setRegInfo(hHal, pConfig->countryCode);
1395 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1396 /*
1397 * If auto channel is configured i.e. channel is 0,
1398 * so skip channel validation.
1399 */
1400 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001401 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001402 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1403 {
1404 hddLog(VOS_TRACE_LEVEL_ERROR,
1405 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1406 return -EINVAL;
1407 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001408 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001409 /*
1410 * Validate the given channel range for the given country code
1411 */
1412 else
1413 {
1414 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
1415 WLANSAP_SetChannelRange(hHal,hdd_pConfig->apStartChannelNum,hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
1416 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001417 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001418 else
1419 {
1420 pConfig->ieee80211d = 0;
1421 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001422 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001423 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001424 {
1425 pConfig->ieee80211d = 0;
1426 }
1427 pConfig->authType = eSAP_AUTO_SWITCH;
1428
1429 capab_info = pMgmt_frame->u.beacon.capab_info;
1430
1431 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1432 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1433
1434 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1435
1436 /*Set wps station to configured*/
1437 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1438
1439 if(pIe)
1440 {
1441 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1442 {
1443 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1444 return -EINVAL;
1445 }
1446 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1447 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001448 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001449 /* Check 15 bit of WPS IE as it contain information for wps state
1450 * WPS state
1451 */
1452 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1453 {
1454 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1455 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1456 {
1457 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1458 }
1459 }
1460 }
1461 else
1462 {
1463 pConfig->wps_state = SAP_WPS_DISABLED;
1464 }
1465 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1466
1467 pConfig->RSNWPAReqIELength = 0;
1468 pConfig->pRSNWPAReqIE = NULL;
1469 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1470 WLAN_EID_RSN);
1471 if(pIe && pIe[1])
1472 {
1473 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1474 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1475 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1476 /* The actual processing may eventually be more extensive than
1477 * this. Right now, just consume any PMKIDs that are sent in
1478 * by the app.
1479 * */
1480 status = hdd_softap_unpackIE(
1481 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1482 &RSNEncryptType,
1483 &mcRSNEncryptType,
1484 &RSNAuthType,
1485 pConfig->pRSNWPAReqIE[1]+2,
1486 pConfig->pRSNWPAReqIE );
1487
1488 if( VOS_STATUS_SUCCESS == status )
1489 {
1490 /* Now copy over all the security attributes you have
1491 * parsed out
1492 * */
1493 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1494 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1495 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1496 = RSNEncryptType;
1497 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1498 "EncryptionType = %d mcEncryptionType = %d\n"),
1499 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1500 }
1501 }
1502
1503 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1504 pBeacon->tail, pBeacon->tail_len);
1505
1506 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1507 {
1508 if (pConfig->pRSNWPAReqIE)
1509 {
1510 /*Mixed mode WPA/WPA2*/
1511 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1512 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1513 }
1514 else
1515 {
1516 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1517 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1518 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1519 status = hdd_softap_unpackIE(
1520 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1521 &RSNEncryptType,
1522 &mcRSNEncryptType,
1523 &RSNAuthType,
1524 pConfig->pRSNWPAReqIE[1]+2,
1525 pConfig->pRSNWPAReqIE );
1526
1527 if( VOS_STATUS_SUCCESS == status )
1528 {
1529 /* Now copy over all the security attributes you have
1530 * parsed out
1531 * */
1532 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1533 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1534 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1535 = RSNEncryptType;
1536 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1537 "EncryptionType = %d mcEncryptionType = %d\n"),
1538 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1539 }
1540 }
1541 }
1542
1543 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1544
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001545#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001546 if (params->ssid != NULL)
1547 {
1548 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1549 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1550 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1551 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1552 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001553#else
1554 if (ssid != NULL)
1555 {
1556 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1557 pConfig->SSIDinfo.ssid.length = ssid_len;
1558 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1559 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1560 }
1561#endif
1562
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 vos_mem_copy(pConfig->self_macaddr.bytes,
1564 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1565
1566 /* default value */
1567 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1568 pConfig->num_accept_mac = 0;
1569 pConfig->num_deny_mac = 0;
1570
1571 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1572 pBeacon->tail, pBeacon->tail_len);
1573
1574 /* pIe for black list is following form:
1575 type : 1 byte
1576 length : 1 byte
1577 OUI : 4 bytes
1578 acl type : 1 byte
1579 no of mac addr in black list: 1 byte
1580 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1581 */
1582 if ((pIe != NULL) && (pIe[1] != 0))
1583 {
1584 pConfig->SapMacaddr_acl = pIe[6];
1585 pConfig->num_deny_mac = pIe[7];
1586 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1587 pIe[6], pIe[7]);
1588 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1589 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1590 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1591 for (i = 0; i < pConfig->num_deny_mac; i++)
1592 {
1593 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1594 acl_entry++;
1595 }
1596 }
1597 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1598 pBeacon->tail, pBeacon->tail_len);
1599
1600 /* pIe for white list is following form:
1601 type : 1 byte
1602 length : 1 byte
1603 OUI : 4 bytes
1604 acl type : 1 byte
1605 no of mac addr in white list: 1 byte
1606 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1607 */
1608 if ((pIe != NULL) && (pIe[1] != 0))
1609 {
1610 pConfig->SapMacaddr_acl = pIe[6];
1611 pConfig->num_accept_mac = pIe[7];
1612 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1613 pIe[6], pIe[7]);
1614 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1615 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1616 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1617 for (i = 0; i < pConfig->num_accept_mac; i++)
1618 {
1619 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1620 acl_entry++;
1621 }
1622 }
1623 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1624
Jeff Johnsone7245742012-09-05 17:12:55 -07001625#ifdef WLAN_FEATURE_11AC
1626 if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1627 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1628 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) )
1629 {
1630 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1631 }
1632#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301633
1634 wlan_hdd_select_cbmode(pHostapdAdapter,pConfig);
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;
3236 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3237 int freq = chan->center_freq; /* freq is in MHZ */
3238
3239 ENTER();
3240
3241 hddLog(VOS_TRACE_LEVEL_INFO,
3242 "%s: device_mode = %d freq = %d \n",__func__,
3243 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003244 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3245 {
3246 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3247 return -EAGAIN;
3248 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003249
3250 /*
3251 * Do freq to chan conversion
3252 * TODO: for 11a
3253 */
3254
3255 channel = ieee80211_frequency_to_channel(freq);
3256
3257 /* Check freq range */
3258 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3259 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3260 {
3261 hddLog(VOS_TRACE_LEVEL_ERROR,
3262 "%s: Channel [%d] is outside valid range from %d to %d\n",
3263 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3264 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3265 return -EINVAL;
3266 }
3267
3268 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3269
3270 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3271#ifdef WLAN_FEATURE_P2P
3272 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3273#endif
3274 )
3275 {
3276 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3277 {
3278 hddLog(VOS_TRACE_LEVEL_ERROR,
3279 "%s: Invalid Channel [%d] \n", __func__, channel);
3280 return -EINVAL;
3281 }
3282 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3283 "%s: set channel to [%d] for device mode =%d",
3284 __func__, channel,pAdapter->device_mode);
3285 }
3286 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3287#ifdef WLAN_FEATURE_P2P
3288 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3289#endif
3290 )
3291 {
3292 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3293 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3294 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3295
3296 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3297 {
3298 /* Link is up then return cant set channel*/
3299 hddLog( VOS_TRACE_LEVEL_ERROR,
3300 "%s: IBSS Associated, can't set the channel\n", __func__);
3301 return -EINVAL;
3302 }
3303
3304 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3305 pHddStaCtx->conn_info.operationChannel = channel;
3306 pRoamProfile->ChannelInfo.ChannelList =
3307 &pHddStaCtx->conn_info.operationChannel;
3308 }
3309 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3310#ifdef WLAN_FEATURE_P2P
3311 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3312#endif
3313 )
3314 {
3315 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3316
3317 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3318 {
3319 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3320
3321 /* If auto channel selection is configured as enable/ 1 then ignore
3322 channel set by supplicant
3323 */
3324 if ( cfg_param->apAutoChannelSelection )
3325 {
3326 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3327
3328 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3329 "%s: set channel to auto channel (0) for device mode =%d",
3330 __func__, pAdapter->device_mode);
3331 }
3332 }
3333 }
3334 else
3335 {
3336 hddLog(VOS_TRACE_LEVEL_FATAL,
3337 "%s: Invalid device mode failed to set valid channel", __func__);
3338 return -EINVAL;
3339 }
3340 EXIT();
3341 return 0;
3342}
3343
3344
3345
3346/*
3347 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3348 * This function is used to inform the BSS details to nl80211 interface.
3349 */
3350static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3351 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3352{
3353 struct net_device *dev = pAdapter->dev;
3354 struct wireless_dev *wdev = dev->ieee80211_ptr;
3355 struct wiphy *wiphy = wdev->wiphy;
3356 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3357 int chan_no;
3358 int ie_length;
3359 const char *ie;
3360 unsigned int freq;
3361 struct ieee80211_channel *chan;
3362 int rssi = 0;
3363 struct cfg80211_bss *bss = NULL;
3364
3365 ENTER();
3366
3367 if( NULL == pBssDesc )
3368 {
3369 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3370 return bss;
3371 }
3372
3373 chan_no = pBssDesc->channelId;
3374 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3375 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3376
3377 if( NULL == ie )
3378 {
3379 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3380 return bss;
3381 }
3382
3383#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3384 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3385 {
3386 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3387 }
3388 else
3389 {
3390 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3391 }
3392#else
3393 freq = ieee80211_channel_to_frequency(chan_no);
3394#endif
3395
3396 chan = __ieee80211_get_channel(wiphy, freq);
3397
3398 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3399 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3400 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3401 if (bss == NULL)
3402 {
3403 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3404
3405 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3406 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3407 pBssDesc->capabilityInfo,
3408 pBssDesc->beaconInterval, ie, ie_length,
3409 rssi, GFP_KERNEL ));
3410}
3411 else
3412 {
3413 return bss;
3414 }
3415}
3416
3417
3418
3419/*
3420 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3421 * This function is used to inform the BSS details to nl80211 interface.
3422 */
3423struct cfg80211_bss*
3424wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3425 tSirBssDescription *bss_desc
3426 )
3427{
3428 /*
3429 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3430 already exists in bss data base of cfg80211 for that particular BSS ID.
3431 Using cfg80211_inform_bss_frame to update the bss entry instead of
3432 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3433 now there is no possibility to get the mgmt(probe response) frame from PE,
3434 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3435 cfg80211_inform_bss_frame.
3436 */
3437 struct net_device *dev = pAdapter->dev;
3438 struct wireless_dev *wdev = dev->ieee80211_ptr;
3439 struct wiphy *wiphy = wdev->wiphy;
3440 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003441#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3442 qcom_ie_age *qie_age = NULL;
3443 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3444#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003445 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003446#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003447 const char *ie =
3448 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3449 unsigned int freq;
3450 struct ieee80211_channel *chan;
3451 struct ieee80211_mgmt *mgmt =
3452 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3453 struct cfg80211_bss *bss_status = NULL;
3454 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3455 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003456#ifdef WLAN_OPEN_SOURCE
3457 struct timespec ts;
3458#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003459
3460 ENTER();
3461
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003462 if (!mgmt)
3463 return NULL;
3464
Jeff Johnson295189b2012-06-20 16:38:30 -07003465 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003466
3467#ifdef WLAN_OPEN_SOURCE
3468 /* Android does not want the timestamp from the frame.
3469 Instead it wants a monotonic increasing value */
3470 get_monotonic_boottime(&ts);
3471 mgmt->u.probe_resp.timestamp =
3472 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3473#else
3474 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003475 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3476 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003477
3478#endif
3479
Jeff Johnson295189b2012-06-20 16:38:30 -07003480 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3481 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003482
3483#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3484 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3485 /* Assuming this is the last IE, copy at the end */
3486 ie_length -=sizeof(qcom_ie_age);
3487 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3488 qie_age->element_id = QCOM_VENDOR_IE_ID;
3489 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3490 qie_age->oui_1 = QCOM_OUI1;
3491 qie_age->oui_2 = QCOM_OUI2;
3492 qie_age->oui_3 = QCOM_OUI3;
3493 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3494 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3495#endif
3496
Jeff Johnson295189b2012-06-20 16:38:30 -07003497 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3498
3499 mgmt->frame_control |=
3500 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3501
3502#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3503 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3504 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3505 {
3506 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3507 }
3508 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3509 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3510
3511 {
3512 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3513 }
3514 else
3515 {
3516 kfree(mgmt);
3517 return NULL;
3518 }
3519#else
3520 freq = ieee80211_channel_to_frequency(chan_no);
3521#endif
3522 chan = __ieee80211_get_channel(wiphy, freq);
3523
3524 /*To keep the rssi icon of the connected AP in the scan window
3525 *and the rssi icon of the wireless networks in sync
3526 * */
3527 if (( eConnectionState_Associated ==
3528 pAdapter->sessionCtx.station.conn_info.connState ) &&
3529 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3530 pAdapter->sessionCtx.station.conn_info.bssId,
3531 WNI_CFG_BSSID_LEN)))
3532 {
3533 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3534 rssi = (pAdapter->rssi * 100);
3535 }
3536 else
3537 {
3538 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3539 }
3540
3541 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3542 frame_len, rssi, GFP_KERNEL);
3543 kfree(mgmt);
3544 return bss_status;
3545}
3546
3547/*
3548 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3549 * This function is used to update the BSS data base of CFG8011
3550 */
3551struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3552 tCsrRoamInfo *pRoamInfo
3553 )
3554{
3555 tCsrRoamConnectedProfile roamProfile;
3556 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3557 struct cfg80211_bss *bss = NULL;
3558
3559 ENTER();
3560
3561 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3562 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3563
3564 if (NULL != roamProfile.pBssDesc)
3565 {
3566 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3567 &roamProfile);
3568
3569 if (NULL == bss)
3570 {
3571 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3572 __func__);
3573 }
3574
3575 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3576 }
3577 else
3578 {
3579 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3580 __func__);
3581 }
3582 return bss;
3583}
3584
3585/*
3586 * FUNCTION: wlan_hdd_cfg80211_update_bss
3587 */
3588static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3589 hdd_adapter_t *pAdapter
3590 )
3591{
3592 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3593 tCsrScanResultInfo *pScanResult;
3594 eHalStatus status = 0;
3595 tScanResultHandle pResult;
3596 struct cfg80211_bss *bss_status = NULL;
3597
3598 ENTER();
3599
3600 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3601 {
3602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3603 return -EAGAIN;
3604 }
3605
3606 /*
3607 * start getting scan results and populate cgf80211 BSS database
3608 */
3609 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3610
3611 /* no scan results */
3612 if (NULL == pResult)
3613 {
3614 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3615 return status;
3616 }
3617
3618 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3619
3620 while (pScanResult)
3621 {
3622 /*
3623 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3624 * entry already exists in bss data base of cfg80211 for that
3625 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3626 * bss entry instead of cfg80211_inform_bss, But this call expects
3627 * mgmt packet as input. As of now there is no possibility to get
3628 * the mgmt(probe response) frame from PE, converting bss_desc to
3629 * ieee80211_mgmt(probe response) and passing to c
3630 * fg80211_inform_bss_frame.
3631 * */
3632
3633 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3634 &pScanResult->BssDescriptor);
3635
3636
3637 if (NULL == bss_status)
3638 {
3639 hddLog(VOS_TRACE_LEVEL_INFO,
3640 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3641 }
3642 else
3643 {
3644 cfg80211_put_bss(bss_status);
3645 }
3646
3647 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3648 }
3649
3650 sme_ScanResultPurge(hHal, pResult);
3651
3652 return 0;
3653}
3654
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003655void
3656hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3657{
3658 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003659 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3660 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3661 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003662} /****** end hddPrintMacAddr() ******/
3663
3664void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003665hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003666{
3667 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003668 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3669 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3670 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3671 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003672} /****** end hddPrintPmkId() ******/
3673
3674//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3675//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3676
3677//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3678//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3679
3680#define dump_bssid(bssid) \
3681 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003682 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3683 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3684 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003685 }
3686
3687#define dump_pmkid(pMac, pmkid) \
3688 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003689 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3690 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3691 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003692 }
3693
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003694#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003695/*
3696 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3697 * This function is used to notify the supplicant of a new PMKSA candidate.
3698 */
3699int wlan_hdd_cfg80211_pmksa_candidate_notify(
3700 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3701 int index, bool preauth )
3702{
Jeff Johnsone7245742012-09-05 17:12:55 -07003703#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003704 struct net_device *dev = pAdapter->dev;
3705
3706 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003707 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003708
3709 if( NULL == pRoamInfo )
3710 {
3711 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3712 return -EINVAL;
3713 }
3714
3715 dump_bssid(pRoamInfo->bssid);
3716 cfg80211_pmksa_candidate_notify(dev, index,
3717 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003718#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003719 return 0;
3720}
3721#endif //FEATURE_WLAN_LFR
3722
Jeff Johnson295189b2012-06-20 16:38:30 -07003723/*
3724 * FUNCTION: hdd_cfg80211_scan_done_callback
3725 * scanning callback function, called after finishing scan
3726 *
3727 */
3728static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3729 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3730{
3731 struct net_device *dev = (struct net_device *) pContext;
3732 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3733 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003734 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3735 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003736 struct cfg80211_scan_request *req = NULL;
3737 int ret = 0;
3738
3739 ENTER();
3740
3741 hddLog(VOS_TRACE_LEVEL_INFO,
3742 "%s called with halHandle = %p, pContext = %p,"
3743 "scanID = %d, returned status = %d\n",
3744 __func__, halHandle, pContext, (int) scanId, (int) status);
3745
3746 //Block on scan req completion variable. Can't wait forever though.
3747 ret = wait_for_completion_interruptible_timeout(
3748 &pScanInfo->scan_req_completion_event,
3749 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3750 if (!ret)
3751 {
3752 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003753 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003754 }
3755
3756 if(pScanInfo->mScanPending != VOS_TRUE)
3757 {
3758 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003759 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003760 }
3761
3762 /* Check the scanId */
3763 if (pScanInfo->scanId != scanId)
3764 {
3765 hddLog(VOS_TRACE_LEVEL_INFO,
3766 "%s called with mismatched scanId pScanInfo->scanId = %d "
3767 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3768 (int) scanId);
3769 }
3770
Jeff Johnson295189b2012-06-20 16:38:30 -07003771 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3772 pAdapter);
3773
3774 if (0 > ret)
3775 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3776
3777
3778 /* If any client wait scan result through WEXT
3779 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003780 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003781 {
3782 /* The other scan request waiting for current scan finish
3783 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003784 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003785 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003786 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003787 }
3788 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003789 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 {
3791 struct net_device *dev = pAdapter->dev;
3792 union iwreq_data wrqu;
3793 int we_event;
3794 char *msg;
3795
3796 memset(&wrqu, '\0', sizeof(wrqu));
3797 we_event = SIOCGIWSCAN;
3798 msg = NULL;
3799 wireless_send_event(dev, we_event, &wrqu, msg);
3800 }
3801 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003802 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003803
3804 /* Get the Scan Req */
3805 req = pAdapter->request;
3806
3807 if (!req)
3808 {
3809 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003810 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003811 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003812 }
3813
3814 /*
3815 * setting up 0, just in case.
3816 */
3817 req->n_ssids = 0;
3818 req->n_channels = 0;
3819 req->ie = 0;
3820
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003822 /* Scan is no longer pending */
3823 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003824
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003825 /*
3826 * cfg80211_scan_done informing NL80211 about completion
3827 * of scanning
3828 */
3829 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003830 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003831
Jeff Johnsone7245742012-09-05 17:12:55 -07003832allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003833 /* release the wake lock at the end of the scan*/
3834 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003835
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003836 /* Acquire wakelock to handle the case where APP's tries to suspend
3837 * immediatly after the driver gets connect request(i.e after scan)
3838 * from supplicant, this result in app's is suspending and not able
3839 * to process the connect request to AP */
3840 hdd_allow_suspend_timeout(100);
3841
Jeff Johnson295189b2012-06-20 16:38:30 -07003842 EXIT();
3843 return 0;
3844}
3845
3846/*
3847 * FUNCTION: wlan_hdd_cfg80211_scan
3848 * this scan respond to scan trigger and update cfg80211 scan database
3849 * later, scan dump command can be used to recieve scan results
3850 */
3851int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, struct net_device *dev,
3852 struct cfg80211_scan_request *request)
3853{
3854 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
3855 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3856 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3857 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3858 tCsrScanRequest scanRequest;
3859 tANI_U8 *channelList = NULL, i;
3860 v_U32_t scanId = 0;
3861 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003862 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003863#ifdef WLAN_FEATURE_P2P
3864 v_U8_t* pP2pIe = NULL;
3865#endif
3866
3867 ENTER();
3868
3869 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3870 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003871
3872 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
3873 (eConnectionState_Connecting ==
3874 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
3875 {
3876 hddLog(VOS_TRACE_LEVEL_ERROR,
3877 "%s: Connection in progress: Scan request denied (EBUSY)", __func__);
3878 return -EBUSY;
3879 }
3880
Jeff Johnson295189b2012-06-20 16:38:30 -07003881#ifdef WLAN_BTAMP_FEATURE
3882 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003883 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07003884 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08003885 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003886 "%s: No scanning when AMP is on", __func__);
3887 return -EOPNOTSUPP;
3888 }
3889#endif
3890 //Scan on any other interface is not supported.
3891 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
3892 {
3893 hddLog(VOS_TRACE_LEVEL_ERROR,
3894 "%s: Not scanning on device_mode = %d",
3895 __func__, pAdapter->device_mode);
3896 return -EOPNOTSUPP;
3897 }
3898
3899 if (TRUE == pScanInfo->mScanPending)
3900 {
3901 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
3902 return -EBUSY;
3903 }
3904
3905 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3906 {
3907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3908 "%s:LOGP in Progress. Ignore!!!", __func__);
3909 return -EAGAIN;
3910 }
3911
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07003912 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
3913 {
3914 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3915 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
3916 return -EAGAIN;
3917 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07003918 //Don't Allow Scan and return busy if Remain On
3919 //Channel and action frame is pending
3920 //Otherwise Cancel Remain On Channel and allow Scan
3921 //If no action frame pending
3922 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
3923 {
3924 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
3925 return -EBUSY;
3926 }
3927
Jeff Johnson295189b2012-06-20 16:38:30 -07003928 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
3929 {
3930 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
3931 "%s: Aquire lock fail", __func__);
3932 return -EAGAIN;
3933 }
3934 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
3935 {
3936 hddLog(VOS_TRACE_LEVEL_WARN,
3937 "%s: MAX TM Level Scan not allowed", __func__);
3938 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3939 return -EBUSY;
3940 }
3941 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
3942
3943 vos_mem_zero( &scanRequest, sizeof(scanRequest));
3944
3945 if (NULL != request)
3946 {
3947 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
3948 (int)request->n_ssids);
3949
3950 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
3951 * Becasue of this, driver is assuming that this is not wildcard scan and so
3952 * is not aging out the scan results.
3953 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07003954 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07003955 {
3956 request->n_ssids = 0;
3957 }
3958
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003959 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07003960 {
3961 tCsrSSIDInfo *SsidInfo;
3962 int j;
3963 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
3964 /* Allocate num_ssid tCsrSSIDInfo structure */
3965 SsidInfo = scanRequest.SSIDs.SSIDList =
3966 ( tCsrSSIDInfo *)vos_mem_malloc(
3967 request->n_ssids*sizeof(tCsrSSIDInfo));
3968
3969 if(NULL == scanRequest.SSIDs.SSIDList)
3970 {
3971 hddLog(VOS_TRACE_LEVEL_ERROR,
3972 "memory alloc failed SSIDInfo buffer");
3973 return -ENOMEM;
3974 }
3975
3976 /* copy all the ssid's and their length */
3977 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
3978 {
3979 /* get the ssid length */
3980 SsidInfo->SSID.length = request->ssids[j].ssid_len;
3981 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
3982 SsidInfo->SSID.length);
3983 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
3984 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
3985 j, SsidInfo->SSID.ssId);
3986 }
3987 /* set the scan type to active */
3988 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3989 }
3990 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
3991 {
3992 /* set the scan type to active */
3993 scanRequest.scanType = eSIR_ACTIVE_SCAN;
3994 }
3995 else
3996 {
3997 /*Set the scan type to default type, in this case it is ACTIVE*/
3998 scanRequest.scanType = pScanInfo->scan_mode;
3999 }
4000 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4001 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4002 }
4003 else
4004 {
4005 /* set the scan type to active */
4006 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4007 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4008
4009 /* set min and max channel time to zero */
4010 scanRequest.minChnTime = 0;
4011 scanRequest.maxChnTime = 0;
4012 }
4013
4014 /* set BSSType to default type */
4015 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4016
4017 /*TODO: scan the requested channels only*/
4018
4019 /*Right now scanning all the channels */
4020 if( request )
4021 {
4022 if( request->n_channels )
4023 {
4024 channelList = vos_mem_malloc( request->n_channels );
4025 if( NULL == channelList )
4026 {
4027 status = -ENOMEM;
4028 goto free_mem;
4029 }
4030
4031 for( i = 0 ; i < request->n_channels ; i++ )
4032 channelList[i] = request->channels[i]->hw_value;
4033 }
4034
4035 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4036 scanRequest.ChannelInfo.ChannelList = channelList;
4037
4038 /* set requestType to full scan */
4039 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004040
4041 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4042 * search (Flush on both full scan and social scan but not on single
4043 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4044 */
4045
4046 /* Supplicant does single channel scan after 8-way handshake
4047 * and in that case driver shoudnt flush scan results. If
4048 * driver flushes the scan results here and unfortunately if
4049 * the AP doesnt respond to our probe req then association
4050 * fails which is not desired
4051 */
4052
4053 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4054 {
4055 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4056 pAdapter->sessionId );
4057 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004058
4059 if( request->ie_len )
4060 {
4061 /* save this for future association (join requires this) */
4062 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4063 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4064 pScanInfo->scanAddIE.length = request->ie_len;
4065
4066 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004067 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4068 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004069 )
4070 {
4071 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4072 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4073 }
4074
4075 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4076 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4077
4078#ifdef WLAN_FEATURE_P2P
4079 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4080 request->ie_len);
4081 if (pP2pIe != NULL)
4082 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004083#ifdef WLAN_FEATURE_P2P_DEBUG
4084 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4085 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4086 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4087 {
4088 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4089 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4090 "Go nego completed to Connection is started");
4091 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4092 "for 8way Handshake");
4093 }
4094 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4095 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4096 {
4097 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4098 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4099 "Disconnected state to Connection is started");
4100 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4101 "for 4way Handshake");
4102 }
4103#endif
4104
Jeff Johnsone7245742012-09-05 17:12:55 -07004105 /* no_cck will be set during p2p find to disable 11b rates */
4106 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004107 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004108 hddLog(VOS_TRACE_LEVEL_INFO,
4109 "%s: This is a P2P Search", __func__);
4110 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004111
Jeff Johnsone7245742012-09-05 17:12:55 -07004112 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4113 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004114 /* set requestType to P2P Discovery */
4115 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004116 }
4117
4118 /*
4119 Skip Dfs Channel in case of P2P Search
4120 if it is set in ini file
4121 */
4122 if(cfg_param->skipDfsChnlInP2pSearch)
4123 {
4124 scanRequest.skipDfsChnlInP2pSearch = 1;
4125 }
4126 else
4127 {
4128 scanRequest.skipDfsChnlInP2pSearch = 0;
4129 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004130
Jeff Johnson295189b2012-06-20 16:38:30 -07004131 }
4132 }
4133#endif
4134 }
4135 }
4136
4137 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4138
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004139 /* acquire the wakelock to avoid the apps suspend during the scan. To
4140 * address the following issues.
4141 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4142 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4143 * for long time, this result in apps running at full power for long time.
4144 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4145 * be stuck in full power because of resume BMPS
4146 */
4147 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004148
4149 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004150 pAdapter->sessionId, &scanRequest, &scanId,
4151 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004152
Jeff Johnson295189b2012-06-20 16:38:30 -07004153 if (eHAL_STATUS_SUCCESS != status)
4154 {
4155 hddLog(VOS_TRACE_LEVEL_ERROR,
4156 "%s: sme_ScanRequest returned error %d", __func__, status);
4157 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004158 if(eHAL_STATUS_RESOURCES == status)
4159 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004160 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 -07004161 status = -EBUSY;
4162 } else {
4163 status = -EIO;
4164 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004165 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004166 goto free_mem;
4167 }
4168
4169 pScanInfo->mScanPending = TRUE;
4170 pAdapter->request = request;
4171 pScanInfo->scanId = scanId;
4172
4173 complete(&pScanInfo->scan_req_completion_event);
4174
4175free_mem:
4176 if( scanRequest.SSIDs.SSIDList )
4177 {
4178 vos_mem_free(scanRequest.SSIDs.SSIDList);
4179 }
4180
4181 if( channelList )
4182 vos_mem_free( channelList );
4183
4184 EXIT();
4185
4186 return status;
4187}
4188
4189/*
4190 * FUNCTION: wlan_hdd_cfg80211_connect_start
4191 * This function is used to start the association process
4192 */
4193int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004194 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004195{
4196 int status = 0;
4197 hdd_wext_state_t *pWextState;
4198 v_U32_t roamId;
4199 tCsrRoamProfile *pRoamProfile;
4200 eMib_dot11DesiredBssType connectedBssType;
4201 eCsrAuthType RSNAuthType;
4202
4203 ENTER();
4204
4205 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4206
4207 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4208 {
4209 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4210 return -EINVAL;
4211 }
4212
4213 pRoamProfile = &pWextState->roamProfile;
4214
4215 if (pRoamProfile)
4216 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004217 int ret = 0;
4218 hdd_station_ctx_t *pHddStaCtx;
4219 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4220 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4221
4222 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4223 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4224 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004225 {
4226 /* Issue disconnect to CSR */
4227 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4228 if( eHAL_STATUS_SUCCESS ==
4229 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4230 pAdapter->sessionId,
4231 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4232 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004233 ret = wait_for_completion_interruptible_timeout(
4234 &pAdapter->disconnect_comp_var,
4235 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4236 if (0 == ret)
4237 {
4238 VOS_ASSERT(0);
4239 }
4240 }
4241 }
4242 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4243 {
4244 ret = wait_for_completion_interruptible_timeout(
4245 &pAdapter->disconnect_comp_var,
4246 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4247 if (0 == ret)
4248 {
4249 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 }
4251 }
4252
4253 if (HDD_WMM_USER_MODE_NO_QOS ==
4254 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4255 {
4256 /*QoS not enabled in cfg file*/
4257 pRoamProfile->uapsd_mask = 0;
4258 }
4259 else
4260 {
4261 /*QoS enabled, update uapsd mask from cfg file*/
4262 pRoamProfile->uapsd_mask =
4263 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4264 }
4265
4266 pRoamProfile->SSIDs.numOfSSIDs = 1;
4267 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4268 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4269 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4270 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4271 ssid, ssid_len);
4272
4273 if (bssid)
4274 {
4275 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4276 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4277 WNI_CFG_BSSID_LEN);
4278 /* Save BSSID in seperate variable as well, as RoamProfile
4279 BSSID is getting zeroed out in the association process. And in
4280 case of join failure we should send valid BSSID to supplicant
4281 */
4282 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4283 WNI_CFG_BSSID_LEN);
4284 }
4285
4286 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4287 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4288 {
4289 /*set gen ie*/
4290 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4291 /*set auth*/
4292 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4293 }
4294 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4295 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4296 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4297 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4298 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4299 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4300 )
4301 {
4302 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4303 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4304 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4305 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4306 eCSR_AUTH_TYPE_AUTOSWITCH;
4307 pWextState->roamProfile.AuthType.authType[0] =
4308 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4309 }
4310#ifdef FEATURE_WLAN_WAPI
4311 if (pAdapter->wapi_info.nWapiMode)
4312 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004313 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004314 switch (pAdapter->wapi_info.wapiAuthMode)
4315 {
4316 case WAPI_AUTH_MODE_PSK:
4317 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004318 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004319 pAdapter->wapi_info.wapiAuthMode);
4320 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4321 break;
4322 }
4323 case WAPI_AUTH_MODE_CERT:
4324 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004325 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004326 pAdapter->wapi_info.wapiAuthMode);
4327 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4328 break;
4329 }
4330 } // End of switch
4331 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4332 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4333 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004334 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004335 pRoamProfile->AuthType.numEntries = 1;
4336 pRoamProfile->EncryptionType.numEntries = 1;
4337 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4338 pRoamProfile->mcEncryptionType.numEntries = 1;
4339 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4340 }
4341 }
4342#endif /* FEATURE_WLAN_WAPI */
4343 pRoamProfile->csrPersona = pAdapter->device_mode;
4344
Jeff Johnson32d95a32012-09-10 13:15:23 -07004345 if( operatingChannel )
4346 {
4347 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4348 pRoamProfile->ChannelInfo.numOfChannels = 1;
4349 }
4350
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4352 pAdapter->sessionId, pRoamProfile, &roamId);
4353
Jeff Johnson32d95a32012-09-10 13:15:23 -07004354 pRoamProfile->ChannelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004355 pRoamProfile->ChannelInfo.numOfChannels = 0;
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304356
4357 if( (eHAL_STATUS_SUCCESS == status) &&
4358 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4359
4360 {
4361 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4362 eConnectionState_Connecting);
4363 }
4364
4365 if( status != eHAL_STATUS_SUCCESS )
4366 {
4367 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect failed with "
4368 "status %d", __func__, status);
4369 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 }
4371 else
4372 {
4373 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4374 return -EINVAL;
4375 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004376 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004377 return status;
4378}
4379
4380/*
4381 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4382 * This function is used to set the authentication type (OPEN/SHARED).
4383 *
4384 */
4385static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4386 enum nl80211_auth_type auth_type)
4387{
4388 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4389 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4390
4391 ENTER();
4392
4393 /*set authentication type*/
4394 switch (auth_type)
4395 {
4396 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4397 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004398#ifdef WLAN_FEATURE_VOWIFI_11R
4399 case NL80211_AUTHTYPE_FT:
4400#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004401 hddLog(VOS_TRACE_LEVEL_INFO,
4402 "%s: set authentication type to OPEN", __func__);
4403 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4404 break;
4405
4406 case NL80211_AUTHTYPE_SHARED_KEY:
4407 hddLog(VOS_TRACE_LEVEL_INFO,
4408 "%s: set authentication type to SHARED", __func__);
4409 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4410 break;
4411#ifdef FEATURE_WLAN_CCX
4412 case NL80211_AUTHTYPE_NETWORK_EAP:
4413 hddLog(VOS_TRACE_LEVEL_INFO,
4414 "%s: set authentication type to CCKM WPA", __func__);
4415 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4416 break;
4417#endif
4418
4419
4420 default:
4421 hddLog(VOS_TRACE_LEVEL_ERROR,
4422 "%s: Unsupported authentication type %d", __func__,
4423 auth_type);
4424 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4425 return -EINVAL;
4426 }
4427
4428 pWextState->roamProfile.AuthType.authType[0] =
4429 pHddStaCtx->conn_info.authType;
4430 return 0;
4431}
4432
4433/*
4434 * FUNCTION: wlan_hdd_set_akm_suite
4435 * This function is used to set the key mgmt type(PSK/8021x).
4436 *
4437 */
4438static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4439 u32 key_mgmt
4440 )
4441{
4442 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4443 ENTER();
4444
4445 /*set key mgmt type*/
4446 switch(key_mgmt)
4447 {
4448 case WLAN_AKM_SUITE_PSK:
4449 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4450 __func__);
4451 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4452 break;
4453
4454 case WLAN_AKM_SUITE_8021X:
4455 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4456 __func__);
4457 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4458 break;
4459#ifdef FEATURE_WLAN_CCX
4460#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4461#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4462 case WLAN_AKM_SUITE_CCKM:
4463 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4464 __func__);
4465 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4466 break;
4467#endif
4468
4469 default:
4470 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4471 __func__, key_mgmt);
4472 return -EINVAL;
4473
4474 }
4475 return 0;
4476}
4477
4478/*
4479 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4480 * This function is used to set the encryption type
4481 * (NONE/WEP40/WEP104/TKIP/CCMP).
4482 */
4483static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4484 u32 cipher,
4485 bool ucast
4486 )
4487{
4488 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4489 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4490 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4491
4492 ENTER();
4493
4494 if (!cipher)
4495 {
4496 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4497 __func__, cipher);
4498 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4499 }
4500 else
4501 {
4502
4503 /*set encryption method*/
4504 switch (cipher)
4505 {
4506 case IW_AUTH_CIPHER_NONE:
4507 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4508 break;
4509
4510 case WLAN_CIPHER_SUITE_WEP40:
4511 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4512 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4513 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4514 else
4515 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4516 break;
4517
4518 case WLAN_CIPHER_SUITE_WEP104:
4519 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4520 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4521 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4522 else
4523 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4524 break;
4525
4526 case WLAN_CIPHER_SUITE_TKIP:
4527 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4528 break;
4529
4530 case WLAN_CIPHER_SUITE_CCMP:
4531 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4532 break;
4533#ifdef FEATURE_WLAN_WAPI
4534 case WLAN_CIPHER_SUITE_SMS4:
4535 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4536 break;
4537#endif
4538
4539#ifdef FEATURE_WLAN_CCX
4540 case WLAN_CIPHER_SUITE_KRK:
4541 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4542 break;
4543#endif
4544 default:
4545 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4546 __func__, cipher);
4547 return -EOPNOTSUPP;
4548 }
4549 }
4550
4551 if (ucast)
4552 {
4553 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4554 __func__, encryptionType);
4555 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4556 pWextState->roamProfile.EncryptionType.numEntries = 1;
4557 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4558 encryptionType;
4559 }
4560 else
4561 {
4562 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4563 __func__, encryptionType);
4564 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4565 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4566 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4567 }
4568
4569 return 0;
4570}
4571
4572
4573/*
4574 * FUNCTION: wlan_hdd_cfg80211_set_ie
4575 * This function is used to parse WPA/RSN IE's.
4576 */
4577int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4578 u8 *ie,
4579 size_t ie_len
4580 )
4581{
4582 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4583 u8 *genie = ie;
4584 v_U16_t remLen = ie_len;
4585#ifdef FEATURE_WLAN_WAPI
4586 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4587 u16 *tmp;
4588 v_U16_t akmsuiteCount;
4589 int *akmlist;
4590#endif
4591 ENTER();
4592
4593 /* clear previous assocAddIE */
4594 pWextState->assocAddIE.length = 0;
4595 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4596
4597 while (remLen >= 2)
4598 {
4599 v_U16_t eLen = 0;
4600 v_U8_t elementId;
4601 elementId = *genie++;
4602 eLen = *genie++;
4603 remLen -= 2;
4604
4605 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4606 __func__, elementId, eLen);
4607
4608 switch ( elementId )
4609 {
4610 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004611 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 -07004612 {
4613 hddLog(VOS_TRACE_LEVEL_ERROR,
4614 "%s: Invalid WPA IE", __func__);
4615 return -EINVAL;
4616 }
4617 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4618 {
4619 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4620 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4621 __func__, eLen + 2);
4622
4623 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4624 {
4625 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE. "
4626 "Need bigger buffer space\n");
4627 VOS_ASSERT(0);
4628 return -ENOMEM;
4629 }
4630 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4631 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4632 pWextState->assocAddIE.length += eLen + 2;
4633
4634 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4635 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4636 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4637 }
4638 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4639 {
4640 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4641 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4642 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4643 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4644 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4645 }
4646#ifdef WLAN_FEATURE_P2P
4647 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4648 P2P_OUI_TYPE_SIZE))
4649 /*Consider P2P IE, only for P2P Client */
4650 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4651 {
4652 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4653 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4654 __func__, eLen + 2);
4655
4656 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4657 {
4658 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4659 "Need bigger buffer space\n");
4660 VOS_ASSERT(0);
4661 return -ENOMEM;
4662 }
4663 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4664 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4665 pWextState->assocAddIE.length += eLen + 2;
4666
4667 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4668 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4669 }
4670#endif
4671#ifdef WLAN_FEATURE_WFD
4672 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4673 WFD_OUI_TYPE_SIZE))
4674 /*Consider WFD IE, only for P2P Client */
4675 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4676 {
4677 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4678 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4679 __func__, eLen + 2);
4680
4681 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4682 {
4683 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4684 "Need bigger buffer space\n");
4685 VOS_ASSERT(0);
4686 return -ENOMEM;
4687 }
4688 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4689 // WPS IE + P2P IE + WFD IE
4690 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4691 pWextState->assocAddIE.length += eLen + 2;
4692
4693 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4694 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4695 }
4696#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004697 /* Appending HS 2.0 Indication Element in Assiciation Request */
4698 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004699 HS20_OUI_TYPE_SIZE)) )
4700 {
4701 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4702 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4703 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004704
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004705 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4706 {
4707 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4708 "Need bigger buffer space\n");
4709 VOS_ASSERT(0);
4710 return -ENOMEM;
4711 }
4712 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4713 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004714
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004715 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4716 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4717 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004718
Jeff Johnson295189b2012-06-20 16:38:30 -07004719 break;
4720 case DOT11F_EID_RSN:
4721 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4722 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4723 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4724 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4725 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4726 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004727 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4728 case DOT11F_EID_EXTCAP:
4729 {
4730 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4731 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4732 __func__, eLen + 2);
4733
4734 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4735 {
4736 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accomadate assocAddIE "
4737 "Need bigger buffer space\n");
4738 VOS_ASSERT(0);
4739 return -ENOMEM;
4740 }
4741 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4742 pWextState->assocAddIE.length += eLen + 2;
4743
4744 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4745 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4746 break;
4747 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004748#ifdef FEATURE_WLAN_WAPI
4749 case WLAN_EID_WAPI:
4750 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4751 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4752 pAdapter->wapi_info.nWapiMode);
4753 tmp = (u16 *)ie;
4754 tmp = tmp + 2; // Skip element Id and Len, Version
4755 akmsuiteCount = WPA_GET_LE16(tmp);
4756 tmp = tmp + 1;
4757 akmlist = (int *)(tmp);
4758 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4759 {
4760 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4761 }
4762 else
4763 {
4764 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4765 VOS_ASSERT(0);
4766 return -EINVAL;
4767 }
4768
4769 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4770 {
4771 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004772 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004773 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4774 }
4775 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4776 {
4777 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004778 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004779 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4780 }
4781 break;
4782#endif
4783 default:
4784 hddLog (VOS_TRACE_LEVEL_ERROR,
4785 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004786 /* when Unknown IE is received we should break and continue
4787 * to the next IE in the buffer instead we were returning
4788 * so changing this to break */
4789 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004790 }
4791 genie += eLen;
4792 remLen -= eLen;
4793 }
4794 EXIT();
4795 return 0;
4796}
4797
4798/*
4799 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4800 * This function is used to initialize the security
4801 * parameters during connect operation.
4802 */
4803int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
4804 struct cfg80211_connect_params *req
4805 )
4806{
4807 int status = 0;
4808 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4809 ENTER();
4810
4811 /*set wpa version*/
4812 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
4813
4814 if (req->crypto.wpa_versions)
4815 {
4816 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
4817 && ( (req->ie_len)
4818 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
4819 // Make sure that it is including a WPA IE.
4820 /* Currently NL is putting WPA version 1 even for open,
4821 * since p2p ie is also put in same buffer.
4822 * */
4823 {
4824 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
4825 }
4826 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
4827 {
4828 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
4829 }
4830 }
4831
4832 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
4833 pWextState->wpaVersion);
4834
4835 /*set authentication type*/
4836 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
4837
4838 if (0 > status)
4839 {
4840 hddLog(VOS_TRACE_LEVEL_ERROR,
4841 "%s: failed to set authentication type ", __func__);
4842 return status;
4843 }
4844
4845 /*set key mgmt type*/
4846 if (req->crypto.n_akm_suites)
4847 {
4848 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
4849 if (0 > status)
4850 {
4851 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
4852 __func__);
4853 return status;
4854 }
4855 }
4856
4857 /*set pairwise cipher type*/
4858 if (req->crypto.n_ciphers_pairwise)
4859 {
4860 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
4861 req->crypto.ciphers_pairwise[0], true);
4862 if (0 > status)
4863 {
4864 hddLog(VOS_TRACE_LEVEL_ERROR,
4865 "%s: failed to set unicast cipher type", __func__);
4866 return status;
4867 }
4868 }
4869 else
4870 {
4871 /*Reset previous cipher suite to none*/
4872 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
4873 if (0 > status)
4874 {
4875 hddLog(VOS_TRACE_LEVEL_ERROR,
4876 "%s: failed to set unicast cipher type", __func__);
4877 return status;
4878 }
4879 }
4880
4881 /*set group cipher type*/
4882 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
4883 false);
4884
4885 if (0 > status)
4886 {
4887 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
4888 __func__);
4889 return status;
4890 }
4891
4892 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
4893 if (req->ie_len)
4894 {
4895 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
4896 if ( 0 > status)
4897 {
4898 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
4899 __func__);
4900 return status;
4901 }
4902 }
4903
4904 /*incase of WEP set default key information*/
4905 if (req->key && req->key_len)
4906 {
4907 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
4908 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
4909 )
4910 {
4911 if ( IW_AUTH_KEY_MGMT_802_1X
4912 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
4913 {
4914 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
4915 __func__);
4916 return -EOPNOTSUPP;
4917 }
4918 else
4919 {
4920 u8 key_len = req->key_len;
4921 u8 key_idx = req->key_idx;
4922
4923 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
4924 && (CSR_MAX_NUM_KEY > key_idx)
4925 )
4926 {
4927 hddLog(VOS_TRACE_LEVEL_INFO,
4928 "%s: setting default wep key, key_idx = %hu key_len %hu",
4929 __func__, key_idx, key_len);
4930 vos_mem_copy(
4931 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
4932 req->key, key_len);
4933 pWextState->roamProfile.Keys.KeyLength[key_idx] =
4934 (u8)key_len;
4935 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
4936 }
4937 }
4938 }
4939 }
4940
4941 return status;
4942}
4943
4944/*
4945 * FUNCTION: wlan_hdd_cfg80211_set_privacy
4946 * This function is used to initialize the security
4947 * parameters during connect operation.
4948 */
4949static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
4950 struct net_device *ndev,
4951 struct cfg80211_connect_params *req
4952 )
4953{
4954 int status = 0;
4955 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
4956 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
4957 hdd_context_t *pHddCtx = NULL;
4958
4959 ENTER();
4960
4961 hddLog(VOS_TRACE_LEVEL_INFO,
4962 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
4963
4964 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
4965 {
4966 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4967 "%s:LOGP in Progress. Ignore!!!", __func__);
4968 return -EAGAIN;
4969 }
4970
4971#ifdef WLAN_BTAMP_FEATURE
4972 //Infra connect not supported when AMP traffic is on.
4973 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
4974 {
4975 hddLog(VOS_TRACE_LEVEL_ERROR,
4976 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004977 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07004978 }
4979#endif
4980 /*initialise security parameters*/
4981 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
4982
4983 if ( 0 > status)
4984 {
4985 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
4986 __func__);
4987 return status;
4988 }
4989
4990 //If Device Mode is Station Concurrent Sessions Exit BMps
4991 //P2P Mode will be taken care in Open/close adaptor
4992 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4993 (vos_concurrent_sessions_running()))
4994 {
4995 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4996
4997 if (NULL != pVosContext)
4998 {
4999 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5000 if(NULL != pHddCtx)
5001 {
5002 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5003 }
5004 }
5005 }
5006
Mohit Khanna765234a2012-09-11 15:08:35 -07005007 if ( req->channel )
5008 {
5009 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5010 req->ssid_len, req->bssid,
5011 req->channel->hw_value);
5012 }
5013 else
5014 {
5015 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5016 req->ssid_len, req->bssid,
5017 0);
5018 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005019
5020 if (0 > status)
5021 {
5022 //ReEnable BMPS if disabled
5023 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5024 (NULL != pHddCtx))
5025 {
5026 //ReEnable Bmps and Imps back
5027 hdd_enable_bmps_imps(pHddCtx);
5028 }
5029
5030 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5031 return status;
5032 }
5033 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5034 EXIT();
5035 return status;
5036}
5037
5038
5039/*
5040 * FUNCTION: wlan_hdd_cfg80211_disconnect
5041 * This function is used to issue a disconnect request to SME
5042 */
5043static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5044 struct net_device *dev,
5045 u16 reason
5046 )
5047{
5048 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5049 tCsrRoamProfile *pRoamProfile =
5050 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5051 int status = 0;
5052 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5053
5054 ENTER();
5055
5056 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5057 __func__,pAdapter->device_mode);
5058
5059 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5060 __func__, reason);
5061
5062 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5063 {
5064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5065 "%s:LOGP in Progress. Ignore!!!",__func__);
5066 return -EAGAIN;
5067 }
5068 if (NULL != pRoamProfile)
5069 {
5070 /*issue disconnect request to SME, if station is in connected state*/
5071 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5072 {
5073 eCsrRoamDisconnectReason reasonCode =
5074 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5075 switch(reason)
5076 {
5077 case WLAN_REASON_MIC_FAILURE:
5078 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5079 break;
5080
5081 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5082 case WLAN_REASON_DISASSOC_AP_BUSY:
5083 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5084 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5085 break;
5086
5087 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5088 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5089 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5090 break;
5091
5092 case WLAN_REASON_DEAUTH_LEAVING:
5093 default:
5094 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5095 break;
5096 }
5097 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5098 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5099 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5100
5101 /*issue disconnect*/
5102 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5103 pAdapter->sessionId, reasonCode);
5104
5105 if ( 0 != status)
5106 {
5107 hddLog(VOS_TRACE_LEVEL_ERROR,
5108 "%s csrRoamDisconnect failure, returned %d \n",
5109 __func__, (int)status );
5110 return -EINVAL;
5111 }
5112
5113 wait_for_completion_interruptible_timeout(
5114 &pAdapter->disconnect_comp_var,
5115 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5116
5117
5118 /*stop tx queues*/
5119 netif_tx_disable(dev);
5120 netif_carrier_off(dev);
5121 }
5122 }
5123 else
5124 {
5125 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5126 }
5127
5128 return status;
5129}
5130
5131/*
5132 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5133 * This function is used to initialize the security
5134 * settings in IBSS mode.
5135 */
5136static int wlan_hdd_cfg80211_set_privacy_ibss(
5137 hdd_adapter_t *pAdapter,
5138 struct cfg80211_ibss_params *params
5139 )
5140{
5141 int status = 0;
5142 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5143 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5144 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5145
5146 ENTER();
5147
5148 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5149
5150 if (params->ie_len && ( NULL != params->ie) )
5151 {
5152 if (WLAN_EID_RSN == params->ie[0])
5153 {
5154 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5155 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5156 }
5157 else
5158 {
5159 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5160 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5161 }
5162 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5163
5164 if (0 > status)
5165 {
5166 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5167 __func__);
5168 return status;
5169 }
5170 }
5171
5172 pWextState->roamProfile.AuthType.authType[0] =
5173 pHddStaCtx->conn_info.authType =
5174 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5175
5176 if (params->privacy)
5177 {
5178 /* Security enabled IBSS, At this time there is no information available
5179 * about the security paramters, so initialise the encryption type to
5180 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5181 * The correct security parameters will be updated later in
5182 * wlan_hdd_cfg80211_add_key */
5183 /* Hal expects encryption type to be set inorder
5184 *enable privacy bit in beacons */
5185
5186 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5187 }
5188
5189 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5190 pWextState->roamProfile.EncryptionType.numEntries = 1;
5191 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5192
5193 return status;
5194}
5195
5196/*
5197 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5198 * This function is used to create/join an IBSS
5199 */
5200static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5201 struct net_device *dev,
5202 struct cfg80211_ibss_params *params
5203 )
5204{
5205 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5206 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5207 tCsrRoamProfile *pRoamProfile;
5208 int status;
5209 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5210
5211 ENTER();
5212
5213 hddLog(VOS_TRACE_LEVEL_INFO,
5214 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5215
5216 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5217 {
5218 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5219 "%s:LOGP in Progress. Ignore!!!", __func__);
5220 return -EAGAIN;
5221 }
5222
5223 if (NULL == pWextState)
5224 {
5225 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5226 __func__);
5227 return -EIO;
5228 }
5229
5230 pRoamProfile = &pWextState->roamProfile;
5231
5232 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5233 {
5234 hddLog (VOS_TRACE_LEVEL_ERROR,
5235 "%s Interface type is not set to IBSS \n", __func__);
5236 return -EINVAL;
5237 }
5238
5239 /* Set Channel */
5240 if (NULL != params->channel)
5241 {
5242 u8 channelNum;
5243 if (IEEE80211_BAND_5GHZ == params->channel->band)
5244 {
5245 hddLog(VOS_TRACE_LEVEL_ERROR,
5246 "%s: IBSS join is called with unsupported band %d",
5247 __func__, params->channel->band);
5248 return -EOPNOTSUPP;
5249 }
5250
5251 /* Get channel number */
5252 channelNum =
5253 ieee80211_frequency_to_channel(params->channel->center_freq);
5254
5255 /*TODO: use macro*/
5256 if (14 >= channelNum)
5257 {
5258 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5259 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5260 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5261 int indx;
5262
5263 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5264 validChan, &numChans))
5265 {
5266 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5267 __func__);
5268 return -EOPNOTSUPP;
5269 }
5270
5271 for (indx = 0; indx < numChans; indx++)
5272 {
5273 if (channelNum == validChan[indx])
5274 {
5275 break;
5276 }
5277 }
5278 if (indx >= numChans)
5279 {
5280 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5281 __func__, channelNum);
5282 return -EINVAL;
5283 }
5284 /* Set the Operational Channel */
5285 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5286 channelNum);
5287 pRoamProfile->ChannelInfo.numOfChannels = 1;
5288 pHddStaCtx->conn_info.operationChannel = channelNum;
5289 pRoamProfile->ChannelInfo.ChannelList =
5290 &pHddStaCtx->conn_info.operationChannel;
5291 }
5292 else
5293 {
5294 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5295 __func__, channelNum);
5296 return -EINVAL;
5297 }
5298 }
5299
5300 /* Initialize security parameters */
5301 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5302 if (status < 0)
5303 {
5304 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5305 __func__);
5306 return status;
5307 }
5308
5309 /* Issue connect start */
5310 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005311 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005312
5313 if (0 > status)
5314 {
5315 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5316 return status;
5317 }
5318
5319 return 0;
5320}
5321
5322/*
5323 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5324 * This function is used to leave an IBSS
5325 */
5326static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5327 struct net_device *dev
5328 )
5329{
5330 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5331 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5332 tCsrRoamProfile *pRoamProfile;
5333
5334 ENTER();
5335
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005336 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5337 {
5338 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5339 "%s:LOGP in Progress. Ignore!!!", __func__);
5340 return -EAGAIN;
5341 }
5342
Jeff Johnson295189b2012-06-20 16:38:30 -07005343 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5344 if (NULL == pWextState)
5345 {
5346 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5347 __func__);
5348 return -EIO;
5349 }
5350
5351 pRoamProfile = &pWextState->roamProfile;
5352
5353 /* Issue disconnect only if interface type is set to IBSS */
5354 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5355 {
5356 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5357 __func__);
5358 return -EINVAL;
5359 }
5360
5361 /* Issue Disconnect request */
5362 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5363 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5364 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5365
5366 return 0;
5367}
5368
5369/*
5370 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5371 * This function is used to set the phy parameters
5372 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5373 */
5374static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5375 u32 changed)
5376{
5377 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5378 tHalHandle hHal = pHddCtx->hHal;
5379
5380 ENTER();
5381
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005382 if ( pHddCtx->isLogpInProgress )
5383 {
5384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5385 "%s:LOGP in Progress. Ignore!!!", __func__);
5386 return -EAGAIN;
5387 }
5388
Jeff Johnson295189b2012-06-20 16:38:30 -07005389 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5390 {
5391 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5392 WNI_CFG_RTS_THRESHOLD_STAMAX :
5393 wiphy->rts_threshold;
5394
5395 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5396 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5397 {
5398 hddLog(VOS_TRACE_LEVEL_ERROR,
5399 "%s: Invalid RTS Threshold value %hu",
5400 __func__, rts_threshold);
5401 return -EINVAL;
5402 }
5403
5404 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5405 rts_threshold, ccmCfgSetCallback,
5406 eANI_BOOLEAN_TRUE))
5407 {
5408 hddLog(VOS_TRACE_LEVEL_ERROR,
5409 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5410 __func__, rts_threshold);
5411 return -EIO;
5412 }
5413
5414 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5415 rts_threshold);
5416 }
5417
5418 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5419 {
5420 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5421 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5422 wiphy->frag_threshold;
5423
5424 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5425 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5426 {
5427 hddLog(VOS_TRACE_LEVEL_ERROR,
5428 "%s: Invalid frag_threshold value %hu", __func__,
5429 frag_threshold);
5430 return -EINVAL;
5431 }
5432
5433 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5434 frag_threshold, ccmCfgSetCallback,
5435 eANI_BOOLEAN_TRUE))
5436 {
5437 hddLog(VOS_TRACE_LEVEL_ERROR,
5438 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5439 __func__, frag_threshold);
5440 return -EIO;
5441 }
5442
5443 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5444 frag_threshold);
5445 }
5446
5447 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5448 || (changed & WIPHY_PARAM_RETRY_LONG))
5449 {
5450 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5451 wiphy->retry_short :
5452 wiphy->retry_long;
5453
5454 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5455 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5456 {
5457 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5458 __func__, retry_value);
5459 return -EINVAL;
5460 }
5461
5462 if (changed & WIPHY_PARAM_RETRY_SHORT)
5463 {
5464 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5465 retry_value, ccmCfgSetCallback,
5466 eANI_BOOLEAN_TRUE))
5467 {
5468 hddLog(VOS_TRACE_LEVEL_ERROR,
5469 "%s: ccmCfgSetInt failed for long retry count %hu",
5470 __func__, retry_value);
5471 return -EIO;
5472 }
5473 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5474 __func__, retry_value);
5475 }
5476 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5477 {
5478 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5479 retry_value, ccmCfgSetCallback,
5480 eANI_BOOLEAN_TRUE))
5481 {
5482 hddLog(VOS_TRACE_LEVEL_ERROR,
5483 "%s: ccmCfgSetInt failed for short retry count %hu",
5484 __func__, retry_value);
5485 return -EIO;
5486 }
5487 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5488 __func__, retry_value);
5489 }
5490 }
5491
5492 return 0;
5493}
5494
5495/*
5496 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5497 * This function is used to set the txpower
5498 */
5499static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5500#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5501 enum tx_power_setting type,
5502#else
5503 enum nl80211_tx_power_setting type,
5504#endif
5505 int dbm)
5506{
5507 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5508 tHalHandle hHal = pHddCtx->hHal;
5509 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5510 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5511
5512 ENTER();
5513
5514 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5515 dbm, ccmCfgSetCallback,
5516 eANI_BOOLEAN_TRUE))
5517 {
5518 hddLog(VOS_TRACE_LEVEL_ERROR,
5519 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5520 return -EIO;
5521 }
5522
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005523 if ( pHddCtx->isLogpInProgress )
5524 {
5525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5526 "%s:LOGP in Progress. Ignore!!!", __func__);
5527 return -EAGAIN;
5528 }
5529
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5531 dbm);
5532
5533 switch(type)
5534 {
5535 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5536 /* Fall through */
5537 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5538 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5539 {
5540 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5541 __func__);
5542 return -EIO;
5543 }
5544 break;
5545 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5546 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5547 __func__);
5548 return -EOPNOTSUPP;
5549 break;
5550 default:
5551 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5552 __func__, type);
5553 return -EIO;
5554 }
5555
5556 return 0;
5557}
5558
5559/*
5560 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5561 * This function is used to read the txpower
5562 */
5563static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5564{
5565
5566 hdd_adapter_t *pAdapter;
5567 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5568
Jeff Johnsone7245742012-09-05 17:12:55 -07005569 ENTER();
5570
Jeff Johnson295189b2012-06-20 16:38:30 -07005571 if (NULL == pHddCtx)
5572 {
5573 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5574 *dbm = 0;
5575 return -ENOENT;
5576 }
5577
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005578 if ( pHddCtx->isLogpInProgress )
5579 {
5580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5581 "%s:LOGP in Progress. Ignore!!!", __func__);
5582 return -EAGAIN;
5583 }
5584
Jeff Johnson295189b2012-06-20 16:38:30 -07005585 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5586 if (NULL == pAdapter)
5587 {
5588 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5589 return -ENOENT;
5590 }
5591
5592 wlan_hdd_get_classAstats(pAdapter);
5593 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5594
Jeff Johnsone7245742012-09-05 17:12:55 -07005595 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005596 return 0;
5597}
5598
5599static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5600 u8* mac, struct station_info *sinfo)
5601{
5602 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5603 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5604 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5605 tANI_U8 rate_flags;
5606
5607 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5608 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5609 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5610
5611 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5612 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5613 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5614 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5615 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5616 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5617 tANI_U16 maxRate = 0;
5618 tANI_U16 myRate;
5619 tANI_U16 currentRate = 0;
5620 tANI_U8 maxSpeedMCS = 0;
5621 tANI_U8 maxMCSIdx = 0;
5622 tANI_U8 rateFlag = 1;
5623 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005624 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005625
Jeff Johnsone7245742012-09-05 17:12:55 -07005626 ENTER();
5627
Jeff Johnson295189b2012-06-20 16:38:30 -07005628 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5629 (0 == ssidlen))
5630 {
5631 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5632 " Invalid ssidlen, %d", __func__, ssidlen);
5633 /*To keep GUI happy*/
5634 return 0;
5635 }
5636
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005637 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5638 {
5639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5640 "%s:LOGP in Progress. Ignore!!!", __func__);
5641 return -EAGAIN;
5642 }
5643
Jeff Johnson295189b2012-06-20 16:38:30 -07005644 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5645 sinfo->filled |= STATION_INFO_SIGNAL;
5646
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005647 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005648 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5649
5650 //convert to the UI units of 100kbps
5651 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5652
5653#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005654 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 -07005655 sinfo->signal,
5656 pCfg->reportMaxLinkSpeed,
5657 myRate,
5658 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005659 (int) pCfg->linkSpeedRssiMid,
5660 (int) pCfg->linkSpeedRssiLow,
5661 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005662#endif //LINKSPEED_DEBUG_ENABLED
5663
5664 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5665 {
5666 // we do not want to necessarily report the current speed
5667 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5668 {
5669 // report the max possible speed
5670 rssidx = 0;
5671 }
5672 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5673 {
5674 // report the max possible speed with RSSI scaling
5675 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5676 {
5677 // report the max possible speed
5678 rssidx = 0;
5679 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005680 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005681 {
5682 // report middle speed
5683 rssidx = 1;
5684 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005685 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5686 {
5687 // report middle speed
5688 rssidx = 2;
5689 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005690 else
5691 {
5692 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005693 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005694 }
5695 }
5696 else
5697 {
5698 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5699 hddLog(VOS_TRACE_LEVEL_ERROR,
5700 "%s: Invalid value for reportMaxLinkSpeed: %u",
5701 __func__, pCfg->reportMaxLinkSpeed);
5702 rssidx = 0;
5703 }
5704
5705 maxRate = 0;
5706
5707 /* Get Basic Rate Set */
5708 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5709 for (i = 0; i < ORLeng; i++)
5710 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005711 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005712 {
5713 /* Validate Rate Set */
5714 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5715 {
5716 currentRate = supported_data_rate[j].supported_rate[rssidx];
5717 break;
5718 }
5719 }
5720 /* Update MAX rate */
5721 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5722 }
5723
5724 /* Get Extended Rate Set */
5725 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5726 for (i = 0; i < ERLeng; i++)
5727 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005728 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005729 {
5730 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5731 {
5732 currentRate = supported_data_rate[j].supported_rate[rssidx];
5733 break;
5734 }
5735 }
5736 /* Update MAX rate */
5737 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5738 }
5739
5740 /* Get MCS Rate Set -- but only if we are connected at MCS
5741 rates or if we are always reporting max speed or if we have
5742 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005743 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005744 {
5745 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5746 rateFlag = 0;
5747 if (rate_flags & eHAL_TX_RATE_HT40)
5748 {
5749 rateFlag |= 1;
5750 }
5751 if (rate_flags & eHAL_TX_RATE_SGI)
5752 {
5753 rateFlag |= 2;
5754 }
5755
5756 for (i = 0; i < MCSLeng; i++)
5757 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005758 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5759 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005760 {
5761 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5762 {
5763 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5764 break;
5765 }
5766 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005767 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005768 {
5769 maxRate = currentRate;
5770 maxSpeedMCS = 1;
5771 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5772 }
5773 }
5774 }
5775
5776 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005777 if (((maxRate < myRate) && (0 == rssidx)) ||
5778 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005779 {
5780 maxRate = myRate;
5781 if (rate_flags & eHAL_TX_RATE_LEGACY)
5782 {
5783 maxSpeedMCS = 0;
5784 }
5785 else
5786 {
5787 maxSpeedMCS = 1;
5788 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5789 }
5790 }
5791
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005792 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07005793 {
5794 sinfo->txrate.legacy = maxRate;
5795#ifdef LINKSPEED_DEBUG_ENABLED
5796 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
5797#endif //LINKSPEED_DEBUG_ENABLED
5798 }
5799 else
5800 {
5801 sinfo->txrate.mcs = maxMCSIdx;
5802 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5803 if (rate_flags & eHAL_TX_RATE_SGI)
5804 {
5805 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5806 }
5807 if (rate_flags & eHAL_TX_RATE_HT40)
5808 {
5809 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5810 }
5811#ifdef LINKSPEED_DEBUG_ENABLED
5812 pr_info("Reporting MCS rate %d flags %x\n",
5813 sinfo->txrate.mcs,
5814 sinfo->txrate.flags );
5815#endif //LINKSPEED_DEBUG_ENABLED
5816 }
5817 }
5818 else
5819 {
5820 // report current rate instead of max rate
5821
5822 if (rate_flags & eHAL_TX_RATE_LEGACY)
5823 {
5824 //provide to the UI in units of 100kbps
5825 sinfo->txrate.legacy = myRate;
5826#ifdef LINKSPEED_DEBUG_ENABLED
5827 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
5828#endif //LINKSPEED_DEBUG_ENABLED
5829 }
5830 else
5831 {
5832 //must be MCS
5833 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5834 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
5835 if (rate_flags & eHAL_TX_RATE_SGI)
5836 {
5837 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
5838 }
5839 if (rate_flags & eHAL_TX_RATE_HT40)
5840 {
5841 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
5842 }
5843#ifdef LINKSPEED_DEBUG_ENABLED
5844 pr_info("Reporting actual MCS rate %d flags %x\n",
5845 sinfo->txrate.mcs,
5846 sinfo->txrate.flags );
5847#endif //LINKSPEED_DEBUG_ENABLED
5848 }
5849 }
5850 sinfo->filled |= STATION_INFO_TX_BITRATE;
5851
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005852 sinfo->tx_packets =
5853 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
5854 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
5855 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
5856 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
5857
5858 sinfo->tx_retries =
5859 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
5860 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
5861 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
5862 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
5863
5864 sinfo->tx_failed =
5865 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
5866 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
5867 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
5868 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
5869
5870 sinfo->filled |=
5871 STATION_INFO_TX_PACKETS |
5872 STATION_INFO_TX_RETRIES |
5873 STATION_INFO_TX_FAILED;
5874
5875 EXIT();
5876 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005877}
5878
5879static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
5880 struct net_device *dev, bool mode, v_SINT_t timeout)
5881{
5882 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5883 VOS_STATUS vos_status;
5884
Jeff Johnsone7245742012-09-05 17:12:55 -07005885 ENTER();
5886
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 if (NULL == pAdapter)
5888 {
5889 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
5890 return -ENODEV;
5891 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005892 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5893 {
5894 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5895 "%s:LOGP in Progress. Ignore!!!", __func__);
5896 return -EAGAIN;
5897 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005898
5899 /**The get power cmd from the supplicant gets updated by the nl only
5900 *on successful execution of the function call
5901 *we are oppositely mapped w.r.t mode in the driver
5902 **/
5903 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
5904
Jeff Johnsone7245742012-09-05 17:12:55 -07005905 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 if (VOS_STATUS_E_FAILURE == vos_status)
5907 {
5908 return -EINVAL;
5909 }
5910 return 0;
5911}
5912
5913
5914#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5915static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
5916 struct net_device *netdev,
5917 u8 key_index)
5918{
Jeff Johnsone7245742012-09-05 17:12:55 -07005919 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005920 return 0;
5921}
5922#endif //LINUX_VERSION_CODE
5923
5924#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5925static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5926 struct net_device *dev,
5927 struct ieee80211_txq_params *params)
5928{
Jeff Johnsone7245742012-09-05 17:12:55 -07005929 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005930 return 0;
5931}
5932#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5933static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
5934 struct ieee80211_txq_params *params)
5935{
Jeff Johnsone7245742012-09-05 17:12:55 -07005936 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005937 return 0;
5938}
5939#endif //LINUX_VERSION_CODE
5940
5941static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
5942 struct net_device *dev, u8 *mac)
5943{
5944 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5945
Jeff Johnsone7245742012-09-05 17:12:55 -07005946 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
5948 {
5949 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
5950 return -EINVAL;
5951 }
5952
5953 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
5954 {
5955 hddLog( LOGE,
5956 "%s: Wlan Load/Unload is in progress", __func__);
5957 return -EBUSY;
5958 }
5959
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005960 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5961 {
5962 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5963 "%s:LOGP in Progress. Ignore!!!", __func__);
5964 return -EAGAIN;
5965 }
5966
Jeff Johnson295189b2012-06-20 16:38:30 -07005967 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
5968#ifdef WLAN_FEATURE_P2P
5969 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5970#endif
5971 )
5972 {
5973 if( NULL == mac )
5974 {
5975 v_U16_t i;
5976 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
5977 {
5978 if(pAdapter->aStaInfo[i].isUsed)
5979 {
5980 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
5981 hddLog(VOS_TRACE_LEVEL_INFO,
5982 "%s: Delete STA with MAC::"
5983 "%02x:%02x:%02x:%02x:%02x:%02x",
5984 __func__,
5985 macAddr[0], macAddr[1], macAddr[2],
5986 macAddr[3], macAddr[4], macAddr[5]);
5987 hdd_softap_sta_deauth(pAdapter, macAddr);
5988 }
5989 }
5990 }
5991 else
5992 {
5993 hddLog(VOS_TRACE_LEVEL_INFO,
5994 "%s: Delete STA with MAC::"
5995 "%02x:%02x:%02x:%02x:%02x:%02x",
5996 __func__,
5997 mac[0], mac[1], mac[2],
5998 mac[3], mac[4], mac[5]);
5999 hdd_softap_sta_deauth(pAdapter, mac);
6000 }
6001 }
6002
6003 EXIT();
6004
6005 return 0;
6006}
6007
6008static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6009 struct net_device *dev, u8 *mac, struct station_parameters *params)
6010{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006011#ifdef FEATURE_WLAN_TDLS
6012 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6013 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6014 u32 mask, set;
6015 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006016 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006017
6018 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6019 {
6020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6021 "Invalid arguments");
6022 return -EINVAL;
6023 }
6024
6025 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6026 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6027 {
6028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6029 "TDLS Disabled in INI OR not enabled in FW.\
6030 Cannot process TDLS commands \n");
6031 return -ENOTSUPP;
6032 }
6033
6034 mask = params->sta_flags_mask;
6035
6036 set = params->sta_flags_set;
6037
6038
6039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6040 "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
6041
6042 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6043 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6044 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6045 "Add TDLS peer");
6046
6047
6048 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6049 pAdapter->sessionId, mac);
6050
6051 if (VOS_STATUS_SUCCESS != status) {
6052 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6053 "%s: sme_AddTdlsPeerSta failed!", __func__);
6054 }
6055 }
6056 }
6057#endif
6058
Jeff Johnson295189b2012-06-20 16:38:30 -07006059 return 0;
6060}
6061
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006062
6063#ifdef FEATURE_WLAN_LFR
6064static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006065 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006066{
6067#define MAX_PMKSAIDS_IN_CACHE 8
6068 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006069 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006070 tANI_U32 j=0;
6071 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6072 tHalHandle halHandle;
6073 eHalStatus result;
6074 tANI_U8 BSSIDMatched = 0;
6075
Jeff Johnsone7245742012-09-05 17:12:55 -07006076 ENTER();
6077
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006078 // Validate pAdapter
6079 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6080 {
6081 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6082 return -EINVAL;
6083 }
6084
6085 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6086 {
6087 hddLog( LOGE,
6088 "%s: Wlan Load/Unload is in progress", __func__);
6089 return -EBUSY;
6090 }
6091
6092 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6093 {
6094 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6095 "%s:LOGP in Progress. Ignore!!!", __func__);
6096 return -EAGAIN;
6097 }
6098
6099 // Retrieve halHandle
6100 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6101
6102 for (j = 0; j < i; j++)
6103 {
6104 if(vos_mem_compare(PMKIDCache[j].BSSID,
6105 pmksa->bssid, WNI_CFG_BSSID_LEN))
6106 {
6107 /* BSSID matched previous entry. Overwrite it. */
6108 BSSIDMatched = 1;
6109 vos_mem_copy(PMKIDCache[j].BSSID,
6110 pmksa->bssid, WNI_CFG_BSSID_LEN);
6111 vos_mem_copy(PMKIDCache[j].PMKID,
6112 pmksa->pmkid,
6113 CSR_RSN_PMKID_SIZE);
6114 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006115 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006116 dump_bssid(pmksa->bssid);
6117 dump_pmkid(halHandle, pmksa->pmkid);
6118 break;
6119 }
6120 }
6121
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006122 /* Check we compared all entries,if then take the first slot now */
6123 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6124
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006125 if (!BSSIDMatched)
6126 {
6127 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6128 vos_mem_copy(PMKIDCache[i].BSSID,
6129 pmksa->bssid, ETHER_ADDR_LEN);
6130 vos_mem_copy(PMKIDCache[i].PMKID,
6131 pmksa->pmkid,
6132 CSR_RSN_PMKID_SIZE);
6133 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006134 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006135 dump_bssid(pmksa->bssid);
6136 dump_pmkid(halHandle, pmksa->pmkid);
6137 // Increment the HDD Local Cache index
6138 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6139 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6140 }
6141
6142
6143 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6144 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006145 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006146 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006147 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006148 // Finally set the PMKSA ID Cache in CSR
6149 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6150 PMKIDCache,
6151 i );
6152 return 0;
6153}
6154
6155
6156static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006157 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006158{
Jeff Johnsone7245742012-09-05 17:12:55 -07006159 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006160 // TODO: Implement this later.
6161 return 0;
6162}
6163
6164static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6165{
Jeff Johnsone7245742012-09-05 17:12:55 -07006166 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006167 // TODO: Implement this later.
6168 return 0;
6169}
6170#endif
6171
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006172#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6173static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6174 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6175{
6176 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6177 hdd_station_ctx_t *pHddStaCtx;
6178
6179 if (NULL == pAdapter)
6180 {
6181 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6182 return -ENODEV;
6183 }
6184
6185 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6186
6187 // Added for debug on reception of Re-assoc Req.
6188 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6189 {
6190 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6191 ftie->ie_len);
6192 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6193 }
6194
6195#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6196 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6197 ftie->ie_len);
6198#endif
6199
6200 // Pass the received FT IEs to SME
6201 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6202 ftie->ie_len);
6203 return 0;
6204}
6205#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006206
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006207#ifdef FEATURE_WLAN_TDLS
6208static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6209 u8 *peer, u8 action_code, u8 dialog_token,
6210 u16 status_code, const u8 *buf, size_t len)
6211{
6212
6213 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6214 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6215 u8 *buf_1;
6216 size_t len_1 = len;
6217 u8 peerMac[6];
6218 VOS_STATUS status;
6219
6220 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6221 {
6222 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6223 "Invalid arguments");
6224 return -EINVAL;
6225 }
6226
6227 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6228 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6229 {
6230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6231 "TDLS Disabled in INI OR not enabled in FW.\
6232 Cannot process TDLS commands \n");
6233 return -ENOTSUPP;
6234 }
6235 vos_mem_copy( peerMac, peer, 6);
6236
6237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6238 "Request to send TDLS management: action = %d, status = %d, \
6239 len = %d", action_code, status_code, len);
6240
6241 buf_1 = vos_mem_malloc(len);
6242 if(buf_1 == NULL) {
6243 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6244 "%s: malloc failed!", __func__);
6245 return -ENOMEM;
6246 }
6247 vos_mem_copy(buf_1, buf, len);
6248
6249 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6250 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6251
6252 if (VOS_STATUS_SUCCESS != status) {
6253 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6254 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6255 }
6256
6257 vos_mem_free(buf_1);
6258
6259 return 0;
6260}
6261
6262static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6263 u8 *peer, enum nl80211_tdls_operation oper)
6264{
6265 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6266 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6267
6268 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6269 {
6270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6271 "Invalid arguments");
6272 return -EINVAL;
6273 }
6274
6275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6276 "Request for TDLS oper: %d", (int)oper);
6277
6278 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6279 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6280 {
6281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6282 "TDLS Disabled in INI OR not enabled in FW.\
6283 Cannot process TDLS commands \n");
6284 return -ENOTSUPP;
6285 }
6286
6287 switch (oper) {
6288 case NL80211_TDLS_ENABLE_LINK:
6289 {
6290 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6291 v_U8_t my_peer[6];
6292 v_U8_t ucSTAId;
6293 VOS_STATUS status;
6294
6295 if (peer) {
6296 vos_mem_copy(my_peer, peer, 6);
6297 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6298
6299 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6300 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6301 __func__, peer[0], peer[1],
6302 peer[2], peer[3],
6303 peer[4], peer[5] );
6304
6305 if (-1 == ucSTAId ) {
6306 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
6307 return 0;
6308 }
6309
6310 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6311 WLANTL_STA_AUTHENTICATED );
6312
6313 if (0 != status) {
6314 hddLog(VOS_TRACE_LEVEL_ERROR,
6315 "%s: WLANTL_ChangeSTAState failed, returned %d",
6316 __func__, status);
6317 return status;
6318 }
6319 } else {
6320 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6321 }
6322 }
6323 break;
6324 case NL80211_TDLS_DISABLE_LINK:
6325 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6326 pAdapter->sessionId, peer );
6327 return 0;
6328 case NL80211_TDLS_TEARDOWN:
6329 case NL80211_TDLS_SETUP:
6330 case NL80211_TDLS_DISCOVERY_REQ:
6331 /* We don't support in-driver setup/teardown/discovery */
6332 return -ENOTSUPP;
6333 default:
6334 return -ENOTSUPP;
6335 }
6336 return 0;
6337}
6338#endif
6339
Jeff Johnson295189b2012-06-20 16:38:30 -07006340/* cfg80211_ops */
6341static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6342{
6343 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6344 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6345 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6346 .change_station = wlan_hdd_change_station,
6347#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6348 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6349 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6350 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006351#else
6352 .start_ap = wlan_hdd_cfg80211_start_ap,
6353 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6354 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006355#endif
6356 .change_bss = wlan_hdd_cfg80211_change_bss,
6357 .add_key = wlan_hdd_cfg80211_add_key,
6358 .get_key = wlan_hdd_cfg80211_get_key,
6359 .del_key = wlan_hdd_cfg80211_del_key,
6360 .set_default_key = wlan_hdd_cfg80211_set_default_key,
6361 .set_channel = wlan_hdd_cfg80211_set_channel,
6362 .scan = wlan_hdd_cfg80211_scan,
6363 .connect = wlan_hdd_cfg80211_connect,
6364 .disconnect = wlan_hdd_cfg80211_disconnect,
6365 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6366 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6367 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6368 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6369 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6370#ifdef WLAN_FEATURE_P2P
6371 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6372 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6373 .mgmt_tx = wlan_hdd_action,
6374#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6375 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6376 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6377 .set_txq_params = wlan_hdd_set_txq_params,
6378#endif
6379#endif
6380 .get_station = wlan_hdd_cfg80211_get_station,
6381 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6382 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006383 .add_station = wlan_hdd_cfg80211_add_station,
6384#ifdef FEATURE_WLAN_LFR
6385 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6386 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6387 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6388#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006389#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6390 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6391#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006392#ifdef FEATURE_WLAN_TDLS
6393 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6394 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6395#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006396};
6397
6398#endif // CONFIG_CFG80211