blob: d82f82a854c04c5b4a2666c162a2f872249cad13 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
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/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**========================================================================
43
44 \file wlan_hdd_cfg80211.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 21/12/09 Ashwani Created module.
69
70 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
71 Ganesh K
72 ==========================================================================*/
73
74#ifdef CONFIG_CFG80211
75
76#include <linux/version.h>
77#include <linux/module.h>
78#include <linux/kernel.h>
79#include <linux/init.h>
80#include <linux/wireless.h>
81#include <wlan_hdd_includes.h>
82#include <net/arp.h>
83#include <net/cfg80211.h>
84#include <linux/wireless.h>
85#include <wlan_hdd_wowl.h>
86#include <aniGlobal.h>
87#include "ccmApi.h"
88#include "sirParams.h"
89#include "dot11f.h"
90#include "wlan_hdd_assoc.h"
91#include "wlan_hdd_wext.h"
92#include "sme_Api.h"
93#include "wlan_hdd_p2p.h"
94#include "wlan_hdd_cfg80211.h"
95#include "wlan_hdd_hostapd.h"
96#include "sapInternal.h"
97#include "wlan_hdd_softap_tx_rx.h"
98#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053099#include "wlan_hdd_assoc.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#ifdef WLAN_BTAMP_FEATURE
101#include "bap_hdd_misc.h"
102#endif
103#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800104#ifdef FEATURE_WLAN_TDLS
105#include "wlan_hdd_tdls.h"
106#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700107
108#define g_mode_rates_size (12)
109#define a_mode_rates_size (8)
110#define FREQ_BASE_80211G (2407)
111#define FREQ_BAND_DIFF_80211G (5)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700112#define MAX_SCAN_SSID 9
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
114 ((int) OFFSET_OF( tSirBssDescription, ieFields)))
115
116#define HDD2GHZCHAN(freq, chan, flag) { \
117 .band = IEEE80211_BAND_2GHZ, \
118 .center_freq = (freq), \
119 .hw_value = (chan),\
120 .flags = (flag), \
121 .max_antenna_gain = 0 ,\
122 .max_power = 30, \
123}
124
125#define HDD5GHZCHAN(freq, chan, flag) { \
126 .band = IEEE80211_BAND_5GHZ, \
127 .center_freq = (freq), \
128 .hw_value = (chan),\
129 .flags = (flag), \
130 .max_antenna_gain = 0 ,\
131 .max_power = 30, \
132}
133
134#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
135{\
136 .bitrate = rate, \
137 .hw_value = rate_id, \
138 .flags = flag, \
139}
140
Lee Hoonkic1262f22013-01-24 21:59:00 -0800141#ifndef WLAN_FEATURE_TDLS_DEBUG
142#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
143#else
144#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
145#endif
146
Jeff Johnson295189b2012-06-20 16:38:30 -0700147static const u32 hdd_cipher_suites[] =
148{
149 WLAN_CIPHER_SUITE_WEP40,
150 WLAN_CIPHER_SUITE_WEP104,
151 WLAN_CIPHER_SUITE_TKIP,
152#ifdef FEATURE_WLAN_CCX
153#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
154 WLAN_CIPHER_SUITE_KRK,
155 WLAN_CIPHER_SUITE_CCMP,
156#else
157 WLAN_CIPHER_SUITE_CCMP,
158#endif
159#ifdef FEATURE_WLAN_WAPI
160 WLAN_CIPHER_SUITE_SMS4,
161#endif
162};
163
164static inline int is_broadcast_ether_addr(const u8 *addr)
165{
166 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
167 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
168}
169
170static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
171{
172 HDD2GHZCHAN(2412, 1, 0) ,
173 HDD2GHZCHAN(2417, 2, 0) ,
174 HDD2GHZCHAN(2422, 3, 0) ,
175 HDD2GHZCHAN(2427, 4, 0) ,
176 HDD2GHZCHAN(2432, 5, 0) ,
177 HDD2GHZCHAN(2437, 6, 0) ,
178 HDD2GHZCHAN(2442, 7, 0) ,
179 HDD2GHZCHAN(2447, 8, 0) ,
180 HDD2GHZCHAN(2452, 9, 0) ,
181 HDD2GHZCHAN(2457, 10, 0) ,
182 HDD2GHZCHAN(2462, 11, 0) ,
183 HDD2GHZCHAN(2467, 12, 0) ,
184 HDD2GHZCHAN(2472, 13, 0) ,
185 HDD2GHZCHAN(2484, 14, 0) ,
186};
187
188#ifdef WLAN_FEATURE_P2P
189static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
190{
191 HDD2GHZCHAN(2412, 1, 0) ,
192 HDD2GHZCHAN(2437, 6, 0) ,
193 HDD2GHZCHAN(2462, 11, 0) ,
194};
195#endif
196
197static struct ieee80211_channel hdd_channels_5_GHZ[] =
198{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700199 HDD5GHZCHAN(4920, 240, 0) ,
200 HDD5GHZCHAN(4940, 244, 0) ,
201 HDD5GHZCHAN(4960, 248, 0) ,
202 HDD5GHZCHAN(4980, 252, 0) ,
203 HDD5GHZCHAN(5040, 208, 0) ,
204 HDD5GHZCHAN(5060, 212, 0) ,
205 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700206 HDD5GHZCHAN(5180, 36, 0) ,
207 HDD5GHZCHAN(5200, 40, 0) ,
208 HDD5GHZCHAN(5220, 44, 0) ,
209 HDD5GHZCHAN(5240, 48, 0) ,
210 HDD5GHZCHAN(5260, 52, 0) ,
211 HDD5GHZCHAN(5280, 56, 0) ,
212 HDD5GHZCHAN(5300, 60, 0) ,
213 HDD5GHZCHAN(5320, 64, 0) ,
214 HDD5GHZCHAN(5500,100, 0) ,
215 HDD5GHZCHAN(5520,104, 0) ,
216 HDD5GHZCHAN(5540,108, 0) ,
217 HDD5GHZCHAN(5560,112, 0) ,
218 HDD5GHZCHAN(5580,116, 0) ,
219 HDD5GHZCHAN(5600,120, 0) ,
220 HDD5GHZCHAN(5620,124, 0) ,
221 HDD5GHZCHAN(5640,128, 0) ,
222 HDD5GHZCHAN(5660,132, 0) ,
223 HDD5GHZCHAN(5680,136, 0) ,
224 HDD5GHZCHAN(5700,140, 0) ,
225 HDD5GHZCHAN(5745,149, 0) ,
226 HDD5GHZCHAN(5765,153, 0) ,
227 HDD5GHZCHAN(5785,157, 0) ,
228 HDD5GHZCHAN(5805,161, 0) ,
229 HDD5GHZCHAN(5825,165, 0) ,
230};
231
232static struct ieee80211_rate g_mode_rates[] =
233{
234 HDD_G_MODE_RATETAB(10, 0x1, 0),
235 HDD_G_MODE_RATETAB(20, 0x2, 0),
236 HDD_G_MODE_RATETAB(55, 0x4, 0),
237 HDD_G_MODE_RATETAB(110, 0x8, 0),
238 HDD_G_MODE_RATETAB(60, 0x10, 0),
239 HDD_G_MODE_RATETAB(90, 0x20, 0),
240 HDD_G_MODE_RATETAB(120, 0x40, 0),
241 HDD_G_MODE_RATETAB(180, 0x80, 0),
242 HDD_G_MODE_RATETAB(240, 0x100, 0),
243 HDD_G_MODE_RATETAB(360, 0x200, 0),
244 HDD_G_MODE_RATETAB(480, 0x400, 0),
245 HDD_G_MODE_RATETAB(540, 0x800, 0),
246};
247
248static struct ieee80211_rate a_mode_rates[] =
249{
250 HDD_G_MODE_RATETAB(60, 0x10, 0),
251 HDD_G_MODE_RATETAB(90, 0x20, 0),
252 HDD_G_MODE_RATETAB(120, 0x40, 0),
253 HDD_G_MODE_RATETAB(180, 0x80, 0),
254 HDD_G_MODE_RATETAB(240, 0x100, 0),
255 HDD_G_MODE_RATETAB(360, 0x200, 0),
256 HDD_G_MODE_RATETAB(480, 0x400, 0),
257 HDD_G_MODE_RATETAB(540, 0x800, 0),
258};
259
260static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
261{
262 .channels = hdd_channels_2_4_GHZ,
263 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
264 .band = IEEE80211_BAND_2GHZ,
265 .bitrates = g_mode_rates,
266 .n_bitrates = g_mode_rates_size,
267 .ht_cap.ht_supported = 1,
268 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
269 | IEEE80211_HT_CAP_GRN_FLD
270 | IEEE80211_HT_CAP_DSSSCCK40
271 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
272 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
273 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
274 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
275 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
276 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
277};
278
279#ifdef WLAN_FEATURE_P2P
280static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
281{
282 .channels = hdd_social_channels_2_4_GHZ,
283 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
284 .band = IEEE80211_BAND_2GHZ,
285 .bitrates = g_mode_rates,
286 .n_bitrates = g_mode_rates_size,
287 .ht_cap.ht_supported = 1,
288 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
289 | IEEE80211_HT_CAP_GRN_FLD
290 | IEEE80211_HT_CAP_DSSSCCK40
291 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
292 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
293 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
294 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
295 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
296 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
297};
298#endif
299
300static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
301{
302 .channels = hdd_channels_5_GHZ,
303 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
304 .band = IEEE80211_BAND_5GHZ,
305 .bitrates = a_mode_rates,
306 .n_bitrates = a_mode_rates_size,
307 .ht_cap.ht_supported = 1,
308 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
309 | IEEE80211_HT_CAP_GRN_FLD
310 | IEEE80211_HT_CAP_DSSSCCK40
311 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
312 | IEEE80211_HT_CAP_SGI_40
313 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
314 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
315 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
316 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
317 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
318 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
319};
320
321/* This structure contain information what kind of frame are expected in
322 TX/RX direction for each kind of interface */
323static const struct ieee80211_txrx_stypes
324wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
325 [NL80211_IFTYPE_STATION] = {
326 .tx = 0xffff,
327 .rx = BIT(SIR_MAC_MGMT_ACTION) |
328 BIT(SIR_MAC_MGMT_PROBE_REQ),
329 },
330 [NL80211_IFTYPE_AP] = {
331 .tx = 0xffff,
332 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
333 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
334 BIT(SIR_MAC_MGMT_PROBE_REQ) |
335 BIT(SIR_MAC_MGMT_DISASSOC) |
336 BIT(SIR_MAC_MGMT_AUTH) |
337 BIT(SIR_MAC_MGMT_DEAUTH) |
338 BIT(SIR_MAC_MGMT_ACTION),
339 },
340#ifdef WLAN_FEATURE_P2P
341 [NL80211_IFTYPE_P2P_CLIENT] = {
342 .tx = 0xffff,
343 .rx = BIT(SIR_MAC_MGMT_ACTION) |
344 BIT(SIR_MAC_MGMT_PROBE_REQ),
345 },
346 [NL80211_IFTYPE_P2P_GO] = {
347 /* This is also same as for SoftAP */
348 .tx = 0xffff,
349 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
350 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
351 BIT(SIR_MAC_MGMT_PROBE_REQ) |
352 BIT(SIR_MAC_MGMT_DISASSOC) |
353 BIT(SIR_MAC_MGMT_AUTH) |
354 BIT(SIR_MAC_MGMT_DEAUTH) |
355 BIT(SIR_MAC_MGMT_ACTION),
356 },
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800357#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700358};
359
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800360#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
361#ifdef WLAN_FEATURE_P2P
362static const struct ieee80211_iface_limit
363wlan_hdd_iface_limit[] = {
364 {
365 /* max=2 is to support JellyBean architecture which has wlan0
366 * and p2p0 interfaces during init. p2p0 is considered station
367 * interface until a group is formed */
368 .max = 2,
369 .types = BIT(NL80211_IFTYPE_STATION),
370 },
371 {
372 .max = 1,
373 .types = BIT(NL80211_IFTYPE_AP),
374 },
375 {
376 .max = 1,
377 .types = BIT(NL80211_IFTYPE_P2P_GO) |
378 BIT(NL80211_IFTYPE_P2P_CLIENT),
379 },
380};
381
382/* By default, only single channel concurrency is allowed */
383static struct ieee80211_iface_combination
384wlan_hdd_iface_combination = {
385 .limits = wlan_hdd_iface_limit,
386 .num_different_channels = 1,
387 .max_interfaces = 2,
388 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
389 .beacon_int_infra_match = false,
390};
391#endif
392#endif
393
Jeff Johnson295189b2012-06-20 16:38:30 -0700394static struct cfg80211_ops wlan_hdd_cfg80211_ops;
395
396/* Data rate 100KBPS based on IE Index */
397struct index_data_rate_type
398{
399 v_U8_t beacon_rate_index;
400 v_U16_t supported_rate[4];
401};
402
403/* 11B, 11G Rate table include Basic rate and Extended rate
404 The IDX field is the rate index
405 The HI field is the rate when RSSI is strong or being ignored
406 (in this case we report actual rate)
407 The MID field is the rate when RSSI is moderate
408 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
409 The LO field is the rate when RSSI is low
410 (in this case we don't report rates, actual current rate used)
411 */
412static const struct
413{
414 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700415 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700416} supported_data_rate[] =
417{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700418/* IDX HI HM LM LO (RSSI-based index */
419 {2, { 10, 10, 10, 0}},
420 {4, { 20, 20, 10, 0}},
421 {11, { 55, 20, 10, 0}},
422 {12, { 60, 55, 20, 0}},
423 {18, { 90, 55, 20, 0}},
424 {22, {110, 55, 20, 0}},
425 {24, {120, 90, 60, 0}},
426 {36, {180, 120, 60, 0}},
427 {44, {220, 180, 60, 0}},
428 {48, {240, 180, 90, 0}},
429 {66, {330, 180, 90, 0}},
430 {72, {360, 240, 90, 0}},
431 {96, {480, 240, 120, 0}},
432 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700433};
434
435/* MCS Based rate table */
436static struct index_data_rate_type supported_mcs_rate[] =
437{
438/* MCS L20 L40 S20 S40 */
439 {0, {65, 135, 72, 150}},
440 {1, {130, 270, 144, 300}},
441 {2, {195, 405, 217, 450}},
442 {3, {260, 540, 289, 600}},
443 {4, {390, 810, 433, 900}},
444 {5, {520, 1080, 578, 1200}},
445 {6, {585, 1215, 650, 1350}},
446 {7, {650, 1350, 722, 1500}}
447};
448
449extern struct net_device_ops net_ops_struct;
450
451/*
452 * FUNCTION: wlan_hdd_cfg80211_init
453 * This function is called by hdd_wlan_startup()
454 * during initialization.
455 * This function is used to initialize and register wiphy structure.
456 */
457struct wiphy *wlan_hdd_cfg80211_init(int priv_size)
458{
459 struct wiphy *wiphy;
460 ENTER();
461
462 /*
463 * Create wiphy device
464 */
465 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
466
467 if (!wiphy)
468 {
469 /* Print error and jump into err label and free the memory */
470 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
471 return NULL;
472 }
473
474 return wiphy;
475}
476
477/*
478 * FUNCTION: wlan_hdd_cfg80211_update_band
479 * This function is called from the supplicant through a
480 * private ioctl to change the band value
481 */
482int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
483{
Jeff Johnsone7245742012-09-05 17:12:55 -0700484 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700485 switch(eBand)
486 {
487 case eCSR_BAND_24:
488 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
489 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
490 break;
491 case eCSR_BAND_5G:
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700492#ifdef WLAN_FEATURE_P2P
493 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
494#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700495 wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
Madan Mohan Koyyalamudi6f6390c2012-09-24 13:57:46 -0700496#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700497 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
498 break;
499 case eCSR_BAND_ALL:
500 default:
501 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
502 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
503 }
504 return 0;
505}
506/*
507 * FUNCTION: wlan_hdd_cfg80211_init
508 * This function is called by hdd_wlan_startup()
509 * during initialization.
510 * This function is used to initialize and register wiphy structure.
511 */
512int wlan_hdd_cfg80211_register(struct device *dev,
513 struct wiphy *wiphy,
514 hdd_config_t *pCfg
515 )
516{
Jeff Johnsone7245742012-09-05 17:12:55 -0700517 ENTER();
518
Jeff Johnson295189b2012-06-20 16:38:30 -0700519 /* Now bind the underlying wlan device with wiphy */
520 set_wiphy_dev(wiphy, dev);
521
522 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
523
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700524 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
Jeff Johnson295189b2012-06-20 16:38:30 -0700525
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700526#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -0700527 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
528 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
529 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -0700530 | WIPHY_FLAG_OFFCHAN_TX;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700531#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800532#ifdef FEATURE_WLAN_TDLS
533 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
534 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
535#endif
536
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700537 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
538 driver can still register regulatory callback and
539 it will get CRDA setting in wiphy->band[], but
540 driver need to determine what to do with both
541 regulatory settings */
542 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700543
Jeff Johnson295189b2012-06-20 16:38:30 -0700544 wiphy->max_scan_ssids = MAX_SCAN_SSID;
545
546 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
547
548 /* Supports STATION & AD-HOC modes right now */
549 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
550 | BIT(NL80211_IFTYPE_ADHOC)
551#ifdef WLAN_FEATURE_P2P
552 | BIT(NL80211_IFTYPE_P2P_CLIENT)
553 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800554#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700555 | BIT(NL80211_IFTYPE_AP);
556
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800557#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
558#ifdef WLAN_FEATURE_P2P
559 if( pCfg->enableMCC )
560 {
561 /* Currently, supports up to two channels */
562 wlan_hdd_iface_combination.num_different_channels = 2;
563
564 if( !pCfg->allowMCCGODiffBI )
565 wlan_hdd_iface_combination.beacon_int_infra_match = true;
566
567 }
568 wiphy->iface_combinations = &wlan_hdd_iface_combination;
569 wiphy->n_iface_combinations = 1;
570#endif
571#endif
572
Jeff Johnson295189b2012-06-20 16:38:30 -0700573 /* Before registering we need to update the ht capabilitied based
574 * on ini values*/
575 if( !pCfg->ShortGI20MhzEnable )
576 {
577 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
578 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
579 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
580 }
581
582 if( !pCfg->ShortGI40MhzEnable )
583 {
584 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
585 }
586
587 if( !pCfg->nChannelBondingMode5GHz )
588 {
589 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
590 }
591
592 /*Initialize band capability*/
593 switch(pCfg->nBandCapability)
594 {
595 case eCSR_BAND_24:
596 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
597 break;
598 case eCSR_BAND_5G:
599#ifdef WLAN_FEATURE_P2P
600 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
601#endif
602 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
603 break;
604 case eCSR_BAND_ALL:
605 default:
606 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
607 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
608 }
609 /*Initialise the supported cipher suite details*/
610 wiphy->cipher_suites = hdd_cipher_suites;
611 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
612
613 /*signal strength in mBm (100*dBm) */
614 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
615
616#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
617#ifdef WLAN_FEATURE_P2P
618 wiphy->max_remain_on_channel_duration = 1000;
619#endif
620#endif
621
622 /* Register our wiphy dev with cfg80211 */
623 if (0 > wiphy_register(wiphy))
624 {
625 /* print eror */
626 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
627 return -EIO;
628 }
629
630 EXIT();
631 return 0;
632}
633
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700634/* In this function we will try to get default country code from crda.
635 If the gCrdaDefaultCountryCode is configured in ini file,
636 we will try to call user space crda to get the regulatory settings for
637 that country. We will timeout if we can't get it from crda.
638 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
639*/
640int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
641{
642 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
643 if (memcmp(pCfg->crdaDefaultCountryCode,
644 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
645 {
646 init_completion(&pHddCtx->driver_crda_req);
647 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
648 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
649 CRDA_WAIT_TIME);
650 }
651 return 0;
652}
653
Jeff Johnson295189b2012-06-20 16:38:30 -0700654/* In this function we will do all post VOS start initialization.
655 In this function we will register for all frame in which supplicant
656 is interested.
657*/
658void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
659{
660#ifdef WLAN_FEATURE_P2P
661 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
662 /* Register for all P2P action, public action etc frames */
663 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
664
Jeff Johnsone7245742012-09-05 17:12:55 -0700665 ENTER();
666
Jeff Johnson295189b2012-06-20 16:38:30 -0700667 /* Right now we are registering these frame when driver is getting
668 initialized. Once we will move to 2.6.37 kernel, in which we have
669 frame register ops, we will move this code as a part of that */
670 /* GAS Initial Request */
671 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
672 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
673
674 /* GAS Initial Response */
675 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
676 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
677
678 /* GAS Comeback Request */
679 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
680 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
681
682 /* GAS Comeback Response */
683 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
684 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
685
686 /* P2P Public Action */
687 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
688 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
689 P2P_PUBLIC_ACTION_FRAME_SIZE );
690
691 /* P2P Action */
692 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
693 (v_U8_t*)P2P_ACTION_FRAME,
694 P2P_ACTION_FRAME_SIZE );
695#endif /* WLAN_FEATURE_P2P */
696}
697
698void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
699{
700#ifdef WLAN_FEATURE_P2P
701 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
702 /* Register for all P2P action, public action etc frames */
703 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
704
Jeff Johnsone7245742012-09-05 17:12:55 -0700705 ENTER();
706
Jeff Johnson295189b2012-06-20 16:38:30 -0700707 /* Right now we are registering these frame when driver is getting
708 initialized. Once we will move to 2.6.37 kernel, in which we have
709 frame register ops, we will move this code as a part of that */
710 /* GAS Initial Request */
711
712 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
713 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
714
715 /* GAS Initial Response */
716 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
717 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
718
719 /* GAS Comeback Request */
720 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
721 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
722
723 /* GAS Comeback Response */
724 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
725 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
726
727 /* P2P Public Action */
728 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
729 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
730 P2P_PUBLIC_ACTION_FRAME_SIZE );
731
732 /* P2P Action */
733 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
734 (v_U8_t*)P2P_ACTION_FRAME,
735 P2P_ACTION_FRAME_SIZE );
736#endif /* WLAN_FEATURE_P2P */
737}
738
739#ifdef FEATURE_WLAN_WAPI
740void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
741 const u8 *mac_addr, u8 *key , int key_Len)
742{
743 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
744 tCsrRoamSetKey setKey;
745 v_BOOL_t isConnected = TRUE;
746 int status = 0;
747 v_U32_t roamId= 0xFF;
748 tANI_U8 *pKeyPtr = NULL;
749 int n = 0;
750
751 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
752 __func__,pAdapter->device_mode);
753
754 setKey.keyId = key_index; // Store Key ID
755 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
756 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
757 setKey.paeRole = 0 ; // the PAE role
758 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
759 {
760 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
761 }
762 else
763 {
764 isConnected = hdd_connIsConnected(pHddStaCtx);
765 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
766 }
767 setKey.keyLength = key_Len;
768 pKeyPtr = setKey.Key;
769 memcpy( pKeyPtr, key, key_Len);
770
771 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
772 __func__, key_Len);
773 for (n = 0 ; n < key_Len; n++)
774 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
775 __func__,n,setKey.Key[n]);
776
777 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
778 if ( isConnected )
779 {
780 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
781 pAdapter->sessionId, &setKey, &roamId );
782 }
783 if ( status != 0 )
784 {
785 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
786 "[%4d] sme_RoamSetKey returned ERROR status= %d",
787 __LINE__, status );
788 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
789 }
790}
791#endif /* FEATURE_WLAN_WAPI*/
792
793#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
794int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
795 beacon_data_t **ppBeacon,
796 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700797#else
798int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
799 beacon_data_t **ppBeacon,
800 struct cfg80211_beacon_data *params,
801 int dtim_period)
802#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700803{
804 int size;
805 beacon_data_t *beacon = NULL;
806 beacon_data_t *old = NULL;
807 int head_len,tail_len;
808
Jeff Johnsone7245742012-09-05 17:12:55 -0700809 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700810 if (params->head && !params->head_len)
811 return -EINVAL;
812
813 old = pAdapter->sessionCtx.ap.beacon;
814
815 if (!params->head && !old)
816 return -EINVAL;
817
818 if (params->tail && !params->tail_len)
819 return -EINVAL;
820
821#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
822 /* Kernel 3.0 is not updating dtim_period for set beacon */
823 if (!params->dtim_period)
824 return -EINVAL;
825#endif
826
827 if(params->head)
828 head_len = params->head_len;
829 else
830 head_len = old->head_len;
831
832 if(params->tail || !old)
833 tail_len = params->tail_len;
834 else
835 tail_len = old->tail_len;
836
837 size = sizeof(beacon_data_t) + head_len + tail_len;
838
839 beacon = kzalloc(size, GFP_KERNEL);
840
841 if( beacon == NULL )
842 return -ENOMEM;
843
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700844#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700845 if(params->dtim_period || !old )
846 beacon->dtim_period = params->dtim_period;
847 else
848 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700849#else
850 if(dtim_period || !old )
851 beacon->dtim_period = dtim_period;
852 else
853 beacon->dtim_period = old->dtim_period;
854#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700855
856 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
857 beacon->tail = beacon->head + head_len;
858 beacon->head_len = head_len;
859 beacon->tail_len = tail_len;
860
861 if(params->head) {
862 memcpy (beacon->head,params->head,beacon->head_len);
863 }
864 else {
865 if(old)
866 memcpy (beacon->head,old->head,beacon->head_len);
867 }
868
869 if(params->tail) {
870 memcpy (beacon->tail,params->tail,beacon->tail_len);
871 }
872 else {
873 if(old)
874 memcpy (beacon->tail,old->tail,beacon->tail_len);
875 }
876
877 *ppBeacon = beacon;
878
879 kfree(old);
880
881 return 0;
882
883}
Jeff Johnson295189b2012-06-20 16:38:30 -0700884
885v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
886{
887 int left = length;
888 v_U8_t *ptr = pIes;
889 v_U8_t elem_id,elem_len;
890
891 while(left >= 2)
892 {
893 elem_id = ptr[0];
894 elem_len = ptr[1];
895 left -= 2;
896 if(elem_len > left)
897 {
898 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700899 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700900 eid,elem_len,left);
901 return NULL;
902 }
903 if (elem_id == eid)
904 {
905 return ptr;
906 }
907
908 left -= elem_len;
909 ptr += (elem_len + 2);
910 }
911 return NULL;
912}
913
Jeff Johnson295189b2012-06-20 16:38:30 -0700914/* Check if rate is 11g rate or not */
915static int wlan_hdd_rate_is_11g(u8 rate)
916{
917 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
918 u8 i;
919 for (i = 0; i < 8; i++)
920 {
921 if(rate == gRateArray[i])
922 return TRUE;
923 }
924 return FALSE;
925}
926
927/* Check for 11g rate and set proper 11g only mode */
928static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
929 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
930{
931 u8 i, num_rates = pIe[0];
932
933 pIe += 1;
934 for ( i = 0; i < num_rates; i++)
935 {
936 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
937 {
938 /* If rate set have 11g rate than change the mode to 11G */
939 *pSapHw_mode = eSAP_DOT11_MODE_11g;
940 if (pIe[i] & BASIC_RATE_MASK)
941 {
942 /* If we have 11g rate as basic rate, it means mode
943 is 11g only mode.
944 */
945 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
946 *pCheckRatesfor11g = FALSE;
947 }
948 }
949 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
950 {
951 *require_ht = TRUE;
952 }
953 }
954 return;
955}
956
957static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
958{
959 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
960 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
961 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
962 u8 checkRatesfor11g = TRUE;
963 u8 require_ht = FALSE;
964 u8 *pIe=NULL;
965
966 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
967
968 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
969 pBeacon->head_len, WLAN_EID_SUPP_RATES);
970 if (pIe != NULL)
971 {
972 pIe += 1;
973 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
974 &pConfig->SapHw_mode);
975 }
976
977 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
978 WLAN_EID_EXT_SUPP_RATES);
979 if (pIe != NULL)
980 {
981
982 pIe += 1;
983 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
984 &pConfig->SapHw_mode);
985 }
986
987 if( pConfig->channel > 14 )
988 {
989 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
990 }
991
992 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
993 WLAN_EID_HT_CAPABILITY);
994
995 if(pIe)
996 {
997 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
998 if(require_ht)
999 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1000 }
1001}
1002
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001003#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001004static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1005 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001006#else
1007static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1008 struct cfg80211_beacon_data *params)
1009#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001010{
1011 v_U8_t *genie;
1012 v_U8_t total_ielen = 0, ielen = 0;
1013 v_U8_t *pIe = NULL;
1014 v_U8_t addIE[1] = {0};
1015 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -07001016 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001017
1018 genie = vos_mem_malloc(MAX_GENIE_LEN);
1019
1020 if(genie == NULL) {
1021
1022 return -ENOMEM;
1023 }
1024
1025 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1026
1027 if(pIe)
1028 {
1029 /*Copy the wps IE*/
1030 ielen = pIe[1] + 2;
1031 if( ielen <=MAX_GENIE_LEN)
1032 {
1033 vos_mem_copy(genie, pIe, ielen);
1034 }
1035 else
1036 {
1037 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001038 ret = -EINVAL;
1039 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001040 }
1041 total_ielen = ielen;
1042 }
1043
1044#ifdef WLAN_FEATURE_WFD
1045 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1046
1047 if(pIe)
1048 {
1049 ielen = pIe[1] + 2;
1050 if(total_ielen + ielen <= MAX_GENIE_LEN) {
1051 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
1052 }
1053 else {
1054 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001055 ret = -EINVAL;
1056 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001057 }
1058 total_ielen += ielen;
1059 }
1060#endif
1061
1062#ifdef WLAN_FEATURE_P2P
1063 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1064
1065 if(pIe)
1066 {
1067 ielen = pIe[1] + 2;
1068 if(total_ielen + ielen <= MAX_GENIE_LEN)
1069 {
1070 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1071 }
1072 else
1073 {
1074 hddLog( VOS_TRACE_LEVEL_ERROR,
1075 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001076 ret = -EINVAL;
1077 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001078 }
1079 total_ielen += ielen;
1080 }
1081#endif
1082
1083 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1084 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1085 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1086 {
1087 hddLog(LOGE,
1088 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001089 ret = -EINVAL;
1090 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001091 }
1092
1093 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1094 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1095 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1096 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1097 ==eHAL_STATUS_FAILURE)
1098 {
1099 hddLog(LOGE,
1100 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001101 ret = -EINVAL;
1102 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 }
1104
1105 // Added for ProResp IE
1106 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1107 {
1108 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1109 u8 probe_rsp_ie_len[3] = {0};
1110 u8 counter = 0;
1111 /* Check Probe Resp Length if it is greater then 255 then Store
1112 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1113 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1114 Store More then 255 bytes into One Variable.
1115 */
1116 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1117 {
1118 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1119 {
1120 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1121 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1122 }
1123 else
1124 {
1125 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1126 rem_probe_resp_ie_len = 0;
1127 }
1128 }
1129
1130 rem_probe_resp_ie_len = 0;
1131
1132 if (probe_rsp_ie_len[0] > 0)
1133 {
1134 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1135 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1136 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1137 probe_rsp_ie_len[0], NULL,
1138 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1139 {
1140 hddLog(LOGE,
1141 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001142 ret = -EINVAL;
1143 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001144 }
1145 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1146 }
1147
1148 if (probe_rsp_ie_len[1] > 0)
1149 {
1150 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1151 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1152 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1153 probe_rsp_ie_len[1], NULL,
1154 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1155 {
1156 hddLog(LOGE,
1157 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001158 ret = -EINVAL;
1159 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001160 }
1161 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1162 }
1163
1164 if (probe_rsp_ie_len[2] > 0)
1165 {
1166 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1167 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1168 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1169 probe_rsp_ie_len[2], NULL,
1170 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1171 {
1172 hddLog(LOGE,
1173 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001174 ret = -EINVAL;
1175 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 }
1177 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1178 }
1179
1180 if (probe_rsp_ie_len[1] == 0 )
1181 {
1182 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1183 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1184 eANI_BOOLEAN_FALSE) )
1185 {
1186 hddLog(LOGE,
1187 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1188 }
1189 }
1190
1191 if (probe_rsp_ie_len[2] == 0 )
1192 {
1193 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1194 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1195 eANI_BOOLEAN_FALSE) )
1196 {
1197 hddLog(LOGE,
1198 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1199 }
1200 }
1201
1202 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1203 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1204 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1205 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1206 == eHAL_STATUS_FAILURE)
1207 {
1208 hddLog(LOGE,
1209 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001210 ret = -EINVAL;
1211 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001212 }
1213 }
1214 else
1215 {
1216 // Reset WNI_CFG_PROBE_RSP Flags
1217 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1218
1219 hddLog(VOS_TRACE_LEVEL_INFO,
1220 "%s: No Probe Response IE received in set beacon",
1221 __func__);
1222 }
1223
1224 // Added for AssocResp IE
1225 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1226 {
1227 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1228 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1229 params->assocresp_ies_len, NULL,
1230 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1231 {
1232 hddLog(LOGE,
1233 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001234 ret = -EINVAL;
1235 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001236 }
1237
1238 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1239 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1240 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1241 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1242 == eHAL_STATUS_FAILURE)
1243 {
1244 hddLog(LOGE,
1245 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001246 ret = -EINVAL;
1247 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001248 }
1249 }
1250 else
1251 {
1252 hddLog(VOS_TRACE_LEVEL_INFO,
1253 "%s: No Assoc Response IE received in set beacon",
1254 __func__);
1255
1256 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1257 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1258 eANI_BOOLEAN_FALSE) )
1259 {
1260 hddLog(LOGE,
1261 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1262 }
1263 }
1264
Jeff Johnsone7245742012-09-05 17:12:55 -07001265done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001266 vos_mem_free(genie);
1267 return 0;
1268}
Jeff Johnson295189b2012-06-20 16:38:30 -07001269
1270/*
1271 * FUNCTION: wlan_hdd_validate_operation_channel
1272 * called by wlan_hdd_cfg80211_start_bss() and
1273 * wlan_hdd_cfg80211_set_channel()
1274 * This function validates whether given channel is part of valid
1275 * channel list.
1276 */
1277static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1278{
1279
1280 v_U32_t num_ch = 0;
1281 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1282 u32 indx = 0;
1283 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1284
1285 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1286
1287 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1288 valid_ch, &num_ch))
1289 {
1290 hddLog(VOS_TRACE_LEVEL_ERROR,
1291 "%s: failed to get valid channel list\n", __func__);
1292 return VOS_STATUS_E_FAILURE;
1293 }
1294
1295 for (indx = 0; indx < num_ch; indx++)
1296 {
1297 if (channel == valid_ch[indx])
1298 {
1299 break;
1300 }
1301 }
1302
1303 if (indx >= num_ch)
1304 {
1305 hddLog(VOS_TRACE_LEVEL_ERROR,
1306 "%s: Invalid Channel [%d] \n", __func__, channel);
1307 return VOS_STATUS_E_FAILURE;
1308 }
1309 return VOS_STATUS_SUCCESS;
1310
1311}
1312
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301313/*
1314 * FUNCTION: wlan_hdd_select_cbmode
1315 * called by wlan_hdd_cfg80211_start_bss() and
1316 * This function selects the cbmode based on primary channel
1317 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001318VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301319{
1320 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001321 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1322 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1323
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301324 if(
1325#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001326 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1327 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301328#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001329 SapHw_mode != eSAP_DOT11_MODE_11n &&
1330 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301331 )
1332 {
1333 return VOS_STATUS_SUCCESS;
1334 }
1335
1336 if (!pConfigIni->nChannelBondingMode5GHz) {
1337 return VOS_STATUS_SUCCESS;
1338 }
1339
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001340 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301341 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1342
1343 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1344
1345#ifdef WLAN_FEATURE_11AC
1346
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001347 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1348 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301349 {
1350 if ( channel== 36 || channel == 52 || channel == 100 ||
1351 channel == 116 || channel == 149 )
1352 {
1353 smeConfig.csrConfig.channelBondingMode5GHz =
1354 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1355 }
1356 else if ( channel == 40 || channel == 56 || channel == 104 ||
1357 channel == 120 || channel == 153 )
1358 {
1359 smeConfig.csrConfig.channelBondingMode5GHz =
1360 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1361 }
1362 else if ( channel == 44 || channel == 60 || channel == 108 ||
1363 channel == 124 || channel == 157 )
1364 {
1365 smeConfig.csrConfig.channelBondingMode5GHz =
1366 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1367 }
1368 else if ( channel == 48 || channel == 64 || channel == 112 ||
1369 channel == 128 || channel == 161 )
1370 {
1371 smeConfig.csrConfig.channelBondingMode5GHz =
1372 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1373 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301374 }
1375#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001376 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1377 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301378 {
1379 if ( channel== 40 || channel == 48 || channel == 56 ||
1380 channel == 64 || channel == 104 || channel == 112 ||
1381 channel == 120 || channel == 128 || channel == 136 ||
1382 channel == 144 || channel == 153 || channel == 161 )
1383 {
1384 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1385 }
1386 else if ( channel== 36 || channel == 44 || channel == 52 ||
1387 channel == 60 || channel == 100 || channel == 108 ||
1388 channel == 116 || channel == 124 || channel == 132 ||
1389 channel == 140 || channel == 149 || channel == 157 )
1390 {
1391 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1392 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301393 }
1394 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1395
1396 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1397 return VOS_STATUS_SUCCESS;
1398}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001399
Jeff Johnson295189b2012-06-20 16:38:30 -07001400#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1401static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1402 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001403#else
1404static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1405 struct cfg80211_beacon_data *params,
1406 const u8 *ssid, size_t ssid_len,
1407 enum nl80211_hidden_ssid hidden_ssid)
1408#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001409{
1410 tsap_Config_t *pConfig;
1411 beacon_data_t *pBeacon = NULL;
1412 struct ieee80211_mgmt *pMgmt_frame;
1413 v_U8_t *pIe=NULL;
1414 v_U16_t capab_info;
1415 eCsrAuthType RSNAuthType;
1416 eCsrEncryptionType RSNEncryptType;
1417 eCsrEncryptionType mcRSNEncryptType;
1418 int status = VOS_STATUS_SUCCESS;
1419 tpWLAN_SAPEventCB pSapEventCallback;
1420 hdd_hostapd_state_t *pHostapdState;
1421 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1422 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1423 struct qc_mac_acl_entry *acl_entry = NULL;
1424 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001425 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001426
1427 ENTER();
1428
1429 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1430
1431 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1432
1433 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1434
1435 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1436
1437 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1438
1439 //channel is already set in the set_channel Call back
1440 //pConfig->channel = pCommitConfig->channel;
1441
1442 /*Protection parameter to enable or disable*/
1443 pConfig->protEnabled =
1444 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1445
1446 pConfig->dtim_period = pBeacon->dtim_period;
1447
1448 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1449 pConfig->dtim_period);
1450
1451
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001452 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001453 {
1454 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001455 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001456 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001457 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001458 tANI_BOOLEAN restartNeeded;
1459 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1460 pConfig->ieee80211d = 1;
1461 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1462 sme_setRegInfo(hHal, pConfig->countryCode);
1463 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1464 /*
1465 * If auto channel is configured i.e. channel is 0,
1466 * so skip channel validation.
1467 */
1468 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001469 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001470 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1471 {
1472 hddLog(VOS_TRACE_LEVEL_ERROR,
1473 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1474 return -EINVAL;
1475 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001476 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001477 /*
1478 * Validate the given channel range for the given country code
1479 */
1480 else
1481 {
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001482 if(1 != pHddCtx->is_dynamic_channel_range_set)
Ng Chilamfc416462012-12-27 17:26:52 -08001483 {
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001484 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001485 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
Ng Chilamfc416462012-12-27 17:26:52 -08001486 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001487 }
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001488
Ng Chilamfc416462012-12-27 17:26:52 -08001489 pHddCtx->is_dynamic_channel_range_set = 0;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001490 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001491 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001492 else
1493 {
1494 pConfig->ieee80211d = 0;
1495 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001496 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001497 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001498 {
1499 pConfig->ieee80211d = 0;
1500 }
1501 pConfig->authType = eSAP_AUTO_SWITCH;
1502
1503 capab_info = pMgmt_frame->u.beacon.capab_info;
1504
1505 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1506 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1507
1508 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1509
1510 /*Set wps station to configured*/
1511 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1512
1513 if(pIe)
1514 {
1515 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1516 {
1517 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1518 return -EINVAL;
1519 }
1520 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1521 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001522 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001523 /* Check 15 bit of WPS IE as it contain information for wps state
1524 * WPS state
1525 */
1526 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1527 {
1528 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1529 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1530 {
1531 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1532 }
1533 }
1534 }
1535 else
1536 {
1537 pConfig->wps_state = SAP_WPS_DISABLED;
1538 }
1539 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1540
1541 pConfig->RSNWPAReqIELength = 0;
1542 pConfig->pRSNWPAReqIE = NULL;
1543 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1544 WLAN_EID_RSN);
1545 if(pIe && pIe[1])
1546 {
1547 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1548 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1549 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1550 /* The actual processing may eventually be more extensive than
1551 * this. Right now, just consume any PMKIDs that are sent in
1552 * by the app.
1553 * */
1554 status = hdd_softap_unpackIE(
1555 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1556 &RSNEncryptType,
1557 &mcRSNEncryptType,
1558 &RSNAuthType,
1559 pConfig->pRSNWPAReqIE[1]+2,
1560 pConfig->pRSNWPAReqIE );
1561
1562 if( VOS_STATUS_SUCCESS == status )
1563 {
1564 /* Now copy over all the security attributes you have
1565 * parsed out
1566 * */
1567 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1568 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1569 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1570 = RSNEncryptType;
1571 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1572 "EncryptionType = %d mcEncryptionType = %d\n"),
1573 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1574 }
1575 }
1576
1577 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1578 pBeacon->tail, pBeacon->tail_len);
1579
1580 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1581 {
1582 if (pConfig->pRSNWPAReqIE)
1583 {
1584 /*Mixed mode WPA/WPA2*/
1585 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1586 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1587 }
1588 else
1589 {
1590 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1591 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1592 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1593 status = hdd_softap_unpackIE(
1594 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1595 &RSNEncryptType,
1596 &mcRSNEncryptType,
1597 &RSNAuthType,
1598 pConfig->pRSNWPAReqIE[1]+2,
1599 pConfig->pRSNWPAReqIE );
1600
1601 if( VOS_STATUS_SUCCESS == status )
1602 {
1603 /* Now copy over all the security attributes you have
1604 * parsed out
1605 * */
1606 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1607 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1608 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1609 = RSNEncryptType;
1610 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1611 "EncryptionType = %d mcEncryptionType = %d\n"),
1612 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1613 }
1614 }
1615 }
1616
1617 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1618
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001619#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001620 if (params->ssid != NULL)
1621 {
1622 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1623 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1624 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1625 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1626 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001627#else
1628 if (ssid != NULL)
1629 {
1630 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1631 pConfig->SSIDinfo.ssid.length = ssid_len;
1632 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1633 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1634 }
1635#endif
1636
Jeff Johnson295189b2012-06-20 16:38:30 -07001637 vos_mem_copy(pConfig->self_macaddr.bytes,
1638 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1639
1640 /* default value */
1641 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1642 pConfig->num_accept_mac = 0;
1643 pConfig->num_deny_mac = 0;
1644
1645 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1646 pBeacon->tail, pBeacon->tail_len);
1647
1648 /* pIe for black list is following form:
1649 type : 1 byte
1650 length : 1 byte
1651 OUI : 4 bytes
1652 acl type : 1 byte
1653 no of mac addr in black list: 1 byte
1654 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1655 */
1656 if ((pIe != NULL) && (pIe[1] != 0))
1657 {
1658 pConfig->SapMacaddr_acl = pIe[6];
1659 pConfig->num_deny_mac = pIe[7];
1660 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1661 pIe[6], pIe[7]);
1662 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1663 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1664 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1665 for (i = 0; i < pConfig->num_deny_mac; i++)
1666 {
1667 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1668 acl_entry++;
1669 }
1670 }
1671 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1672 pBeacon->tail, pBeacon->tail_len);
1673
1674 /* pIe for white list is following form:
1675 type : 1 byte
1676 length : 1 byte
1677 OUI : 4 bytes
1678 acl type : 1 byte
1679 no of mac addr in white list: 1 byte
1680 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1681 */
1682 if ((pIe != NULL) && (pIe[1] != 0))
1683 {
1684 pConfig->SapMacaddr_acl = pIe[6];
1685 pConfig->num_accept_mac = pIe[7];
1686 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1687 pIe[6], pIe[7]);
1688 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1689 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1690 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1691 for (i = 0; i < pConfig->num_accept_mac; i++)
1692 {
1693 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1694 acl_entry++;
1695 }
1696 }
1697 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1698
Jeff Johnsone7245742012-09-05 17:12:55 -07001699#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001700 /* Overwrite the hostapd setting for HW mode only for 11ac.
1701 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1702 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1703 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1704 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1705 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1706 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1707 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001708 {
1709 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1710 }
1711#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301712
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001713 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1714 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 // ht_capab is not what the name conveys,this is used for protection bitmap
1716 pConfig->ht_capab =
1717 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1718
1719 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1720 {
1721 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1722 return -EINVAL;
1723 }
1724
1725 //Uapsd Enabled Bit
1726 pConfig->UapsdEnable =
1727 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1728 //Enable OBSS protection
1729 pConfig->obssProtEnabled =
1730 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1731
1732 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1733 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1734 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1735 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1736 (int)pConfig->channel);
1737 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1738 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1739 pConfig->authType);
1740 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1741 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1742 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1743 pConfig->protEnabled, pConfig->obssProtEnabled);
1744
1745 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1746 {
1747 //Bss already started. just return.
1748 //TODO Probably it should update some beacon params.
1749 hddLog( LOGE, "Bss Already started...Ignore the request");
1750 EXIT();
1751 return 0;
1752 }
1753
1754 pConfig->persona = pHostapdAdapter->device_mode;
1755
1756 pSapEventCallback = hdd_hostapd_SAPEventCB;
1757 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1758 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1759 {
1760 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1761 return -EINVAL;
1762 }
1763
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001764 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001765 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1766
1767 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1768
1769 if (!VOS_IS_STATUS_SUCCESS(status))
1770 {
1771 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1772 ("ERROR: HDD vos wait for single_event failed!!\n"));
1773 VOS_ASSERT(0);
1774 }
1775
1776 //Succesfully started Bss update the state bit.
1777 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1778
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001779#ifdef WLAN_FEATURE_P2P_DEBUG
1780 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1781 {
1782 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1783 {
1784 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1785 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001786 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001787 }
1788 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1789 {
1790 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1791 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001792 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001793 }
1794 }
1795#endif
1796
Jeff Johnson295189b2012-06-20 16:38:30 -07001797 pHostapdState->bCommit = TRUE;
1798 EXIT();
1799
1800 return 0;
1801}
1802
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001803#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001804static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1805 struct net_device *dev,
1806 struct beacon_parameters *params)
1807{
1808 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1809 int status=VOS_STATUS_SUCCESS;
1810
1811 ENTER();
1812
1813 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1814
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001815 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1816 {
1817 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1818 "%s:LOGP in Progress. Ignore!!!", __func__);
1819 return -EAGAIN;
1820 }
1821
Jeff Johnson295189b2012-06-20 16:38:30 -07001822 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1823#ifdef WLAN_FEATURE_P2P
1824 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1825#endif
1826 )
1827 {
1828 beacon_data_t *old,*new;
1829
1830 old = pAdapter->sessionCtx.ap.beacon;
1831
1832 if (old)
1833 return -EALREADY;
1834
1835 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1836
1837 if(status != VOS_STATUS_SUCCESS)
1838 {
1839 hddLog(VOS_TRACE_LEVEL_FATAL,
1840 "%s:Error!!! Allocating the new beacon\n",__func__);
1841 return -EINVAL;
1842 }
1843
1844 pAdapter->sessionCtx.ap.beacon = new;
1845
1846 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1847 }
1848
1849 EXIT();
1850 return status;
1851}
1852
1853static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1854 struct net_device *dev,
1855 struct beacon_parameters *params)
1856{
1857 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1858 int status=VOS_STATUS_SUCCESS;
1859
1860 ENTER();
1861
1862 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1863 __func__,pAdapter->device_mode);
1864
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001865 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1866 {
1867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1868 "%s:LOGP in Progress. Ignore!!!", __func__);
1869 return -EAGAIN;
1870 }
1871
Jeff Johnson295189b2012-06-20 16:38:30 -07001872 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1873#ifdef WLAN_FEATURE_P2P
1874 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1875#endif
1876 )
1877 {
1878 beacon_data_t *old,*new;
1879
1880 old = pAdapter->sessionCtx.ap.beacon;
1881
1882 if (!old)
1883 return -ENOENT;
1884
1885 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1886
1887 if(status != VOS_STATUS_SUCCESS) {
1888 hddLog(VOS_TRACE_LEVEL_FATAL,
1889 "%s: Error!!! Allocating the new beacon\n",__func__);
1890 return -EINVAL;
1891 }
1892
1893 pAdapter->sessionCtx.ap.beacon = new;
1894
1895 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1896 }
1897
1898 EXIT();
1899 return status;
1900}
1901
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001902#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1903
1904#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001905static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1906 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001907#else
1908static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1909 struct net_device *dev)
1910#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001911{
1912 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001913 hdd_context_t *pHddCtx = NULL;
1914 hdd_scaninfo_t *pScanInfo = NULL;
1915 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001916 VOS_STATUS status = 0;
1917
1918 ENTER();
1919
1920 if (NULL == pAdapter)
1921 {
1922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001923 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001924 return -ENODEV;
1925 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001926 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1927 {
1928 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1929 "%s:LOGP in Progress. Ignore!!!", __func__);
1930 return -EAGAIN;
1931 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001932
1933 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1934 if (NULL == pHddCtx)
1935 {
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001937 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001938 return -ENODEV;
1939 }
1940
1941 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1942 if (NULL == staAdapter)
1943 {
1944 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1945 if (NULL == staAdapter)
1946 {
1947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001948 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001949 return -ENODEV;
1950 }
1951 }
1952
1953 pScanInfo = &pHddCtx->scan_info;
1954
Jeff Johnson295189b2012-06-20 16:38:30 -07001955 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1956 {
1957 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1958 return -EAGAIN;
1959 }
1960
1961 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1962
1963 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1964 __func__,pAdapter->device_mode);
1965
Jeff Johnsone7245742012-09-05 17:12:55 -07001966 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1967 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001968 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001969 hdd_abort_mac_scan(staAdapter->pHddCtx);
1970 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001971 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07001972 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1973 if (!status)
1974 {
1975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08001976 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001977 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001978 VOS_ASSERT(pScanInfo->mScanPending);
1979 return 0;
1980 }
1981 }
1982
Jeff Johnson295189b2012-06-20 16:38:30 -07001983 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1984#ifdef WLAN_FEATURE_P2P
1985 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1986#endif
1987 )
1988 {
1989 beacon_data_t *old;
1990
1991 old = pAdapter->sessionCtx.ap.beacon;
1992
1993 if (!old)
1994 return -ENOENT;
1995
1996#ifdef CONFIG_CFG80211
1997 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1998#endif
1999
2000 mutex_lock(&pHddCtx->sap_lock);
2001 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2002 {
2003 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2004 {
2005 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2006
2007 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2008
2009 if (!VOS_IS_STATUS_SUCCESS(status))
2010 {
2011 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2012 ("ERROR: HDD vos wait for single_event failed!!\n"));
2013 VOS_ASSERT(0);
2014 }
2015 }
2016 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2017 }
2018 mutex_unlock(&pHddCtx->sap_lock);
2019
2020 if(status != VOS_STATUS_SUCCESS)
2021 {
2022 hddLog(VOS_TRACE_LEVEL_FATAL,
2023 "%s:Error!!! Stopping the BSS\n",__func__);
2024 return -EINVAL;
2025 }
2026
2027 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2028 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2029 ==eHAL_STATUS_FAILURE)
2030 {
2031 hddLog(LOGE,
2032 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2033 }
2034
2035 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2036 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2037 eANI_BOOLEAN_FALSE) )
2038 {
2039 hddLog(LOGE,
2040 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2041 }
2042
2043 // Reset WNI_CFG_PROBE_RSP Flags
2044 wlan_hdd_reset_prob_rspies(pAdapter);
2045
2046 pAdapter->sessionCtx.ap.beacon = NULL;
2047 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002048#ifdef WLAN_FEATURE_P2P_DEBUG
2049 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2050 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2051 {
2052 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2053 "GO got removed");
2054 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2055 }
2056#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002057 }
2058 EXIT();
2059 return status;
2060}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002061
2062#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2063
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302064static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2065 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002066 struct cfg80211_ap_settings *params)
2067{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302068 hdd_adapter_t *pAdapter;
2069 hdd_context_t *pHddCtx;
2070 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002071
2072 ENTER();
2073
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302074 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002075 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302076 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2077 "%s: Device is Null", __func__);
2078 return -ENODEV;
2079 }
2080
2081 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2082 if (NULL == pAdapter)
2083 {
2084 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2085 "%s: HDD adapter is Null", __func__);
2086 return -ENODEV;
2087 }
2088
2089 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2090 {
2091 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2092 "%s: HDD adapter magic is invalid", __func__);
2093 return -ENODEV;
2094 }
2095
2096 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2097 if (NULL == pHddCtx)
2098 {
2099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2100 "%s: HDD context is Null", __func__);
2101 return -ENODEV;
2102 }
2103
2104 if (pHddCtx->isLogpInProgress)
2105 {
2106 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2107 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002108 return -EAGAIN;
2109 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302110
2111 if (pHddCtx->isLoadUnloadInProgress)
2112 {
2113 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2114 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2115 return -EAGAIN;
2116 }
2117
2118 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2119 __func__, pAdapter->device_mode);
2120
2121 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002122#ifdef WLAN_FEATURE_P2P
2123 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2124#endif
2125 )
2126 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302127 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002128
2129 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302130
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002131 if (old)
2132 return -EALREADY;
2133
2134 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2135
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302136 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002137 {
2138 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302139 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002140 return -EINVAL;
2141 }
2142 pAdapter->sessionCtx.ap.beacon = new;
2143 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2144 params->ssid_len, params->hidden_ssid);
2145 }
2146
2147 EXIT();
2148 return status;
2149}
2150
2151
2152static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2153 struct net_device *dev,
2154 struct cfg80211_beacon_data *params)
2155{
2156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2157 int status=VOS_STATUS_SUCCESS;
2158
2159 ENTER();
2160
2161 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2162 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002163 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2164 {
2165 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2166 return -EAGAIN;
2167 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002168
2169 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2170#ifdef WLAN_FEATURE_P2P
2171 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2172#endif
2173 )
2174 {
2175 beacon_data_t *old,*new;
2176
2177 old = pAdapter->sessionCtx.ap.beacon;
2178
2179 if (!old)
2180 return -ENOENT;
2181
2182 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2183
2184 if(status != VOS_STATUS_SUCCESS) {
2185 hddLog(VOS_TRACE_LEVEL_FATAL,
2186 "%s: Error!!! Allocating the new beacon\n",__func__);
2187 return -EINVAL;
2188 }
2189
2190 pAdapter->sessionCtx.ap.beacon = new;
2191
2192 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2193 }
2194
2195 EXIT();
2196 return status;
2197}
2198
2199#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2200
Jeff Johnson295189b2012-06-20 16:38:30 -07002201
2202static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2203 struct net_device *dev,
2204 struct bss_parameters *params)
2205{
2206 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2207
2208 ENTER();
2209
2210 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2211 __func__,pAdapter->device_mode);
2212
2213 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2214#ifdef WLAN_FEATURE_P2P
2215 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2216#endif
2217 )
2218 {
2219 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2220 * want to update this parameter */
2221 if (-1 != params->ap_isolate)
2222 {
2223 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2224 }
2225 }
2226
2227 EXIT();
2228 return 0;
2229}
2230
2231/*
2232 * FUNCTION: wlan_hdd_cfg80211_change_iface
2233 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2234 */
2235int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2236 struct net_device *ndev,
2237 enum nl80211_iftype type,
2238 u32 *flags,
2239 struct vif_params *params
2240 )
2241{
2242 struct wireless_dev *wdev;
2243 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2244 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002245 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002246 tCsrRoamProfile *pRoamProfile = NULL;
2247 eCsrRoamBssType LastBSSType;
2248 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2249 eMib_dot11DesiredBssType connectedBssType;
2250 VOS_STATUS status;
2251
2252 ENTER();
2253
2254 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2255 {
2256 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2257 return -EAGAIN;
2258 }
2259
2260 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2261 __func__, pAdapter->device_mode);
2262
2263 wdev = ndev->ieee80211_ptr;
2264
2265#ifdef WLAN_BTAMP_FEATURE
2266 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2267 (NL80211_IFTYPE_ADHOC == type)||
2268 (NL80211_IFTYPE_AP == type)||
2269 (NL80211_IFTYPE_P2P_GO == type))
2270 {
2271 pHddCtx->isAmpAllowed = VOS_FALSE;
2272 // stop AMP traffic
2273 status = WLANBAP_StopAmp();
2274 if(VOS_STATUS_SUCCESS != status )
2275 {
2276 pHddCtx->isAmpAllowed = VOS_TRUE;
2277 hddLog(VOS_TRACE_LEVEL_FATAL,
2278 "%s: Failed to stop AMP", __func__);
2279 return -EINVAL;
2280 }
2281 }
2282#endif //WLAN_BTAMP_FEATURE
2283 /* Reset the current device mode bit mask*/
2284 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2285
2286 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2287#ifdef WLAN_FEATURE_P2P
2288 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002289 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002290#endif
2291 )
2292 {
2293 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2294 pRoamProfile = &pWextState->roamProfile;
2295 LastBSSType = pRoamProfile->BSSType;
2296
2297 switch (type)
2298 {
2299 case NL80211_IFTYPE_STATION:
2300#ifdef WLAN_FEATURE_P2P
2301 case NL80211_IFTYPE_P2P_CLIENT:
2302#endif
2303 hddLog(VOS_TRACE_LEVEL_INFO,
2304 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2305 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002306#ifdef WLAN_FEATURE_11AC
2307 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2308 {
2309 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2310 }
2311#endif
2312 pRoamProfile->phyMode =
2313 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002314 wdev->iftype = type;
2315#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002316 //Check for sub-string p2p to confirm its a p2p interface
2317 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002318 {
2319 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2320 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2321 }
2322 else
2323 {
2324 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002325 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002326 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002327#endif
2328 break;
2329 case NL80211_IFTYPE_ADHOC:
2330 hddLog(VOS_TRACE_LEVEL_INFO,
2331 "%s: setting interface Type to ADHOC", __func__);
2332 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2333 pRoamProfile->phyMode =
2334 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2335 wdev->iftype = type;
2336 break;
2337
2338 case NL80211_IFTYPE_AP:
2339#ifdef WLAN_FEATURE_P2P
2340 case NL80211_IFTYPE_P2P_GO:
2341#endif
2342 {
2343 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2344 "%s: setting interface Type to %s", __func__,
2345 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2346
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002347 //Cancel any remain on channel for GO mode
2348 if (NL80211_IFTYPE_P2P_GO == type)
2349 {
2350 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2351 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002352 if (NL80211_IFTYPE_AP == type)
2353 {
2354 /* As Loading WLAN Driver one interface being created for p2p device
2355 * address. This will take one HW STA and the max number of clients
2356 * that can connect to softAP will be reduced by one. so while changing
2357 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2358 * interface as it is not required in SoftAP mode.
2359 */
2360
2361 // Get P2P Adapter
2362 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2363
2364 if (pP2pAdapter)
2365 {
2366 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2367 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2368 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2369 }
2370 }
2371
Jeff Johnson295189b2012-06-20 16:38:30 -07002372 //De-init the adapter.
2373 hdd_stop_adapter( pHddCtx, pAdapter );
2374 hdd_deinit_adapter( pHddCtx, pAdapter );
2375 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2376#ifdef WLAN_SOFTAP_FEATURE
2377#ifdef WLAN_FEATURE_P2P
2378 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2379 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2380#else
2381 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2382#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002383
2384 //Disable BMPS and IMPS if enabled
2385 //before starting Go
2386 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2387 {
2388 if(VOS_STATUS_E_FAILURE ==
2389 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2390 {
2391 //Fail to Exit BMPS
2392 VOS_ASSERT(0);
2393 }
2394 }
2395
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002396 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2397 (pConfig->apRandomBssidEnabled))
2398 {
2399 /* To meet Android requirements create a randomized
2400 MAC address of the form 02:1A:11:Fx:xx:xx */
2401 get_random_bytes(&ndev->dev_addr[3], 3);
2402 ndev->dev_addr[0] = 0x02;
2403 ndev->dev_addr[1] = 0x1A;
2404 ndev->dev_addr[2] = 0x11;
2405 ndev->dev_addr[3] |= 0xF0;
2406 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2407 VOS_MAC_ADDR_SIZE);
2408 pr_info("wlan: Generated HotSpot BSSID "
2409 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2410 ndev->dev_addr[0],
2411 ndev->dev_addr[1],
2412 ndev->dev_addr[2],
2413 ndev->dev_addr[3],
2414 ndev->dev_addr[4],
2415 ndev->dev_addr[5]);
2416 }
2417
Jeff Johnson295189b2012-06-20 16:38:30 -07002418 hdd_set_ap_ops( pAdapter->dev );
2419
2420 status = hdd_init_ap_mode(pAdapter);
2421 if(status != VOS_STATUS_SUCCESS)
2422 {
2423 hddLog(VOS_TRACE_LEVEL_FATAL,
2424 "%s: Error initializing the ap mode", __func__);
2425 return -EINVAL;
2426 }
2427 hdd_set_conparam(1);
2428
2429#endif
2430 /*interface type changed update in wiphy structure*/
2431 if(wdev)
2432 {
2433 wdev->iftype = type;
2434 pHddCtx->change_iface = type;
2435 }
2436 else
2437 {
2438 hddLog(VOS_TRACE_LEVEL_ERROR,
2439 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2440 return -EINVAL;
2441 }
2442 goto done;
2443 }
2444
2445 default:
2446 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2447 __func__);
2448 return -EOPNOTSUPP;
2449 }
2450 }
2451 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2452#ifdef WLAN_FEATURE_P2P
2453 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2454#endif
2455 )
2456 {
2457 switch(type)
2458 {
2459 case NL80211_IFTYPE_STATION:
2460#ifdef WLAN_FEATURE_P2P
2461 case NL80211_IFTYPE_P2P_CLIENT:
2462#endif
2463 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002464 hdd_stop_adapter( pHddCtx, pAdapter );
2465 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002466 wdev->iftype = type;
2467#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002468 //Check for sub-string p2p to confirm its a p2p interface
2469 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002470 {
2471 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2472 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2473 }
2474 else
2475 {
2476 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002477 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002478 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002479#endif
2480 hdd_set_conparam(0);
2481 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002482 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2483 hdd_set_station_ops( pAdapter->dev );
2484 status = hdd_init_station_mode( pAdapter );
2485 if( VOS_STATUS_SUCCESS != status )
2486 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002487 /* In case of JB, for P2P-GO, only change interface will be called,
2488 * This is the right place to enable back bmps_imps()
2489 */
2490 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002491 goto done;
2492 case NL80211_IFTYPE_AP:
2493#ifdef WLAN_FEATURE_P2P
2494 case NL80211_IFTYPE_P2P_GO:
2495#endif
2496 wdev->iftype = type;
2497#ifdef WLAN_FEATURE_P2P
2498 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2499 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2500#endif
2501 goto done;
2502 default:
2503 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2504 __func__);
2505 return -EOPNOTSUPP;
2506
2507 }
2508
2509 }
2510 else
2511 {
2512 return -EOPNOTSUPP;
2513 }
2514
2515
2516 if(pRoamProfile)
2517 {
2518 if ( LastBSSType != pRoamProfile->BSSType )
2519 {
2520 /*interface type changed update in wiphy structure*/
2521 wdev->iftype = type;
2522
2523 /*the BSS mode changed, We need to issue disconnect
2524 if connected or in IBSS disconnect state*/
2525 if ( hdd_connGetConnectedBssType(
2526 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2527 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2528 {
2529 /*need to issue a disconnect to CSR.*/
2530 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2531 if( eHAL_STATUS_SUCCESS ==
2532 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2533 pAdapter->sessionId,
2534 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2535 {
2536 wait_for_completion_interruptible_timeout(
2537 &pAdapter->disconnect_comp_var,
2538 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2539 }
2540 }
2541 }
2542 }
2543
2544done:
2545 /*set bitmask based on updated value*/
2546 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2547#ifdef WLAN_BTAMP_FEATURE
2548 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2549 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2550 {
2551 //we are ok to do AMP
2552 pHddCtx->isAmpAllowed = VOS_TRUE;
2553 }
2554#endif //WLAN_BTAMP_FEATURE
2555 EXIT();
2556 return 0;
2557}
2558
2559static int wlan_hdd_change_station(struct wiphy *wiphy,
2560 struct net_device *dev,
2561 u8 *mac,
2562 struct station_parameters *params)
2563{
2564 VOS_STATUS status = VOS_STATUS_SUCCESS;
2565 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2566 v_MACADDR_t STAMacAddress;
2567
Jeff Johnsone7245742012-09-05 17:12:55 -07002568 ENTER();
2569
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002570 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2571 {
2572 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2573 "%s:LOGP in Progress. Ignore!!!", __func__);
2574 return -EAGAIN;
2575 }
2576
Jeff Johnson295189b2012-06-20 16:38:30 -07002577 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2578
2579 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2580#ifdef WLAN_FEATURE_P2P
2581 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2582#endif
2583 )
2584 {
2585 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2586 {
2587 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2588 WLANTL_STA_AUTHENTICATED);
2589
2590 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002591 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002592 return -EINVAL;
2593 }
2594 }
2595
Jeff Johnsone7245742012-09-05 17:12:55 -07002596 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002597 return status;
2598}
2599
2600/*
2601 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2602 * This function is used to get peer station index in IBSS mode
2603 */
2604static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2605{
2606 u8 idx = 0;
2607 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2608 ENTER();
2609 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2610 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2611 {
2612 if ( (0 !=
2613 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2614 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2615 temp, VOS_MAC_ADDR_SIZE)
2616 )
2617 {
2618 return idx;
2619 }
2620 }
2621 return idx;
2622}
2623
2624
2625/*
2626 * FUNCTION: wlan_hdd_cfg80211_add_key
2627 * This function is used to initialize the key information
2628 */
2629#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2630static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2631 struct net_device *ndev,
2632 u8 key_index, bool pairwise,
2633 const u8 *mac_addr,
2634 struct key_params *params
2635 )
2636#else
2637static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2638 struct net_device *ndev,
2639 u8 key_index, const u8 *mac_addr,
2640 struct key_params *params
2641 )
2642#endif
2643{
2644 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2645 tCsrRoamSetKey setKey;
2646 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2647 int status = 0;
2648 v_U32_t roamId= 0xFF;
2649 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2650 hdd_hostapd_state_t *pHostapdState;
2651 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002652 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002653
2654 ENTER();
2655
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002656 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2657 {
2658 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2659 "%s:LOGP in Progress. Ignore!!!", __func__);
2660 return -EAGAIN;
2661 }
2662
Jeff Johnson295189b2012-06-20 16:38:30 -07002663 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2664 __func__,pAdapter->device_mode);
2665
2666 if (CSR_MAX_NUM_KEY <= key_index)
2667 {
2668 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2669 key_index);
2670
2671 return -EINVAL;
2672 }
2673
2674 hddLog(VOS_TRACE_LEVEL_INFO,
2675 "%s: called with key index = %d & key length %d",
2676 __func__, key_index, params->key_len);
2677
2678 /*extract key idx, key len and key*/
2679 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2680 setKey.keyId = key_index;
2681 setKey.keyLength = params->key_len;
2682 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2683
2684 switch (params->cipher)
2685 {
2686 case WLAN_CIPHER_SUITE_WEP40:
2687 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2688 break;
2689
2690 case WLAN_CIPHER_SUITE_WEP104:
2691 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2692 break;
2693
2694 case WLAN_CIPHER_SUITE_TKIP:
2695 {
2696 u8 *pKey = &setKey.Key[0];
2697 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2698
2699 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2700
2701 /*Supplicant sends the 32bytes key in this order
2702
2703 |--------------|----------|----------|
2704 | Tk1 |TX-MIC | RX Mic |
2705 |--------------|----------|----------|
2706 <---16bytes---><--8bytes--><--8bytes-->
2707
2708 */
2709 /*Sme expects the 32 bytes key to be in the below order
2710
2711 |--------------|----------|----------|
2712 | Tk1 |RX-MIC | TX Mic |
2713 |--------------|----------|----------|
2714 <---16bytes---><--8bytes--><--8bytes-->
2715 */
2716 /* Copy the Temporal Key 1 (TK1) */
2717 vos_mem_copy(pKey, params->key,16);
2718
2719 /*Copy the rx mic first*/
2720 vos_mem_copy(&pKey[16],&params->key[24],8);
2721
2722 /*Copy the tx mic */
2723 vos_mem_copy(&pKey[24],&params->key[16],8);
2724
2725
2726 break;
2727 }
2728
2729 case WLAN_CIPHER_SUITE_CCMP:
2730 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2731 break;
2732
2733#ifdef FEATURE_WLAN_WAPI
2734 case WLAN_CIPHER_SUITE_SMS4:
2735 {
2736 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2737 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2738 params->key, params->key_len);
2739 return 0;
2740 }
2741#endif
2742#ifdef FEATURE_WLAN_CCX
2743 case WLAN_CIPHER_SUITE_KRK:
2744 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2745 break;
2746#endif
2747 default:
2748 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2749 __func__, params->cipher);
2750 return -EOPNOTSUPP;
2751 }
2752
2753 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2754 __func__, setKey.encType);
2755
2756
2757
2758 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2759#ifdef WLAN_FEATURE_P2P
2760 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2761#endif
2762 )
2763 {
2764
2765
2766 if (
2767#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2768 (!pairwise)
2769#else
2770 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2771#endif
2772 )
2773 {
2774 /* set group key*/
2775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002776 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002777 __func__, __LINE__);
2778 setKey.keyDirection = eSIR_RX_ONLY;
2779 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2780 }
2781 else
2782 {
2783 /* set pairwise key*/
2784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2785 "%s- %d: setting pairwise key",
2786 __func__, __LINE__);
2787 setKey.keyDirection = eSIR_TX_RX;
2788 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2789 }
2790
2791 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2792 if( pHostapdState->bssState == BSS_START )
2793 {
2794 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2795
2796 if ( status != eHAL_STATUS_SUCCESS )
2797 {
2798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2799 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2800 __LINE__, status );
2801 }
2802 }
2803
2804 /* Saving WEP keys */
2805 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2806 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2807 {
2808 //Save the wep key in ap context. Issue setkey after the BSS is started.
2809 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2810 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2811 }
2812 else
2813 {
2814 //Save the key in ap context. Issue setkey after the BSS is started.
2815 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2816 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2817 }
2818 }
2819 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2820#ifdef WLAN_FEATURE_P2P
2821 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2822#endif
2823 )
2824 {
2825 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2826 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2827
2828 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2829
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08002830 pWextState->roamProfile.Keys.defaultIndex = key_index;
2831
2832
Jeff Johnson295189b2012-06-20 16:38:30 -07002833 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2834 params->key, params->key_len);
2835
2836 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2837
2838 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2839 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2840 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2841 )
2842 &&
2843 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2844 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2845 )
2846 )
2847 {
2848 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2849 * interface, copy bssid for pairwise key and group macaddr for
2850 * group key initialization*/
2851
2852 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2853
2854 pWextState->roamProfile.negotiatedUCEncryptionType =
2855 pHddStaCtx->conn_info.ucEncryptionType =
2856 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2857 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2858 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2859
2860
2861 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2862 "%s: Negotiated encryption type %d", __func__,
2863 pWextState->roamProfile.negotiatedUCEncryptionType);
2864
2865 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2866 &pWextState->roamProfile, true);
2867 setKey.keyLength = 0;
2868 setKey.keyDirection = eSIR_TX_RX;
2869
2870#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2871 if (pairwise)
2872 {
2873#endif
2874 if (mac_addr)
2875 {
2876 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2877 }
2878 else
2879 {
2880 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2881 * and peerMacAddress in case of IBSS*/
2882 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2883 {
2884 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2885 if (HDD_MAX_NUM_IBSS_STA != staidx)
2886 {
2887 vos_mem_copy(setKey.peerMac,
2888 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2889 WNI_CFG_BSSID_LEN);
2890
2891 }
2892 else
2893 {
2894 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2895 __func__);
2896 return -EOPNOTSUPP;
2897 }
2898 }
2899 else
2900 {
2901 vos_mem_copy(setKey.peerMac,
2902 &pHddStaCtx->conn_info.bssId[0],
2903 WNI_CFG_BSSID_LEN);
2904 }
2905 }
2906#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2907 }
2908 else
2909 {
2910 /* set group key*/
2911 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2912 "%s- %d: setting Group key",
2913 __func__, __LINE__);
2914 setKey.keyDirection = eSIR_RX_ONLY;
2915 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2916 }
2917#endif
2918 }
2919 else if (
2920#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2921 (!pairwise)
2922#else
2923 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2924#endif
2925 )
2926 {
2927 /* set group key*/
2928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2929 "%s- %d: setting Group key",
2930 __func__, __LINE__);
2931 setKey.keyDirection = eSIR_RX_ONLY;
2932 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2933 }
2934 else
2935 {
2936 /* set pairwise key*/
2937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2938 "%s- %d: setting pairwise key",
2939 __func__, __LINE__);
2940 setKey.keyDirection = eSIR_TX_RX;
2941 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2942 }
2943
2944 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2945 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2946 __func__, setKey.peerMac[0], setKey.peerMac[1],
2947 setKey.peerMac[2], setKey.peerMac[3],
2948 setKey.peerMac[4], setKey.peerMac[5],
2949 setKey.keyDirection);
2950
2951 vos_status = wlan_hdd_check_ula_done(pAdapter);
2952
2953 if ( vos_status != VOS_STATUS_SUCCESS )
2954 {
2955 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2956 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2957 __LINE__, vos_status );
2958
2959 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2960
2961 return -EINVAL;
2962
2963 }
2964
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002965#ifdef WLAN_FEATURE_VOWIFI_11R
2966 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2967 Save the key in the UMAC and include it in the ADD BSS request */
2968 /*TODO 11r - is this used?? */
2969 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2970 if( halStatus == eHAL_STATUS_SUCCESS )
2971 {
2972 return halStatus;
2973 }
2974#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002975
2976 /* issue set key request to SME*/
2977 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2978 pAdapter->sessionId, &setKey, &roamId );
2979
2980 if ( 0 != status )
2981 {
2982 hddLog(VOS_TRACE_LEVEL_ERROR,
2983 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2984 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2985 return -EINVAL;
2986 }
2987
2988
2989 /* in case of IBSS as there was no information available about WEP keys during
2990 * IBSS join, group key intialized with NULL key, so re-initialize group key
2991 * with correct value*/
2992 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2993 !( ( IW_AUTH_KEY_MGMT_802_1X
2994 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2995 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2996 )
2997 &&
2998 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2999 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3000 )
3001 )
3002 {
3003 setKey.keyDirection = eSIR_RX_ONLY;
3004 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3005
3006 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3007 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3008 __func__, setKey.peerMac[0], setKey.peerMac[1],
3009 setKey.peerMac[2], setKey.peerMac[3],
3010 setKey.peerMac[4], setKey.peerMac[5],
3011 setKey.keyDirection);
3012
3013 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3014 pAdapter->sessionId, &setKey, &roamId );
3015
3016 if ( 0 != status )
3017 {
3018 hddLog(VOS_TRACE_LEVEL_ERROR,
3019 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3020 __func__, status);
3021 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3022 return -EINVAL;
3023 }
3024 }
3025 }
3026
3027 return 0;
3028}
3029
3030/*
3031 * FUNCTION: wlan_hdd_cfg80211_get_key
3032 * This function is used to get the key information
3033 */
3034#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3035static int wlan_hdd_cfg80211_get_key(
3036 struct wiphy *wiphy,
3037 struct net_device *ndev,
3038 u8 key_index, bool pairwise,
3039 const u8 *mac_addr, void *cookie,
3040 void (*callback)(void *cookie, struct key_params*)
3041 )
3042#else
3043static int wlan_hdd_cfg80211_get_key(
3044 struct wiphy *wiphy,
3045 struct net_device *ndev,
3046 u8 key_index, const u8 *mac_addr, void *cookie,
3047 void (*callback)(void *cookie, struct key_params*)
3048 )
3049#endif
3050{
3051 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3052 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3053 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3054 struct key_params params;
3055
3056 ENTER();
3057
3058 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3059 __func__,pAdapter->device_mode);
3060
3061 memset(&params, 0, sizeof(params));
3062
3063 if (CSR_MAX_NUM_KEY <= key_index)
3064 {
3065 return -EINVAL;
3066 }
3067
3068 switch(pRoamProfile->EncryptionType.encryptionType[0])
3069 {
3070 case eCSR_ENCRYPT_TYPE_NONE:
3071 params.cipher = IW_AUTH_CIPHER_NONE;
3072 break;
3073
3074 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3075 case eCSR_ENCRYPT_TYPE_WEP40:
3076 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3077 break;
3078
3079 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3080 case eCSR_ENCRYPT_TYPE_WEP104:
3081 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3082 break;
3083
3084 case eCSR_ENCRYPT_TYPE_TKIP:
3085 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3086 break;
3087
3088 case eCSR_ENCRYPT_TYPE_AES:
3089 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3090 break;
3091
3092 default:
3093 params.cipher = IW_AUTH_CIPHER_NONE;
3094 break;
3095 }
3096
3097 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3098 params.seq_len = 0;
3099 params.seq = NULL;
3100 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3101 callback(cookie, &params);
3102 return 0;
3103}
3104
3105/*
3106 * FUNCTION: wlan_hdd_cfg80211_del_key
3107 * This function is used to delete the key information
3108 */
3109#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3110static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3111 struct net_device *ndev,
3112 u8 key_index,
3113 bool pairwise,
3114 const u8 *mac_addr
3115 )
3116#else
3117static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3118 struct net_device *ndev,
3119 u8 key_index,
3120 const u8 *mac_addr
3121 )
3122#endif
3123{
3124 int status = 0;
3125
3126 //This code needs to be revisited. There is sme_removeKey API, we should
3127 //plan to use that. After the change to use correct index in setkey,
3128 //it is observed that this is invalidating peer
3129 //key index whenever re-key is done. This is affecting data link.
3130 //It should be ok to ignore del_key.
3131#if 0
3132 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3133 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3134 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3135 tCsrRoamSetKey setKey;
3136 v_U32_t roamId= 0xFF;
3137
3138 ENTER();
3139
3140 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3141 __func__,pAdapter->device_mode);
3142
3143 if (CSR_MAX_NUM_KEY <= key_index)
3144 {
3145 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3146 key_index);
3147
3148 return -EINVAL;
3149 }
3150
3151 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3152 setKey.keyId = key_index;
3153
3154 if (mac_addr)
3155 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3156 else
3157 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3158
3159 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3160
3161 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3162#ifdef WLAN_FEATURE_P2P
3163 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3164#endif
3165 )
3166 {
3167
3168 hdd_hostapd_state_t *pHostapdState =
3169 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3170 if( pHostapdState->bssState == BSS_START)
3171 {
3172 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3173
3174 if ( status != eHAL_STATUS_SUCCESS )
3175 {
3176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3177 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3178 __LINE__, status );
3179 }
3180 }
3181 }
3182 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3183#ifdef WLAN_FEATURE_P2P
3184 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3185#endif
3186 )
3187 {
3188 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3189
3190 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3191
3192 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3193 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3194 __func__, setKey.peerMac[0], setKey.peerMac[1],
3195 setKey.peerMac[2], setKey.peerMac[3],
3196 setKey.peerMac[4], setKey.peerMac[5]);
3197 if(pAdapter->sessionCtx.station.conn_info.connState ==
3198 eConnectionState_Associated)
3199 {
3200 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3201 pAdapter->sessionId, &setKey, &roamId );
3202
3203 if ( 0 != status )
3204 {
3205 hddLog(VOS_TRACE_LEVEL_ERROR,
3206 "%s: sme_RoamSetKey failure, returned %d",
3207 __func__, status);
3208 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3209 return -EINVAL;
3210 }
3211 }
3212 }
3213#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003214 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003215 return status;
3216}
3217
3218/*
3219 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3220 * This function is used to set the default tx key index
3221 */
3222#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3223static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3224 struct net_device *ndev,
3225 u8 key_index,
3226 bool unicast, bool multicast)
3227#else
3228static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3229 struct net_device *ndev,
3230 u8 key_index)
3231#endif
3232{
3233 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3234 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3235 int status = 0;
3236 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3237
3238 ENTER();
3239
3240 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3241 __func__,pAdapter->device_mode, key_index);
3242
3243 if (CSR_MAX_NUM_KEY <= key_index)
3244 {
3245 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3246 key_index);
3247
3248 return -EINVAL;
3249 }
3250
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003251 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3252 {
3253 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3254 "%s:LOGP in Progress. Ignore!!!", __func__);
3255 return -EAGAIN;
3256 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003257
3258 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3259#ifdef WLAN_FEATURE_P2P
3260 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3261#endif
3262 )
3263 {
3264 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3265 (eCSR_ENCRYPT_TYPE_TKIP !=
3266 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3267 (eCSR_ENCRYPT_TYPE_AES !=
3268 pWextState->roamProfile.EncryptionType.encryptionType[0])
3269 )
3270 {
3271 /* if default key index is not same as previous one,
3272 * then update the default key index */
3273
3274 tCsrRoamSetKey setKey;
3275 v_U32_t roamId= 0xFF;
3276 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3277
3278 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3279 __func__, key_index);
3280
3281 Keys->defaultIndex = (u8)key_index;
3282 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3283 setKey.keyId = key_index;
3284 setKey.keyLength = Keys->KeyLength[key_index];
3285
3286 vos_mem_copy(&setKey.Key[0],
3287 &Keys->KeyMaterial[key_index][0],
3288 Keys->KeyLength[key_index]);
3289
3290 setKey.keyDirection = eSIR_TX_ONLY;
3291
3292 vos_mem_copy(setKey.peerMac,
3293 &pHddStaCtx->conn_info.bssId[0],
3294 WNI_CFG_BSSID_LEN);
3295
3296 setKey.encType =
3297 pWextState->roamProfile.EncryptionType.encryptionType[0];
3298
3299 /* issue set key request */
3300 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3301 pAdapter->sessionId, &setKey, &roamId );
3302
3303 if ( 0 != status )
3304 {
3305 hddLog(VOS_TRACE_LEVEL_ERROR,
3306 "%s: sme_RoamSetKey failed, returned %d", __func__,
3307 status);
3308 return -EINVAL;
3309 }
3310 }
3311 }
3312
3313 /* In SoftAp mode setting key direction for default mode */
3314 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3315 {
3316 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3317 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3318 (eCSR_ENCRYPT_TYPE_AES !=
3319 pWextState->roamProfile.EncryptionType.encryptionType[0])
3320 )
3321 {
3322 /* Saving key direction for default key index to TX default */
3323 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3324 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3325 }
3326 }
3327
3328 return status;
3329}
3330
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003331#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07003332/**
3333 * FUNCTION: wlan_hdd_cfg80211_set_channel
3334 * This function is used to set the channel number
3335 */
3336int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3337 struct ieee80211_channel *chan,
3338 enum nl80211_channel_type channel_type
3339 )
3340{
3341 v_U32_t num_ch = 0;
3342 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003343 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003344 int freq = chan->center_freq; /* freq is in MHZ */
3345
3346 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003347
3348 if( NULL == dev )
3349 {
3350 hddLog(VOS_TRACE_LEVEL_ERROR,
3351 "%s: Called with dev = NULL.\n", __func__);
3352 return -ENODEV;
3353 }
3354 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003355
3356 hddLog(VOS_TRACE_LEVEL_INFO,
3357 "%s: device_mode = %d freq = %d \n",__func__,
3358 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003359 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3360 {
3361 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3362 return -EAGAIN;
3363 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003364
3365 /*
3366 * Do freq to chan conversion
3367 * TODO: for 11a
3368 */
3369
3370 channel = ieee80211_frequency_to_channel(freq);
3371
3372 /* Check freq range */
3373 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3374 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3375 {
3376 hddLog(VOS_TRACE_LEVEL_ERROR,
3377 "%s: Channel [%d] is outside valid range from %d to %d\n",
3378 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3379 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3380 return -EINVAL;
3381 }
3382
3383 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3384
3385 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3386#ifdef WLAN_FEATURE_P2P
3387 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3388#endif
3389 )
3390 {
3391 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3392 {
3393 hddLog(VOS_TRACE_LEVEL_ERROR,
3394 "%s: Invalid Channel [%d] \n", __func__, channel);
3395 return -EINVAL;
3396 }
3397 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3398 "%s: set channel to [%d] for device mode =%d",
3399 __func__, channel,pAdapter->device_mode);
3400 }
3401 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3402#ifdef WLAN_FEATURE_P2P
3403 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3404#endif
3405 )
3406 {
3407 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3408 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3409 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3410
3411 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3412 {
3413 /* Link is up then return cant set channel*/
3414 hddLog( VOS_TRACE_LEVEL_ERROR,
3415 "%s: IBSS Associated, can't set the channel\n", __func__);
3416 return -EINVAL;
3417 }
3418
3419 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3420 pHddStaCtx->conn_info.operationChannel = channel;
3421 pRoamProfile->ChannelInfo.ChannelList =
3422 &pHddStaCtx->conn_info.operationChannel;
3423 }
3424 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3425#ifdef WLAN_FEATURE_P2P
3426 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3427#endif
3428 )
3429 {
3430 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3431
3432 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3433 {
3434 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3435
3436 /* If auto channel selection is configured as enable/ 1 then ignore
3437 channel set by supplicant
3438 */
3439 if ( cfg_param->apAutoChannelSelection )
3440 {
3441 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3442
3443 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3444 "%s: set channel to auto channel (0) for device mode =%d",
3445 __func__, pAdapter->device_mode);
3446 }
3447 }
3448 }
3449 else
3450 {
3451 hddLog(VOS_TRACE_LEVEL_FATAL,
3452 "%s: Invalid device mode failed to set valid channel", __func__);
3453 return -EINVAL;
3454 }
3455 EXIT();
3456 return 0;
3457}
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003458#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003459
3460
3461
3462/*
3463 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3464 * This function is used to inform the BSS details to nl80211 interface.
3465 */
3466static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3467 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3468{
3469 struct net_device *dev = pAdapter->dev;
3470 struct wireless_dev *wdev = dev->ieee80211_ptr;
3471 struct wiphy *wiphy = wdev->wiphy;
3472 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3473 int chan_no;
3474 int ie_length;
3475 const char *ie;
3476 unsigned int freq;
3477 struct ieee80211_channel *chan;
3478 int rssi = 0;
3479 struct cfg80211_bss *bss = NULL;
3480
3481 ENTER();
3482
3483 if( NULL == pBssDesc )
3484 {
3485 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3486 return bss;
3487 }
3488
3489 chan_no = pBssDesc->channelId;
3490 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3491 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3492
3493 if( NULL == ie )
3494 {
3495 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3496 return bss;
3497 }
3498
3499#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3500 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3501 {
3502 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3503 }
3504 else
3505 {
3506 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3507 }
3508#else
3509 freq = ieee80211_channel_to_frequency(chan_no);
3510#endif
3511
3512 chan = __ieee80211_get_channel(wiphy, freq);
3513
3514 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3515 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3516 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3517 if (bss == NULL)
3518 {
3519 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3520
3521 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3522 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3523 pBssDesc->capabilityInfo,
3524 pBssDesc->beaconInterval, ie, ie_length,
3525 rssi, GFP_KERNEL ));
3526}
3527 else
3528 {
3529 return bss;
3530 }
3531}
3532
3533
3534
3535/*
3536 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3537 * This function is used to inform the BSS details to nl80211 interface.
3538 */
3539struct cfg80211_bss*
3540wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3541 tSirBssDescription *bss_desc
3542 )
3543{
3544 /*
3545 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3546 already exists in bss data base of cfg80211 for that particular BSS ID.
3547 Using cfg80211_inform_bss_frame to update the bss entry instead of
3548 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3549 now there is no possibility to get the mgmt(probe response) frame from PE,
3550 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3551 cfg80211_inform_bss_frame.
3552 */
3553 struct net_device *dev = pAdapter->dev;
3554 struct wireless_dev *wdev = dev->ieee80211_ptr;
3555 struct wiphy *wiphy = wdev->wiphy;
3556 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003557#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3558 qcom_ie_age *qie_age = NULL;
3559 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3560#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003561 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003562#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003563 const char *ie =
3564 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3565 unsigned int freq;
3566 struct ieee80211_channel *chan;
3567 struct ieee80211_mgmt *mgmt =
3568 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3569 struct cfg80211_bss *bss_status = NULL;
3570 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3571 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003572#ifdef WLAN_OPEN_SOURCE
3573 struct timespec ts;
3574#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003575
3576 ENTER();
3577
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003578 if (!mgmt)
3579 return NULL;
3580
Jeff Johnson295189b2012-06-20 16:38:30 -07003581 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003582
3583#ifdef WLAN_OPEN_SOURCE
3584 /* Android does not want the timestamp from the frame.
3585 Instead it wants a monotonic increasing value */
3586 get_monotonic_boottime(&ts);
3587 mgmt->u.probe_resp.timestamp =
3588 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3589#else
3590 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003591 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3592 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003593
3594#endif
3595
Jeff Johnson295189b2012-06-20 16:38:30 -07003596 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3597 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003598
3599#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3600 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3601 /* Assuming this is the last IE, copy at the end */
3602 ie_length -=sizeof(qcom_ie_age);
3603 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3604 qie_age->element_id = QCOM_VENDOR_IE_ID;
3605 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3606 qie_age->oui_1 = QCOM_OUI1;
3607 qie_age->oui_2 = QCOM_OUI2;
3608 qie_age->oui_3 = QCOM_OUI3;
3609 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3610 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3611#endif
3612
Jeff Johnson295189b2012-06-20 16:38:30 -07003613 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3614
3615 mgmt->frame_control |=
3616 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3617
3618#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3619 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3620 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3621 {
3622 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3623 }
3624 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3625 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3626
3627 {
3628 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3629 }
3630 else
3631 {
3632 kfree(mgmt);
3633 return NULL;
3634 }
3635#else
3636 freq = ieee80211_channel_to_frequency(chan_no);
3637#endif
3638 chan = __ieee80211_get_channel(wiphy, freq);
3639
3640 /*To keep the rssi icon of the connected AP in the scan window
3641 *and the rssi icon of the wireless networks in sync
3642 * */
3643 if (( eConnectionState_Associated ==
3644 pAdapter->sessionCtx.station.conn_info.connState ) &&
3645 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3646 pAdapter->sessionCtx.station.conn_info.bssId,
3647 WNI_CFG_BSSID_LEN)))
3648 {
3649 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3650 rssi = (pAdapter->rssi * 100);
3651 }
3652 else
3653 {
3654 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3655 }
3656
3657 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3658 frame_len, rssi, GFP_KERNEL);
3659 kfree(mgmt);
3660 return bss_status;
3661}
3662
3663/*
3664 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3665 * This function is used to update the BSS data base of CFG8011
3666 */
3667struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3668 tCsrRoamInfo *pRoamInfo
3669 )
3670{
3671 tCsrRoamConnectedProfile roamProfile;
3672 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3673 struct cfg80211_bss *bss = NULL;
3674
3675 ENTER();
3676
3677 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3678 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3679
3680 if (NULL != roamProfile.pBssDesc)
3681 {
3682 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3683 &roamProfile);
3684
3685 if (NULL == bss)
3686 {
3687 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3688 __func__);
3689 }
3690
3691 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3692 }
3693 else
3694 {
3695 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3696 __func__);
3697 }
3698 return bss;
3699}
3700
3701/*
3702 * FUNCTION: wlan_hdd_cfg80211_update_bss
3703 */
3704static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3705 hdd_adapter_t *pAdapter
3706 )
3707{
3708 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3709 tCsrScanResultInfo *pScanResult;
3710 eHalStatus status = 0;
3711 tScanResultHandle pResult;
3712 struct cfg80211_bss *bss_status = NULL;
3713
3714 ENTER();
3715
3716 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3717 {
3718 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3719 return -EAGAIN;
3720 }
3721
3722 /*
3723 * start getting scan results and populate cgf80211 BSS database
3724 */
3725 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3726
3727 /* no scan results */
3728 if (NULL == pResult)
3729 {
3730 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3731 return status;
3732 }
3733
3734 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3735
3736 while (pScanResult)
3737 {
3738 /*
3739 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3740 * entry already exists in bss data base of cfg80211 for that
3741 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3742 * bss entry instead of cfg80211_inform_bss, But this call expects
3743 * mgmt packet as input. As of now there is no possibility to get
3744 * the mgmt(probe response) frame from PE, converting bss_desc to
3745 * ieee80211_mgmt(probe response) and passing to c
3746 * fg80211_inform_bss_frame.
3747 * */
3748
3749 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3750 &pScanResult->BssDescriptor);
3751
3752
3753 if (NULL == bss_status)
3754 {
3755 hddLog(VOS_TRACE_LEVEL_INFO,
3756 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3757 }
3758 else
3759 {
3760 cfg80211_put_bss(bss_status);
3761 }
3762
3763 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3764 }
3765
3766 sme_ScanResultPurge(hHal, pResult);
3767
3768 return 0;
3769}
3770
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003771void
3772hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3773{
3774 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003775 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3776 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3777 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003778} /****** end hddPrintMacAddr() ******/
3779
3780void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003781hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003782{
3783 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003784 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3785 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3786 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3787 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003788} /****** end hddPrintPmkId() ******/
3789
3790//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3791//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3792
3793//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3794//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3795
3796#define dump_bssid(bssid) \
3797 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003798 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3799 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3800 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003801 }
3802
3803#define dump_pmkid(pMac, pmkid) \
3804 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003805 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3806 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3807 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003808 }
3809
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003810#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003811/*
3812 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3813 * This function is used to notify the supplicant of a new PMKSA candidate.
3814 */
3815int wlan_hdd_cfg80211_pmksa_candidate_notify(
3816 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3817 int index, bool preauth )
3818{
Jeff Johnsone7245742012-09-05 17:12:55 -07003819#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003820 struct net_device *dev = pAdapter->dev;
3821
3822 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003823 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003824
3825 if( NULL == pRoamInfo )
3826 {
3827 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3828 return -EINVAL;
3829 }
3830
3831 dump_bssid(pRoamInfo->bssid);
3832 cfg80211_pmksa_candidate_notify(dev, index,
3833 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003834#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003835 return 0;
3836}
3837#endif //FEATURE_WLAN_LFR
3838
Jeff Johnson295189b2012-06-20 16:38:30 -07003839/*
3840 * FUNCTION: hdd_cfg80211_scan_done_callback
3841 * scanning callback function, called after finishing scan
3842 *
3843 */
3844static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3845 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3846{
3847 struct net_device *dev = (struct net_device *) pContext;
3848 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3849 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003850 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3851 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003852 struct cfg80211_scan_request *req = NULL;
3853 int ret = 0;
3854
3855 ENTER();
3856
3857 hddLog(VOS_TRACE_LEVEL_INFO,
3858 "%s called with halHandle = %p, pContext = %p,"
3859 "scanID = %d, returned status = %d\n",
3860 __func__, halHandle, pContext, (int) scanId, (int) status);
3861
3862 //Block on scan req completion variable. Can't wait forever though.
3863 ret = wait_for_completion_interruptible_timeout(
3864 &pScanInfo->scan_req_completion_event,
3865 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3866 if (!ret)
3867 {
3868 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003869 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003870 }
3871
3872 if(pScanInfo->mScanPending != VOS_TRUE)
3873 {
3874 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003875 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003876 }
3877
3878 /* Check the scanId */
3879 if (pScanInfo->scanId != scanId)
3880 {
3881 hddLog(VOS_TRACE_LEVEL_INFO,
3882 "%s called with mismatched scanId pScanInfo->scanId = %d "
3883 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3884 (int) scanId);
3885 }
3886
Jeff Johnson295189b2012-06-20 16:38:30 -07003887 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3888 pAdapter);
3889
3890 if (0 > ret)
3891 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3892
3893
3894 /* If any client wait scan result through WEXT
3895 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003896 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003897 {
3898 /* The other scan request waiting for current scan finish
3899 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003900 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003901 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003902 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003903 }
3904 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003905 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003906 {
3907 struct net_device *dev = pAdapter->dev;
3908 union iwreq_data wrqu;
3909 int we_event;
3910 char *msg;
3911
3912 memset(&wrqu, '\0', sizeof(wrqu));
3913 we_event = SIOCGIWSCAN;
3914 msg = NULL;
3915 wireless_send_event(dev, we_event, &wrqu, msg);
3916 }
3917 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003918 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003919
3920 /* Get the Scan Req */
3921 req = pAdapter->request;
3922
3923 if (!req)
3924 {
3925 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003926 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003927 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003928 }
3929
3930 /*
3931 * setting up 0, just in case.
3932 */
3933 req->n_ssids = 0;
3934 req->n_channels = 0;
3935 req->ie = 0;
3936
Jeff Johnson295189b2012-06-20 16:38:30 -07003937 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003938 /* Scan is no longer pending */
3939 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003940
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003941 /*
3942 * cfg80211_scan_done informing NL80211 about completion
3943 * of scanning
3944 */
3945 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003946 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003947
Jeff Johnsone7245742012-09-05 17:12:55 -07003948allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003949 /* release the wake lock at the end of the scan*/
3950 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003951
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003952 /* Acquire wakelock to handle the case where APP's tries to suspend
3953 * immediatly after the driver gets connect request(i.e after scan)
3954 * from supplicant, this result in app's is suspending and not able
3955 * to process the connect request to AP */
3956 hdd_allow_suspend_timeout(100);
3957
Jeff Johnson295189b2012-06-20 16:38:30 -07003958 EXIT();
3959 return 0;
3960}
3961
3962/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08003963 * FUNCTION: hdd_isScanAllowed
3964 * Go through each adapter and check if scan allowed
3965 *
3966 */
3967v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
3968{
3969 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3970 hdd_station_ctx_t *pHddStaCtx = NULL;
3971 hdd_adapter_t *pAdapter = NULL;
3972 VOS_STATUS status = 0;
3973 v_U8_t staId = 0;
3974 v_U8_t *staMac = NULL;
3975
3976 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3977
3978 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3979 {
3980 pAdapter = pAdapterNode->pAdapter;
3981
3982 if( pAdapter )
3983 {
3984 hddLog(VOS_TRACE_LEVEL_INFO,
3985 "%s: Adapter with device mode %d exists",
3986 __func__, pAdapter->device_mode);
3987 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3988 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
3989 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
3990 {
3991 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3992 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
3993 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
3994 {
3995 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
3996 hddLog(VOS_TRACE_LEVEL_ERROR,
3997 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
3998 "middle of WPS/EAPOL exchange.", __func__,
3999 staMac[0], staMac[1], staMac[2],
4000 staMac[3], staMac[4], staMac[5]);
4001 return VOS_FALSE;
4002 }
4003 }
4004 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4005 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4006 {
4007 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4008 {
4009 if ((pAdapter->aStaInfo[staId].isUsed) &&
4010 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4011 {
4012 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4013
4014 hddLog(VOS_TRACE_LEVEL_ERROR,
4015 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4016 "middle of WPS/EAPOL exchange.", __func__,
4017 staMac[0], staMac[1], staMac[2],
4018 staMac[3], staMac[4], staMac[5]);
4019 return VOS_FALSE;
4020 }
4021 }
4022 }
4023 }
4024 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4025 pAdapterNode = pNext;
4026 }
4027 hddLog(VOS_TRACE_LEVEL_INFO,
4028 "%s: Scan allowed", __func__);
4029 return VOS_TRUE;
4030}
4031
4032/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004033 * FUNCTION: wlan_hdd_cfg80211_scan
4034 * this scan respond to scan trigger and update cfg80211 scan database
4035 * later, scan dump command can be used to recieve scan results
4036 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004037int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4038#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4039 struct net_device *dev,
4040#endif
4041 struct cfg80211_scan_request *request)
4042{
4043#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4044 struct net_device *dev = request->wdev->netdev;
4045#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004046 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4047 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4048 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4049 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4050 tCsrScanRequest scanRequest;
4051 tANI_U8 *channelList = NULL, i;
4052 v_U32_t scanId = 0;
4053 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004054 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004055#ifdef WLAN_FEATURE_P2P
4056 v_U8_t* pP2pIe = NULL;
4057#endif
4058
4059 ENTER();
4060
4061 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4062 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004063
4064 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4065 (eConnectionState_Connecting ==
4066 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4067 {
4068 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004069 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4070 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004071 return -EBUSY;
4072 }
4073
Jeff Johnson295189b2012-06-20 16:38:30 -07004074#ifdef WLAN_BTAMP_FEATURE
4075 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004076 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004077 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004078 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004079 "%s: No scanning when AMP is on", __func__);
4080 return -EOPNOTSUPP;
4081 }
4082#endif
4083 //Scan on any other interface is not supported.
4084 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4085 {
4086 hddLog(VOS_TRACE_LEVEL_ERROR,
4087 "%s: Not scanning on device_mode = %d",
4088 __func__, pAdapter->device_mode);
4089 return -EOPNOTSUPP;
4090 }
4091
4092 if (TRUE == pScanInfo->mScanPending)
4093 {
4094 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4095 return -EBUSY;
4096 }
4097
4098 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4099 {
4100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4101 "%s:LOGP in Progress. Ignore!!!", __func__);
4102 return -EAGAIN;
4103 }
4104
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004105 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4106 {
4107 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4108 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4109 return -EAGAIN;
4110 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004111 //Don't Allow Scan and return busy if Remain On
4112 //Channel and action frame is pending
4113 //Otherwise Cancel Remain On Channel and allow Scan
4114 //If no action frame pending
4115 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4116 {
4117 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4118 return -EBUSY;
4119 }
4120
Jeff Johnson295189b2012-06-20 16:38:30 -07004121 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4122 {
4123 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004124 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004125 return -EAGAIN;
4126 }
4127 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4128 {
4129 hddLog(VOS_TRACE_LEVEL_WARN,
4130 "%s: MAX TM Level Scan not allowed", __func__);
4131 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4132 return -EBUSY;
4133 }
4134 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4135
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004136 /* Check if scan is allowed at this point of time.
4137 */
4138 if (!hdd_isScanAllowed(pHddCtx))
4139 {
4140 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4141 return -EBUSY;
4142 }
4143
Jeff Johnson295189b2012-06-20 16:38:30 -07004144 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4145
4146 if (NULL != request)
4147 {
4148 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4149 (int)request->n_ssids);
4150
4151 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4152 * Becasue of this, driver is assuming that this is not wildcard scan and so
4153 * is not aging out the scan results.
4154 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004155 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004156 {
4157 request->n_ssids = 0;
4158 }
4159
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004160 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004161 {
4162 tCsrSSIDInfo *SsidInfo;
4163 int j;
4164 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4165 /* Allocate num_ssid tCsrSSIDInfo structure */
4166 SsidInfo = scanRequest.SSIDs.SSIDList =
4167 ( tCsrSSIDInfo *)vos_mem_malloc(
4168 request->n_ssids*sizeof(tCsrSSIDInfo));
4169
4170 if(NULL == scanRequest.SSIDs.SSIDList)
4171 {
4172 hddLog(VOS_TRACE_LEVEL_ERROR,
4173 "memory alloc failed SSIDInfo buffer");
4174 return -ENOMEM;
4175 }
4176
4177 /* copy all the ssid's and their length */
4178 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4179 {
4180 /* get the ssid length */
4181 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4182 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4183 SsidInfo->SSID.length);
4184 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4185 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4186 j, SsidInfo->SSID.ssId);
4187 }
4188 /* set the scan type to active */
4189 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4190 }
4191 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4192 {
4193 /* set the scan type to active */
4194 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4195 }
4196 else
4197 {
4198 /*Set the scan type to default type, in this case it is ACTIVE*/
4199 scanRequest.scanType = pScanInfo->scan_mode;
4200 }
4201 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4202 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4203 }
4204 else
4205 {
4206 /* set the scan type to active */
4207 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4208 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4209
4210 /* set min and max channel time to zero */
4211 scanRequest.minChnTime = 0;
4212 scanRequest.maxChnTime = 0;
4213 }
4214
4215 /* set BSSType to default type */
4216 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4217
4218 /*TODO: scan the requested channels only*/
4219
4220 /*Right now scanning all the channels */
4221 if( request )
4222 {
4223 if( request->n_channels )
4224 {
4225 channelList = vos_mem_malloc( request->n_channels );
4226 if( NULL == channelList )
4227 {
4228 status = -ENOMEM;
4229 goto free_mem;
4230 }
4231
4232 for( i = 0 ; i < request->n_channels ; i++ )
4233 channelList[i] = request->channels[i]->hw_value;
4234 }
4235
4236 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4237 scanRequest.ChannelInfo.ChannelList = channelList;
4238
4239 /* set requestType to full scan */
4240 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004241
4242 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4243 * search (Flush on both full scan and social scan but not on single
4244 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4245 */
4246
4247 /* Supplicant does single channel scan after 8-way handshake
4248 * and in that case driver shoudnt flush scan results. If
4249 * driver flushes the scan results here and unfortunately if
4250 * the AP doesnt respond to our probe req then association
4251 * fails which is not desired
4252 */
4253
4254 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4255 {
4256 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4257 pAdapter->sessionId );
4258 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004259
4260 if( request->ie_len )
4261 {
4262 /* save this for future association (join requires this) */
4263 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4264 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4265 pScanInfo->scanAddIE.length = request->ie_len;
4266
4267 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004268 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4269 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004270 )
4271 {
4272 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4273 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4274 }
4275
4276 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4277 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4278
4279#ifdef WLAN_FEATURE_P2P
4280 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4281 request->ie_len);
4282 if (pP2pIe != NULL)
4283 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004284#ifdef WLAN_FEATURE_P2P_DEBUG
4285 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4286 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4287 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4288 {
4289 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4290 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4291 "Go nego completed to Connection is started");
4292 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4293 "for 8way Handshake");
4294 }
4295 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4296 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4297 {
4298 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4299 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4300 "Disconnected state to Connection is started");
4301 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4302 "for 4way Handshake");
4303 }
4304#endif
4305
Jeff Johnsone7245742012-09-05 17:12:55 -07004306 /* no_cck will be set during p2p find to disable 11b rates */
4307 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004308 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004309 hddLog(VOS_TRACE_LEVEL_INFO,
4310 "%s: This is a P2P Search", __func__);
4311 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004312
Jeff Johnsone7245742012-09-05 17:12:55 -07004313 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4314 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004315 /* set requestType to P2P Discovery */
4316 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004317 }
4318
4319 /*
4320 Skip Dfs Channel in case of P2P Search
4321 if it is set in ini file
4322 */
4323 if(cfg_param->skipDfsChnlInP2pSearch)
4324 {
4325 scanRequest.skipDfsChnlInP2pSearch = 1;
4326 }
4327 else
4328 {
4329 scanRequest.skipDfsChnlInP2pSearch = 0;
4330 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004331
Jeff Johnson295189b2012-06-20 16:38:30 -07004332 }
4333 }
4334#endif
4335 }
4336 }
4337
4338 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4339
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004340 /* acquire the wakelock to avoid the apps suspend during the scan. To
4341 * address the following issues.
4342 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4343 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4344 * for long time, this result in apps running at full power for long time.
4345 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4346 * be stuck in full power because of resume BMPS
4347 */
4348 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004349
4350 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 pAdapter->sessionId, &scanRequest, &scanId,
4352 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004353
Jeff Johnson295189b2012-06-20 16:38:30 -07004354 if (eHAL_STATUS_SUCCESS != status)
4355 {
4356 hddLog(VOS_TRACE_LEVEL_ERROR,
4357 "%s: sme_ScanRequest returned error %d", __func__, status);
4358 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004359 if(eHAL_STATUS_RESOURCES == status)
4360 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004361 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 -07004362 status = -EBUSY;
4363 } else {
4364 status = -EIO;
4365 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004366 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004367 goto free_mem;
4368 }
4369
4370 pScanInfo->mScanPending = TRUE;
4371 pAdapter->request = request;
4372 pScanInfo->scanId = scanId;
4373
4374 complete(&pScanInfo->scan_req_completion_event);
4375
4376free_mem:
4377 if( scanRequest.SSIDs.SSIDList )
4378 {
4379 vos_mem_free(scanRequest.SSIDs.SSIDList);
4380 }
4381
4382 if( channelList )
4383 vos_mem_free( channelList );
4384
4385 EXIT();
4386
4387 return status;
4388}
4389
4390/*
4391 * FUNCTION: wlan_hdd_cfg80211_connect_start
4392 * This function is used to start the association process
4393 */
4394int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004395 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004396{
4397 int status = 0;
4398 hdd_wext_state_t *pWextState;
4399 v_U32_t roamId;
4400 tCsrRoamProfile *pRoamProfile;
4401 eMib_dot11DesiredBssType connectedBssType;
4402 eCsrAuthType RSNAuthType;
4403
4404 ENTER();
4405
4406 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4407
4408 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4409 {
4410 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4411 return -EINVAL;
4412 }
4413
4414 pRoamProfile = &pWextState->roamProfile;
4415
4416 if (pRoamProfile)
4417 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004418 int ret = 0;
4419 hdd_station_ctx_t *pHddStaCtx;
4420 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4421 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4422
4423 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4424 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4425 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004426 {
4427 /* Issue disconnect to CSR */
4428 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4429 if( eHAL_STATUS_SUCCESS ==
4430 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4431 pAdapter->sessionId,
4432 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4433 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004434 ret = wait_for_completion_interruptible_timeout(
4435 &pAdapter->disconnect_comp_var,
4436 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4437 if (0 == ret)
4438 {
4439 VOS_ASSERT(0);
4440 }
4441 }
4442 }
4443 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4444 {
4445 ret = wait_for_completion_interruptible_timeout(
4446 &pAdapter->disconnect_comp_var,
4447 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4448 if (0 == ret)
4449 {
4450 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004451 }
4452 }
4453
4454 if (HDD_WMM_USER_MODE_NO_QOS ==
4455 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4456 {
4457 /*QoS not enabled in cfg file*/
4458 pRoamProfile->uapsd_mask = 0;
4459 }
4460 else
4461 {
4462 /*QoS enabled, update uapsd mask from cfg file*/
4463 pRoamProfile->uapsd_mask =
4464 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4465 }
4466
4467 pRoamProfile->SSIDs.numOfSSIDs = 1;
4468 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4469 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4470 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4471 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4472 ssid, ssid_len);
4473
4474 if (bssid)
4475 {
4476 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4477 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4478 WNI_CFG_BSSID_LEN);
4479 /* Save BSSID in seperate variable as well, as RoamProfile
4480 BSSID is getting zeroed out in the association process. And in
4481 case of join failure we should send valid BSSID to supplicant
4482 */
4483 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4484 WNI_CFG_BSSID_LEN);
4485 }
4486
4487 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4488 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4489 {
4490 /*set gen ie*/
4491 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4492 /*set auth*/
4493 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4494 }
4495 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4496 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4497 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4498 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4499 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4500 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4501 )
4502 {
4503 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4504 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4505 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4506 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4507 eCSR_AUTH_TYPE_AUTOSWITCH;
4508 pWextState->roamProfile.AuthType.authType[0] =
4509 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4510 }
4511#ifdef FEATURE_WLAN_WAPI
4512 if (pAdapter->wapi_info.nWapiMode)
4513 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004514 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004515 switch (pAdapter->wapi_info.wapiAuthMode)
4516 {
4517 case WAPI_AUTH_MODE_PSK:
4518 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004519 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004520 pAdapter->wapi_info.wapiAuthMode);
4521 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4522 break;
4523 }
4524 case WAPI_AUTH_MODE_CERT:
4525 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004526 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004527 pAdapter->wapi_info.wapiAuthMode);
4528 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4529 break;
4530 }
4531 } // End of switch
4532 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4533 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4534 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004535 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004536 pRoamProfile->AuthType.numEntries = 1;
4537 pRoamProfile->EncryptionType.numEntries = 1;
4538 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4539 pRoamProfile->mcEncryptionType.numEntries = 1;
4540 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4541 }
4542 }
4543#endif /* FEATURE_WLAN_WAPI */
4544 pRoamProfile->csrPersona = pAdapter->device_mode;
4545
Jeff Johnson32d95a32012-09-10 13:15:23 -07004546 if( operatingChannel )
4547 {
4548 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4549 pRoamProfile->ChannelInfo.numOfChannels = 1;
4550 }
4551
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004552 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4553 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4554 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4555 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004556 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4557 */
4558 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4559 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4560 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004561
Jeff Johnson295189b2012-06-20 16:38:30 -07004562 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4563 pAdapter->sessionId, pRoamProfile, &roamId);
4564
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004565 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304566 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4567
4568 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004569 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4570 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4571 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304572 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004573 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304574 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004575
4576 pRoamProfile->ChannelInfo.ChannelList = NULL;
4577 pRoamProfile->ChannelInfo.numOfChannels = 0;
4578
Jeff Johnson295189b2012-06-20 16:38:30 -07004579 }
4580 else
4581 {
4582 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4583 return -EINVAL;
4584 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004585 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004586 return status;
4587}
4588
4589/*
4590 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4591 * This function is used to set the authentication type (OPEN/SHARED).
4592 *
4593 */
4594static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4595 enum nl80211_auth_type auth_type)
4596{
4597 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4598 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4599
4600 ENTER();
4601
4602 /*set authentication type*/
4603 switch (auth_type)
4604 {
4605 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4606 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004607#ifdef WLAN_FEATURE_VOWIFI_11R
4608 case NL80211_AUTHTYPE_FT:
4609#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004610 hddLog(VOS_TRACE_LEVEL_INFO,
4611 "%s: set authentication type to OPEN", __func__);
4612 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4613 break;
4614
4615 case NL80211_AUTHTYPE_SHARED_KEY:
4616 hddLog(VOS_TRACE_LEVEL_INFO,
4617 "%s: set authentication type to SHARED", __func__);
4618 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4619 break;
4620#ifdef FEATURE_WLAN_CCX
4621 case NL80211_AUTHTYPE_NETWORK_EAP:
4622 hddLog(VOS_TRACE_LEVEL_INFO,
4623 "%s: set authentication type to CCKM WPA", __func__);
4624 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4625 break;
4626#endif
4627
4628
4629 default:
4630 hddLog(VOS_TRACE_LEVEL_ERROR,
4631 "%s: Unsupported authentication type %d", __func__,
4632 auth_type);
4633 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4634 return -EINVAL;
4635 }
4636
4637 pWextState->roamProfile.AuthType.authType[0] =
4638 pHddStaCtx->conn_info.authType;
4639 return 0;
4640}
4641
4642/*
4643 * FUNCTION: wlan_hdd_set_akm_suite
4644 * This function is used to set the key mgmt type(PSK/8021x).
4645 *
4646 */
4647static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4648 u32 key_mgmt
4649 )
4650{
4651 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4652 ENTER();
4653
4654 /*set key mgmt type*/
4655 switch(key_mgmt)
4656 {
4657 case WLAN_AKM_SUITE_PSK:
4658 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4659 __func__);
4660 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4661 break;
4662
4663 case WLAN_AKM_SUITE_8021X:
4664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4665 __func__);
4666 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4667 break;
4668#ifdef FEATURE_WLAN_CCX
4669#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4670#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4671 case WLAN_AKM_SUITE_CCKM:
4672 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4673 __func__);
4674 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4675 break;
4676#endif
4677
4678 default:
4679 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4680 __func__, key_mgmt);
4681 return -EINVAL;
4682
4683 }
4684 return 0;
4685}
4686
4687/*
4688 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4689 * This function is used to set the encryption type
4690 * (NONE/WEP40/WEP104/TKIP/CCMP).
4691 */
4692static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4693 u32 cipher,
4694 bool ucast
4695 )
4696{
4697 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4698 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4699 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4700
4701 ENTER();
4702
4703 if (!cipher)
4704 {
4705 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4706 __func__, cipher);
4707 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4708 }
4709 else
4710 {
4711
4712 /*set encryption method*/
4713 switch (cipher)
4714 {
4715 case IW_AUTH_CIPHER_NONE:
4716 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4717 break;
4718
4719 case WLAN_CIPHER_SUITE_WEP40:
4720 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4721 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4722 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4723 else
4724 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4725 break;
4726
4727 case WLAN_CIPHER_SUITE_WEP104:
4728 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4729 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4730 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4731 else
4732 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4733 break;
4734
4735 case WLAN_CIPHER_SUITE_TKIP:
4736 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4737 break;
4738
4739 case WLAN_CIPHER_SUITE_CCMP:
4740 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4741 break;
4742#ifdef FEATURE_WLAN_WAPI
4743 case WLAN_CIPHER_SUITE_SMS4:
4744 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4745 break;
4746#endif
4747
4748#ifdef FEATURE_WLAN_CCX
4749 case WLAN_CIPHER_SUITE_KRK:
4750 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4751 break;
4752#endif
4753 default:
4754 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4755 __func__, cipher);
4756 return -EOPNOTSUPP;
4757 }
4758 }
4759
4760 if (ucast)
4761 {
4762 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4763 __func__, encryptionType);
4764 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4765 pWextState->roamProfile.EncryptionType.numEntries = 1;
4766 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4767 encryptionType;
4768 }
4769 else
4770 {
4771 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4772 __func__, encryptionType);
4773 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4774 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4775 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4776 }
4777
4778 return 0;
4779}
4780
4781
4782/*
4783 * FUNCTION: wlan_hdd_cfg80211_set_ie
4784 * This function is used to parse WPA/RSN IE's.
4785 */
4786int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4787 u8 *ie,
4788 size_t ie_len
4789 )
4790{
4791 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4792 u8 *genie = ie;
4793 v_U16_t remLen = ie_len;
4794#ifdef FEATURE_WLAN_WAPI
4795 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4796 u16 *tmp;
4797 v_U16_t akmsuiteCount;
4798 int *akmlist;
4799#endif
4800 ENTER();
4801
4802 /* clear previous assocAddIE */
4803 pWextState->assocAddIE.length = 0;
4804 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4805
4806 while (remLen >= 2)
4807 {
4808 v_U16_t eLen = 0;
4809 v_U8_t elementId;
4810 elementId = *genie++;
4811 eLen = *genie++;
4812 remLen -= 2;
4813
4814 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4815 __func__, elementId, eLen);
4816
4817 switch ( elementId )
4818 {
4819 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004820 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 -07004821 {
4822 hddLog(VOS_TRACE_LEVEL_ERROR,
4823 "%s: Invalid WPA IE", __func__);
4824 return -EINVAL;
4825 }
4826 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4827 {
4828 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4829 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4830 __func__, eLen + 2);
4831
4832 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4833 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004834 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4835 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004836 VOS_ASSERT(0);
4837 return -ENOMEM;
4838 }
4839 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4840 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4841 pWextState->assocAddIE.length += eLen + 2;
4842
4843 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4844 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4845 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4846 }
4847 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4848 {
4849 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4850 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4851 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4852 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4853 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4854 }
4855#ifdef WLAN_FEATURE_P2P
4856 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4857 P2P_OUI_TYPE_SIZE))
4858 /*Consider P2P IE, only for P2P Client */
4859 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4860 {
4861 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4862 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4863 __func__, eLen + 2);
4864
4865 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4866 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004867 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4868 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004869 VOS_ASSERT(0);
4870 return -ENOMEM;
4871 }
4872 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4873 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4874 pWextState->assocAddIE.length += eLen + 2;
4875
4876 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4877 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4878 }
4879#endif
4880#ifdef WLAN_FEATURE_WFD
4881 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4882 WFD_OUI_TYPE_SIZE))
4883 /*Consider WFD IE, only for P2P Client */
4884 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4885 {
4886 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4887 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4888 __func__, eLen + 2);
4889
4890 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4891 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004892 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4893 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004894 VOS_ASSERT(0);
4895 return -ENOMEM;
4896 }
4897 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4898 // WPS IE + P2P IE + WFD IE
4899 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4900 pWextState->assocAddIE.length += eLen + 2;
4901
4902 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4903 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4904 }
4905#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004906 /* Appending HS 2.0 Indication Element in Assiciation Request */
4907 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004908 HS20_OUI_TYPE_SIZE)) )
4909 {
4910 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4911 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4912 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004913
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004914 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4915 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004916 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4917 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004918 VOS_ASSERT(0);
4919 return -ENOMEM;
4920 }
4921 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4922 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004923
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004924 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4925 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4926 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004927
Jeff Johnson295189b2012-06-20 16:38:30 -07004928 break;
4929 case DOT11F_EID_RSN:
4930 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4931 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4932 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4933 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4934 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4935 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004936 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4937 case DOT11F_EID_EXTCAP:
4938 {
4939 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4940 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4941 __func__, eLen + 2);
4942
4943 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4944 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004945 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4946 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004947 VOS_ASSERT(0);
4948 return -ENOMEM;
4949 }
4950 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4951 pWextState->assocAddIE.length += eLen + 2;
4952
4953 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4954 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4955 break;
4956 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004957#ifdef FEATURE_WLAN_WAPI
4958 case WLAN_EID_WAPI:
4959 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4960 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4961 pAdapter->wapi_info.nWapiMode);
4962 tmp = (u16 *)ie;
4963 tmp = tmp + 2; // Skip element Id and Len, Version
4964 akmsuiteCount = WPA_GET_LE16(tmp);
4965 tmp = tmp + 1;
4966 akmlist = (int *)(tmp);
4967 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4968 {
4969 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4970 }
4971 else
4972 {
4973 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4974 VOS_ASSERT(0);
4975 return -EINVAL;
4976 }
4977
4978 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4979 {
4980 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004981 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004982 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
4983 }
4984 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
4985 {
4986 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004987 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004988 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
4989 }
4990 break;
4991#endif
4992 default:
4993 hddLog (VOS_TRACE_LEVEL_ERROR,
4994 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004995 /* when Unknown IE is received we should break and continue
4996 * to the next IE in the buffer instead we were returning
4997 * so changing this to break */
4998 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07004999 }
5000 genie += eLen;
5001 remLen -= eLen;
5002 }
5003 EXIT();
5004 return 0;
5005}
5006
5007/*
5008 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5009 * This function is used to initialize the security
5010 * parameters during connect operation.
5011 */
5012int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5013 struct cfg80211_connect_params *req
5014 )
5015{
5016 int status = 0;
5017 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5018 ENTER();
5019
5020 /*set wpa version*/
5021 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5022
5023 if (req->crypto.wpa_versions)
5024 {
5025 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5026 && ( (req->ie_len)
5027 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5028 // Make sure that it is including a WPA IE.
5029 /* Currently NL is putting WPA version 1 even for open,
5030 * since p2p ie is also put in same buffer.
5031 * */
5032 {
5033 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5034 }
5035 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5036 {
5037 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5038 }
5039 }
5040
5041 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5042 pWextState->wpaVersion);
5043
5044 /*set authentication type*/
5045 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5046
5047 if (0 > status)
5048 {
5049 hddLog(VOS_TRACE_LEVEL_ERROR,
5050 "%s: failed to set authentication type ", __func__);
5051 return status;
5052 }
5053
5054 /*set key mgmt type*/
5055 if (req->crypto.n_akm_suites)
5056 {
5057 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5058 if (0 > status)
5059 {
5060 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5061 __func__);
5062 return status;
5063 }
5064 }
5065
5066 /*set pairwise cipher type*/
5067 if (req->crypto.n_ciphers_pairwise)
5068 {
5069 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5070 req->crypto.ciphers_pairwise[0], true);
5071 if (0 > status)
5072 {
5073 hddLog(VOS_TRACE_LEVEL_ERROR,
5074 "%s: failed to set unicast cipher type", __func__);
5075 return status;
5076 }
5077 }
5078 else
5079 {
5080 /*Reset previous cipher suite to none*/
5081 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5082 if (0 > status)
5083 {
5084 hddLog(VOS_TRACE_LEVEL_ERROR,
5085 "%s: failed to set unicast cipher type", __func__);
5086 return status;
5087 }
5088 }
5089
5090 /*set group cipher type*/
5091 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5092 false);
5093
5094 if (0 > status)
5095 {
5096 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5097 __func__);
5098 return status;
5099 }
5100
5101 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5102 if (req->ie_len)
5103 {
5104 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5105 if ( 0 > status)
5106 {
5107 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5108 __func__);
5109 return status;
5110 }
5111 }
5112
5113 /*incase of WEP set default key information*/
5114 if (req->key && req->key_len)
5115 {
5116 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5117 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5118 )
5119 {
5120 if ( IW_AUTH_KEY_MGMT_802_1X
5121 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5122 {
5123 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5124 __func__);
5125 return -EOPNOTSUPP;
5126 }
5127 else
5128 {
5129 u8 key_len = req->key_len;
5130 u8 key_idx = req->key_idx;
5131
5132 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5133 && (CSR_MAX_NUM_KEY > key_idx)
5134 )
5135 {
5136 hddLog(VOS_TRACE_LEVEL_INFO,
5137 "%s: setting default wep key, key_idx = %hu key_len %hu",
5138 __func__, key_idx, key_len);
5139 vos_mem_copy(
5140 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5141 req->key, key_len);
5142 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5143 (u8)key_len;
5144 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5145 }
5146 }
5147 }
5148 }
5149
5150 return status;
5151}
5152
5153/*
5154 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5155 * This function is used to initialize the security
5156 * parameters during connect operation.
5157 */
5158static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5159 struct net_device *ndev,
5160 struct cfg80211_connect_params *req
5161 )
5162{
5163 int status = 0;
5164 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5165 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5166 hdd_context_t *pHddCtx = NULL;
5167
5168 ENTER();
5169
5170 hddLog(VOS_TRACE_LEVEL_INFO,
5171 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5172
5173 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5174 {
5175 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5176 "%s:LOGP in Progress. Ignore!!!", __func__);
5177 return -EAGAIN;
5178 }
5179
5180#ifdef WLAN_BTAMP_FEATURE
5181 //Infra connect not supported when AMP traffic is on.
5182 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5183 {
5184 hddLog(VOS_TRACE_LEVEL_ERROR,
5185 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005186 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 }
5188#endif
5189 /*initialise security parameters*/
5190 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5191
5192 if ( 0 > status)
5193 {
5194 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5195 __func__);
5196 return status;
5197 }
5198
5199 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005200 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005201 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5202 (vos_concurrent_sessions_running()))
5203 {
5204 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5205
5206 if (NULL != pVosContext)
5207 {
5208 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5209 if(NULL != pHddCtx)
5210 {
5211 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5212 }
5213 }
5214 }
5215
Mohit Khanna765234a2012-09-11 15:08:35 -07005216 if ( req->channel )
5217 {
5218 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5219 req->ssid_len, req->bssid,
5220 req->channel->hw_value);
5221 }
5222 else
5223 {
5224 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5225 req->ssid_len, req->bssid,
5226 0);
5227 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005228
5229 if (0 > status)
5230 {
5231 //ReEnable BMPS if disabled
5232 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5233 (NULL != pHddCtx))
5234 {
5235 //ReEnable Bmps and Imps back
5236 hdd_enable_bmps_imps(pHddCtx);
5237 }
5238
5239 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5240 return status;
5241 }
5242 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5243 EXIT();
5244 return status;
5245}
5246
5247
5248/*
5249 * FUNCTION: wlan_hdd_cfg80211_disconnect
5250 * This function is used to issue a disconnect request to SME
5251 */
5252static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5253 struct net_device *dev,
5254 u16 reason
5255 )
5256{
5257 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5258 tCsrRoamProfile *pRoamProfile =
5259 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5260 int status = 0;
5261 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5262
5263 ENTER();
5264
5265 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5266 __func__,pAdapter->device_mode);
5267
5268 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5269 __func__, reason);
5270
5271 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5272 {
5273 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5274 "%s:LOGP in Progress. Ignore!!!",__func__);
5275 return -EAGAIN;
5276 }
5277 if (NULL != pRoamProfile)
5278 {
5279 /*issue disconnect request to SME, if station is in connected state*/
5280 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5281 {
5282 eCsrRoamDisconnectReason reasonCode =
5283 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5284 switch(reason)
5285 {
5286 case WLAN_REASON_MIC_FAILURE:
5287 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5288 break;
5289
5290 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5291 case WLAN_REASON_DISASSOC_AP_BUSY:
5292 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5293 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5294 break;
5295
5296 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5297 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5298 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5299 break;
5300
5301 case WLAN_REASON_DEAUTH_LEAVING:
5302 default:
5303 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5304 break;
5305 }
5306 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5307 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5308 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5309
5310 /*issue disconnect*/
5311 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5312 pAdapter->sessionId, reasonCode);
5313
5314 if ( 0 != status)
5315 {
5316 hddLog(VOS_TRACE_LEVEL_ERROR,
5317 "%s csrRoamDisconnect failure, returned %d \n",
5318 __func__, (int)status );
5319 return -EINVAL;
5320 }
5321
5322 wait_for_completion_interruptible_timeout(
5323 &pAdapter->disconnect_comp_var,
5324 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5325
5326
5327 /*stop tx queues*/
5328 netif_tx_disable(dev);
5329 netif_carrier_off(dev);
5330 }
5331 }
5332 else
5333 {
5334 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5335 }
5336
5337 return status;
5338}
5339
5340/*
5341 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5342 * This function is used to initialize the security
5343 * settings in IBSS mode.
5344 */
5345static int wlan_hdd_cfg80211_set_privacy_ibss(
5346 hdd_adapter_t *pAdapter,
5347 struct cfg80211_ibss_params *params
5348 )
5349{
5350 int status = 0;
5351 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5352 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5353 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5354
5355 ENTER();
5356
5357 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5358
5359 if (params->ie_len && ( NULL != params->ie) )
5360 {
5361 if (WLAN_EID_RSN == params->ie[0])
5362 {
5363 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5364 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5365 }
5366 else
5367 {
5368 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5369 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5370 }
5371 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5372
5373 if (0 > status)
5374 {
5375 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5376 __func__);
5377 return status;
5378 }
5379 }
5380
5381 pWextState->roamProfile.AuthType.authType[0] =
5382 pHddStaCtx->conn_info.authType =
5383 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5384
5385 if (params->privacy)
5386 {
5387 /* Security enabled IBSS, At this time there is no information available
5388 * about the security paramters, so initialise the encryption type to
5389 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5390 * The correct security parameters will be updated later in
5391 * wlan_hdd_cfg80211_add_key */
5392 /* Hal expects encryption type to be set inorder
5393 *enable privacy bit in beacons */
5394
5395 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5396 }
5397
5398 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5399 pWextState->roamProfile.EncryptionType.numEntries = 1;
5400 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5401
5402 return status;
5403}
5404
5405/*
5406 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5407 * This function is used to create/join an IBSS
5408 */
5409static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5410 struct net_device *dev,
5411 struct cfg80211_ibss_params *params
5412 )
5413{
5414 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5415 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5416 tCsrRoamProfile *pRoamProfile;
5417 int status;
5418 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5419
5420 ENTER();
5421
5422 hddLog(VOS_TRACE_LEVEL_INFO,
5423 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5424
5425 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5426 {
5427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5428 "%s:LOGP in Progress. Ignore!!!", __func__);
5429 return -EAGAIN;
5430 }
5431
5432 if (NULL == pWextState)
5433 {
5434 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5435 __func__);
5436 return -EIO;
5437 }
5438
5439 pRoamProfile = &pWextState->roamProfile;
5440
5441 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5442 {
5443 hddLog (VOS_TRACE_LEVEL_ERROR,
5444 "%s Interface type is not set to IBSS \n", __func__);
5445 return -EINVAL;
5446 }
5447
5448 /* Set Channel */
5449 if (NULL != params->channel)
5450 {
5451 u8 channelNum;
5452 if (IEEE80211_BAND_5GHZ == params->channel->band)
5453 {
5454 hddLog(VOS_TRACE_LEVEL_ERROR,
5455 "%s: IBSS join is called with unsupported band %d",
5456 __func__, params->channel->band);
5457 return -EOPNOTSUPP;
5458 }
5459
5460 /* Get channel number */
5461 channelNum =
5462 ieee80211_frequency_to_channel(params->channel->center_freq);
5463
5464 /*TODO: use macro*/
5465 if (14 >= channelNum)
5466 {
5467 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5468 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5469 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5470 int indx;
5471
5472 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5473 validChan, &numChans))
5474 {
5475 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5476 __func__);
5477 return -EOPNOTSUPP;
5478 }
5479
5480 for (indx = 0; indx < numChans; indx++)
5481 {
5482 if (channelNum == validChan[indx])
5483 {
5484 break;
5485 }
5486 }
5487 if (indx >= numChans)
5488 {
5489 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5490 __func__, channelNum);
5491 return -EINVAL;
5492 }
5493 /* Set the Operational Channel */
5494 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5495 channelNum);
5496 pRoamProfile->ChannelInfo.numOfChannels = 1;
5497 pHddStaCtx->conn_info.operationChannel = channelNum;
5498 pRoamProfile->ChannelInfo.ChannelList =
5499 &pHddStaCtx->conn_info.operationChannel;
5500 }
5501 else
5502 {
5503 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5504 __func__, channelNum);
5505 return -EINVAL;
5506 }
5507 }
5508
5509 /* Initialize security parameters */
5510 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5511 if (status < 0)
5512 {
5513 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5514 __func__);
5515 return status;
5516 }
5517
5518 /* Issue connect start */
5519 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005520 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005521
5522 if (0 > status)
5523 {
5524 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5525 return status;
5526 }
5527
5528 return 0;
5529}
5530
5531/*
5532 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5533 * This function is used to leave an IBSS
5534 */
5535static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5536 struct net_device *dev
5537 )
5538{
5539 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5540 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5541 tCsrRoamProfile *pRoamProfile;
5542
5543 ENTER();
5544
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005545 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5546 {
5547 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5548 "%s:LOGP in Progress. Ignore!!!", __func__);
5549 return -EAGAIN;
5550 }
5551
Jeff Johnson295189b2012-06-20 16:38:30 -07005552 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5553 if (NULL == pWextState)
5554 {
5555 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5556 __func__);
5557 return -EIO;
5558 }
5559
5560 pRoamProfile = &pWextState->roamProfile;
5561
5562 /* Issue disconnect only if interface type is set to IBSS */
5563 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5564 {
5565 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5566 __func__);
5567 return -EINVAL;
5568 }
5569
5570 /* Issue Disconnect request */
5571 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5572 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5573 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5574
5575 return 0;
5576}
5577
5578/*
5579 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5580 * This function is used to set the phy parameters
5581 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5582 */
5583static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5584 u32 changed)
5585{
5586 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5587 tHalHandle hHal = pHddCtx->hHal;
5588
5589 ENTER();
5590
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005591 if ( pHddCtx->isLogpInProgress )
5592 {
5593 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5594 "%s:LOGP in Progress. Ignore!!!", __func__);
5595 return -EAGAIN;
5596 }
5597
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5599 {
5600 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5601 WNI_CFG_RTS_THRESHOLD_STAMAX :
5602 wiphy->rts_threshold;
5603
5604 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5605 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5606 {
5607 hddLog(VOS_TRACE_LEVEL_ERROR,
5608 "%s: Invalid RTS Threshold value %hu",
5609 __func__, rts_threshold);
5610 return -EINVAL;
5611 }
5612
5613 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5614 rts_threshold, ccmCfgSetCallback,
5615 eANI_BOOLEAN_TRUE))
5616 {
5617 hddLog(VOS_TRACE_LEVEL_ERROR,
5618 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5619 __func__, rts_threshold);
5620 return -EIO;
5621 }
5622
5623 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5624 rts_threshold);
5625 }
5626
5627 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5628 {
5629 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5630 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5631 wiphy->frag_threshold;
5632
5633 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5634 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5635 {
5636 hddLog(VOS_TRACE_LEVEL_ERROR,
5637 "%s: Invalid frag_threshold value %hu", __func__,
5638 frag_threshold);
5639 return -EINVAL;
5640 }
5641
5642 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5643 frag_threshold, ccmCfgSetCallback,
5644 eANI_BOOLEAN_TRUE))
5645 {
5646 hddLog(VOS_TRACE_LEVEL_ERROR,
5647 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5648 __func__, frag_threshold);
5649 return -EIO;
5650 }
5651
5652 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5653 frag_threshold);
5654 }
5655
5656 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5657 || (changed & WIPHY_PARAM_RETRY_LONG))
5658 {
5659 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5660 wiphy->retry_short :
5661 wiphy->retry_long;
5662
5663 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5664 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5665 {
5666 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5667 __func__, retry_value);
5668 return -EINVAL;
5669 }
5670
5671 if (changed & WIPHY_PARAM_RETRY_SHORT)
5672 {
5673 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5674 retry_value, ccmCfgSetCallback,
5675 eANI_BOOLEAN_TRUE))
5676 {
5677 hddLog(VOS_TRACE_LEVEL_ERROR,
5678 "%s: ccmCfgSetInt failed for long retry count %hu",
5679 __func__, retry_value);
5680 return -EIO;
5681 }
5682 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5683 __func__, retry_value);
5684 }
5685 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5686 {
5687 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5688 retry_value, ccmCfgSetCallback,
5689 eANI_BOOLEAN_TRUE))
5690 {
5691 hddLog(VOS_TRACE_LEVEL_ERROR,
5692 "%s: ccmCfgSetInt failed for short retry count %hu",
5693 __func__, retry_value);
5694 return -EIO;
5695 }
5696 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5697 __func__, retry_value);
5698 }
5699 }
5700
5701 return 0;
5702}
5703
5704/*
5705 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5706 * This function is used to set the txpower
5707 */
5708static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5709#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5710 enum tx_power_setting type,
5711#else
5712 enum nl80211_tx_power_setting type,
5713#endif
5714 int dbm)
5715{
5716 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5717 tHalHandle hHal = pHddCtx->hHal;
5718 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5719 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5720
5721 ENTER();
5722
5723 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5724 dbm, ccmCfgSetCallback,
5725 eANI_BOOLEAN_TRUE))
5726 {
5727 hddLog(VOS_TRACE_LEVEL_ERROR,
5728 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5729 return -EIO;
5730 }
5731
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005732 if ( pHddCtx->isLogpInProgress )
5733 {
5734 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5735 "%s:LOGP in Progress. Ignore!!!", __func__);
5736 return -EAGAIN;
5737 }
5738
Jeff Johnson295189b2012-06-20 16:38:30 -07005739 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5740 dbm);
5741
5742 switch(type)
5743 {
5744 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5745 /* Fall through */
5746 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5747 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5748 {
5749 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5750 __func__);
5751 return -EIO;
5752 }
5753 break;
5754 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5755 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5756 __func__);
5757 return -EOPNOTSUPP;
5758 break;
5759 default:
5760 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5761 __func__, type);
5762 return -EIO;
5763 }
5764
5765 return 0;
5766}
5767
5768/*
5769 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5770 * This function is used to read the txpower
5771 */
5772static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5773{
5774
5775 hdd_adapter_t *pAdapter;
5776 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5777
Jeff Johnsone7245742012-09-05 17:12:55 -07005778 ENTER();
5779
Jeff Johnson295189b2012-06-20 16:38:30 -07005780 if (NULL == pHddCtx)
5781 {
5782 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5783 *dbm = 0;
5784 return -ENOENT;
5785 }
5786
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005787 if ( pHddCtx->isLogpInProgress )
5788 {
5789 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5790 "%s:LOGP in Progress. Ignore!!!", __func__);
5791 return -EAGAIN;
5792 }
5793
Jeff Johnson295189b2012-06-20 16:38:30 -07005794 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5795 if (NULL == pAdapter)
5796 {
5797 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5798 return -ENOENT;
5799 }
5800
5801 wlan_hdd_get_classAstats(pAdapter);
5802 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5803
Jeff Johnsone7245742012-09-05 17:12:55 -07005804 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 return 0;
5806}
5807
5808static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5809 u8* mac, struct station_info *sinfo)
5810{
5811 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5812 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5813 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5814 tANI_U8 rate_flags;
5815
5816 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5817 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5818 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5819
5820 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5821 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5822 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5823 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5824 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5825 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5826 tANI_U16 maxRate = 0;
5827 tANI_U16 myRate;
5828 tANI_U16 currentRate = 0;
5829 tANI_U8 maxSpeedMCS = 0;
5830 tANI_U8 maxMCSIdx = 0;
5831 tANI_U8 rateFlag = 1;
5832 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005833 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005834
Jeff Johnsone7245742012-09-05 17:12:55 -07005835 ENTER();
5836
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5838 (0 == ssidlen))
5839 {
5840 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5841 " Invalid ssidlen, %d", __func__, ssidlen);
5842 /*To keep GUI happy*/
5843 return 0;
5844 }
5845
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005846 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5847 {
5848 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5849 "%s:LOGP in Progress. Ignore!!!", __func__);
5850 return -EAGAIN;
5851 }
5852
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5854 sinfo->filled |= STATION_INFO_SIGNAL;
5855
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005856 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005857 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5858
5859 //convert to the UI units of 100kbps
5860 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5861
5862#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005863 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 -07005864 sinfo->signal,
5865 pCfg->reportMaxLinkSpeed,
5866 myRate,
5867 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005868 (int) pCfg->linkSpeedRssiMid,
5869 (int) pCfg->linkSpeedRssiLow,
5870 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005871#endif //LINKSPEED_DEBUG_ENABLED
5872
5873 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5874 {
5875 // we do not want to necessarily report the current speed
5876 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5877 {
5878 // report the max possible speed
5879 rssidx = 0;
5880 }
5881 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5882 {
5883 // report the max possible speed with RSSI scaling
5884 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5885 {
5886 // report the max possible speed
5887 rssidx = 0;
5888 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005889 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 {
5891 // report middle speed
5892 rssidx = 1;
5893 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005894 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5895 {
5896 // report middle speed
5897 rssidx = 2;
5898 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005899 else
5900 {
5901 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005902 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005903 }
5904 }
5905 else
5906 {
5907 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5908 hddLog(VOS_TRACE_LEVEL_ERROR,
5909 "%s: Invalid value for reportMaxLinkSpeed: %u",
5910 __func__, pCfg->reportMaxLinkSpeed);
5911 rssidx = 0;
5912 }
5913
5914 maxRate = 0;
5915
5916 /* Get Basic Rate Set */
5917 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5918 for (i = 0; i < ORLeng; i++)
5919 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005920 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005921 {
5922 /* Validate Rate Set */
5923 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5924 {
5925 currentRate = supported_data_rate[j].supported_rate[rssidx];
5926 break;
5927 }
5928 }
5929 /* Update MAX rate */
5930 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5931 }
5932
5933 /* Get Extended Rate Set */
5934 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5935 for (i = 0; i < ERLeng; i++)
5936 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005937 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005938 {
5939 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5940 {
5941 currentRate = supported_data_rate[j].supported_rate[rssidx];
5942 break;
5943 }
5944 }
5945 /* Update MAX rate */
5946 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5947 }
5948
5949 /* Get MCS Rate Set -- but only if we are connected at MCS
5950 rates or if we are always reporting max speed or if we have
5951 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005952 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005953 {
5954 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5955 rateFlag = 0;
5956 if (rate_flags & eHAL_TX_RATE_HT40)
5957 {
5958 rateFlag |= 1;
5959 }
5960 if (rate_flags & eHAL_TX_RATE_SGI)
5961 {
5962 rateFlag |= 2;
5963 }
5964
5965 for (i = 0; i < MCSLeng; i++)
5966 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005967 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5968 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005969 {
5970 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5971 {
5972 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5973 break;
5974 }
5975 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005976 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005977 {
5978 maxRate = currentRate;
5979 maxSpeedMCS = 1;
5980 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
5981 }
5982 }
5983 }
5984
5985 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005986 if (((maxRate < myRate) && (0 == rssidx)) ||
5987 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005988 {
5989 maxRate = myRate;
5990 if (rate_flags & eHAL_TX_RATE_LEGACY)
5991 {
5992 maxSpeedMCS = 0;
5993 }
5994 else
5995 {
5996 maxSpeedMCS = 1;
5997 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
5998 }
5999 }
6000
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006001 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006002 {
6003 sinfo->txrate.legacy = maxRate;
6004#ifdef LINKSPEED_DEBUG_ENABLED
6005 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6006#endif //LINKSPEED_DEBUG_ENABLED
6007 }
6008 else
6009 {
6010 sinfo->txrate.mcs = maxMCSIdx;
6011 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6012 if (rate_flags & eHAL_TX_RATE_SGI)
6013 {
6014 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6015 }
6016 if (rate_flags & eHAL_TX_RATE_HT40)
6017 {
6018 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6019 }
6020#ifdef LINKSPEED_DEBUG_ENABLED
6021 pr_info("Reporting MCS rate %d flags %x\n",
6022 sinfo->txrate.mcs,
6023 sinfo->txrate.flags );
6024#endif //LINKSPEED_DEBUG_ENABLED
6025 }
6026 }
6027 else
6028 {
6029 // report current rate instead of max rate
6030
6031 if (rate_flags & eHAL_TX_RATE_LEGACY)
6032 {
6033 //provide to the UI in units of 100kbps
6034 sinfo->txrate.legacy = myRate;
6035#ifdef LINKSPEED_DEBUG_ENABLED
6036 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6037#endif //LINKSPEED_DEBUG_ENABLED
6038 }
6039 else
6040 {
6041 //must be MCS
6042 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6043 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6044 if (rate_flags & eHAL_TX_RATE_SGI)
6045 {
6046 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6047 }
6048 if (rate_flags & eHAL_TX_RATE_HT40)
6049 {
6050 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6051 }
6052#ifdef LINKSPEED_DEBUG_ENABLED
6053 pr_info("Reporting actual MCS rate %d flags %x\n",
6054 sinfo->txrate.mcs,
6055 sinfo->txrate.flags );
6056#endif //LINKSPEED_DEBUG_ENABLED
6057 }
6058 }
6059 sinfo->filled |= STATION_INFO_TX_BITRATE;
6060
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006061 sinfo->tx_packets =
6062 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6063 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6064 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6065 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6066
6067 sinfo->tx_retries =
6068 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6069 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6070 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6071 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6072
6073 sinfo->tx_failed =
6074 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6075 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6076 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6077 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6078
6079 sinfo->filled |=
6080 STATION_INFO_TX_PACKETS |
6081 STATION_INFO_TX_RETRIES |
6082 STATION_INFO_TX_FAILED;
6083
6084 EXIT();
6085 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006086}
6087
6088static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6089 struct net_device *dev, bool mode, v_SINT_t timeout)
6090{
6091 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6092 VOS_STATUS vos_status;
6093
Jeff Johnsone7245742012-09-05 17:12:55 -07006094 ENTER();
6095
Jeff Johnson295189b2012-06-20 16:38:30 -07006096 if (NULL == pAdapter)
6097 {
6098 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6099 return -ENODEV;
6100 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006101 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6102 {
6103 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6104 "%s:LOGP in Progress. Ignore!!!", __func__);
6105 return -EAGAIN;
6106 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006107
6108 /**The get power cmd from the supplicant gets updated by the nl only
6109 *on successful execution of the function call
6110 *we are oppositely mapped w.r.t mode in the driver
6111 **/
6112 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6113
Jeff Johnsone7245742012-09-05 17:12:55 -07006114 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 if (VOS_STATUS_E_FAILURE == vos_status)
6116 {
6117 return -EINVAL;
6118 }
6119 return 0;
6120}
6121
6122
6123#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6124static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6125 struct net_device *netdev,
6126 u8 key_index)
6127{
Jeff Johnsone7245742012-09-05 17:12:55 -07006128 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006129 return 0;
6130}
6131#endif //LINUX_VERSION_CODE
6132
6133#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6134static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6135 struct net_device *dev,
6136 struct ieee80211_txq_params *params)
6137{
Jeff Johnsone7245742012-09-05 17:12:55 -07006138 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006139 return 0;
6140}
6141#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6142static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6143 struct ieee80211_txq_params *params)
6144{
Jeff Johnsone7245742012-09-05 17:12:55 -07006145 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006146 return 0;
6147}
6148#endif //LINUX_VERSION_CODE
6149
6150static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6151 struct net_device *dev, u8 *mac)
6152{
6153 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006154 VOS_STATUS vos_status;
6155 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006156
Jeff Johnsone7245742012-09-05 17:12:55 -07006157 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006158 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6159 {
6160 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6161 return -EINVAL;
6162 }
6163
6164 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6165 {
6166 hddLog( LOGE,
6167 "%s: Wlan Load/Unload is in progress", __func__);
6168 return -EBUSY;
6169 }
6170
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006171 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6172 {
6173 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6174 "%s:LOGP in Progress. Ignore!!!", __func__);
6175 return -EAGAIN;
6176 }
6177
Jeff Johnson295189b2012-06-20 16:38:30 -07006178 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6179#ifdef WLAN_FEATURE_P2P
6180 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6181#endif
6182 )
6183 {
6184 if( NULL == mac )
6185 {
6186 v_U16_t i;
6187 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6188 {
6189 if(pAdapter->aStaInfo[i].isUsed)
6190 {
6191 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6192 hddLog(VOS_TRACE_LEVEL_INFO,
6193 "%s: Delete STA with MAC::"
6194 "%02x:%02x:%02x:%02x:%02x:%02x",
6195 __func__,
6196 macAddr[0], macAddr[1], macAddr[2],
6197 macAddr[3], macAddr[4], macAddr[5]);
6198 hdd_softap_sta_deauth(pAdapter, macAddr);
6199 }
6200 }
6201 }
6202 else
6203 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006204
6205 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6206 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6207 {
6208 hddLog(VOS_TRACE_LEVEL_INFO,
6209 "%s: Skip this DEL STA as this is not used::"
6210 "%02x:%02x:%02x:%02x:%02x:%02x",
6211 __func__,
6212 mac[0], mac[1], mac[2],
6213 mac[3], mac[4], mac[5]);
6214 return -ENOENT;
6215 }
6216
6217 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6218 {
6219 hddLog(VOS_TRACE_LEVEL_INFO,
6220 "%s: Skip this DEL STA as deauth is in progress::"
6221 "%02x:%02x:%02x:%02x:%02x:%02x",
6222 __func__,
6223 mac[0], mac[1], mac[2],
6224 mac[3], mac[4], mac[5]);
6225 return -ENOENT;
6226 }
6227
6228 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6229
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 hddLog(VOS_TRACE_LEVEL_INFO,
6231 "%s: Delete STA with MAC::"
6232 "%02x:%02x:%02x:%02x:%02x:%02x",
6233 __func__,
6234 mac[0], mac[1], mac[2],
6235 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006236
6237 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6238 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6239 {
6240 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6241 hddLog(VOS_TRACE_LEVEL_INFO,
6242 "%s: STA removal failed for ::"
6243 "%02x:%02x:%02x:%02x:%02x:%02x",
6244 __func__,
6245 mac[0], mac[1], mac[2],
6246 mac[3], mac[4], mac[5]);
6247 return -ENOENT;
6248 }
6249
Jeff Johnson295189b2012-06-20 16:38:30 -07006250 }
6251 }
6252
6253 EXIT();
6254
6255 return 0;
6256}
6257
6258static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6259 struct net_device *dev, u8 *mac, struct station_parameters *params)
6260{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006261#ifdef FEATURE_WLAN_TDLS
6262 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6263 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6264 u32 mask, set;
6265 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006266 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006267
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 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6276 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6277 {
6278 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6279 "TDLS Disabled in INI OR not enabled in FW.\
6280 Cannot process TDLS commands \n");
6281 return -ENOTSUPP;
6282 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006283 /* first to check if we reached to maximum supported TDLS peer.
6284 TODO: for now, return -EPERM looks working fine,
6285 but need to check if any other errno fit into this category.*/
6286 if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
6287 {
6288 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6289 "%s: TDLS Max peer already connected. Request declined. \n",
6290 __func__);
6291 return -EPERM;
6292 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006293
6294 mask = params->sta_flags_mask;
6295
6296 set = params->sta_flags_set;
6297
6298
Lee Hoonkic1262f22013-01-24 21:59:00 -08006299 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6300 "%s: mask 0x%x set 0x%x\n",__func__, mask, set);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006301
6302 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6303 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6305 "Add TDLS peer");
6306
6307
6308 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6309 pAdapter->sessionId, mac);
6310
6311 if (VOS_STATUS_SUCCESS != status) {
6312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6313 "%s: sme_AddTdlsPeerSta failed!", __func__);
6314 }
6315 }
6316 }
6317#endif
6318
Jeff Johnson295189b2012-06-20 16:38:30 -07006319 return 0;
6320}
6321
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006322
6323#ifdef FEATURE_WLAN_LFR
6324static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006325 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006326{
6327#define MAX_PMKSAIDS_IN_CACHE 8
6328 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006329 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006330 tANI_U32 j=0;
6331 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6332 tHalHandle halHandle;
6333 eHalStatus result;
6334 tANI_U8 BSSIDMatched = 0;
6335
Jeff Johnsone7245742012-09-05 17:12:55 -07006336 ENTER();
6337
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006338 // Validate pAdapter
6339 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6340 {
6341 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6342 return -EINVAL;
6343 }
6344
6345 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6346 {
6347 hddLog( LOGE,
6348 "%s: Wlan Load/Unload is in progress", __func__);
6349 return -EBUSY;
6350 }
6351
6352 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6353 {
6354 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6355 "%s:LOGP in Progress. Ignore!!!", __func__);
6356 return -EAGAIN;
6357 }
6358
6359 // Retrieve halHandle
6360 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6361
6362 for (j = 0; j < i; j++)
6363 {
6364 if(vos_mem_compare(PMKIDCache[j].BSSID,
6365 pmksa->bssid, WNI_CFG_BSSID_LEN))
6366 {
6367 /* BSSID matched previous entry. Overwrite it. */
6368 BSSIDMatched = 1;
6369 vos_mem_copy(PMKIDCache[j].BSSID,
6370 pmksa->bssid, WNI_CFG_BSSID_LEN);
6371 vos_mem_copy(PMKIDCache[j].PMKID,
6372 pmksa->pmkid,
6373 CSR_RSN_PMKID_SIZE);
6374 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006375 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006376 dump_bssid(pmksa->bssid);
6377 dump_pmkid(halHandle, pmksa->pmkid);
6378 break;
6379 }
6380 }
6381
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006382 /* Check we compared all entries,if then take the first slot now */
6383 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6384
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006385 if (!BSSIDMatched)
6386 {
6387 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6388 vos_mem_copy(PMKIDCache[i].BSSID,
6389 pmksa->bssid, ETHER_ADDR_LEN);
6390 vos_mem_copy(PMKIDCache[i].PMKID,
6391 pmksa->pmkid,
6392 CSR_RSN_PMKID_SIZE);
6393 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006394 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006395 dump_bssid(pmksa->bssid);
6396 dump_pmkid(halHandle, pmksa->pmkid);
6397 // Increment the HDD Local Cache index
6398 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6399 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6400 }
6401
6402
6403 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6404 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006405 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006406 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006407 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006408 // Finally set the PMKSA ID Cache in CSR
6409 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6410 PMKIDCache,
6411 i );
6412 return 0;
6413}
6414
6415
6416static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006417 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006418{
Jeff Johnsone7245742012-09-05 17:12:55 -07006419 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006420 // TODO: Implement this later.
6421 return 0;
6422}
6423
6424static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6425{
Jeff Johnsone7245742012-09-05 17:12:55 -07006426 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006427 // TODO: Implement this later.
6428 return 0;
6429}
6430#endif
6431
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006432#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6433static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6434 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6435{
6436 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6437 hdd_station_ctx_t *pHddStaCtx;
6438
6439 if (NULL == pAdapter)
6440 {
6441 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6442 return -ENODEV;
6443 }
6444
6445 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6446
6447 // Added for debug on reception of Re-assoc Req.
6448 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6449 {
6450 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6451 ftie->ie_len);
6452 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6453 }
6454
6455#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6456 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6457 ftie->ie_len);
6458#endif
6459
6460 // Pass the received FT IEs to SME
6461 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6462 ftie->ie_len);
6463 return 0;
6464}
6465#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006466
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006467#ifdef FEATURE_WLAN_TDLS
6468static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6469 u8 *peer, u8 action_code, u8 dialog_token,
6470 u16 status_code, const u8 *buf, size_t len)
6471{
6472
6473 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6474 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6475 u8 *buf_1;
6476 size_t len_1 = len;
6477 u8 peerMac[6];
6478 VOS_STATUS status;
6479
6480 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6481 {
6482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6483 "Invalid arguments");
6484 return -EINVAL;
6485 }
6486
6487 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6488 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6489 {
6490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6491 "TDLS Disabled in INI OR not enabled in FW.\
6492 Cannot process TDLS commands \n");
6493 return -ENOTSUPP;
6494 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006495
6496 if(SIR_MAC_TDLS_SETUP_REQ == action_code ||
6497 SIR_MAC_TDLS_SETUP_RSP == action_code )
6498 {
6499 if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
6500 {
6501 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6502 we return error code at 'add_station()'. Hence we have this
6503 check again in addtion to add_station().
6504 Anyway, there is no hard to double-check. */
6505 if(SIR_MAC_TDLS_SETUP_REQ == action_code)
6506 {
6507 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6508 "%s: TDLS Max peer already connected. Request declined. \n",
6509 __func__);
6510 return -EPERM;
6511 }
6512 else
6513 {
6514 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
6515 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6516 "%s: TDLS Max peer already connected send response status %d \n",
6517 __func__,status_code);
6518 }
6519 }
6520 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006521 vos_mem_copy( peerMac, peer, 6);
6522
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006523#ifdef WLAN_FEATURE_TDLS_DEBUG
6524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6525 "%s: %02x:%02x:%02x:%02x:%02x:%02x) action %d, dialog_token %d status %d, len = %d",
6526 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6527 action_code, dialog_token, status_code, len);
6528#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006529
6530 buf_1 = vos_mem_malloc(len);
6531 if(buf_1 == NULL) {
6532 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6533 "%s: malloc failed!", __func__);
6534 return -ENOMEM;
6535 }
6536 vos_mem_copy(buf_1, buf, len);
6537
6538 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6539 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6540
6541 if (VOS_STATUS_SUCCESS != status) {
6542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6543 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6544 }
6545
6546 vos_mem_free(buf_1);
6547
6548 return 0;
6549}
6550
6551static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6552 u8 *peer, enum nl80211_tdls_operation oper)
6553{
6554 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6555 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006556#ifdef WLAN_FEATURE_TDLS_DEBUG
6557 const char *tdls_oper_str[]= {
6558 "NL80211_TDLS_DISCOVERY_REQ",
6559 "NL80211_TDLS_SETUP",
6560 "NL80211_TDLS_TEARDOWN",
6561 "NL80211_TDLS_ENABLE_LINK",
6562 "NL80211_TDLS_DISABLE_LINK",
6563 "NL80211_TDLS_UNKONW_OPER"};
6564#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006565
6566 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6567 {
6568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6569 "Invalid arguments");
6570 return -EINVAL;
6571 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006572
6573#ifdef WLAN_FEATURE_TDLS_DEBUG
6574 if((int)oper > 4)
6575 oper = 5;
6576
6577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6578 "%s: %02x:%02x:%02x:%02x:%02x:%02x: %d (%s) ", "tdls_oper",
6579 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5], (int)oper,
6580 tdls_oper_str[(int)oper]);
6581#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006582
6583 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006584 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006585 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006587 "TDLS Disabled in INI OR not enabled in FW.\
6588 Cannot process TDLS commands \n");
6589 return -ENOTSUPP;
6590 }
6591
6592 switch (oper) {
6593 case NL80211_TDLS_ENABLE_LINK:
6594 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006595 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006596 v_U8_t my_peer[6];
6597 v_U8_t ucSTAId;
6598 VOS_STATUS status;
6599
6600 if (peer) {
6601 vos_mem_copy(my_peer, peer, 6);
6602 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6603
6604 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6605 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6606 __func__, peer[0], peer[1],
6607 peer[2], peer[3],
6608 peer[4], peer[5] );
6609
6610 if (-1 == ucSTAId ) {
6611 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
Hoonki Leef63df0d2013-01-16 19:29:14 -08006612 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006613 }
6614
6615 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6616 WLANTL_STA_AUTHENTICATED );
6617
Hoonki Leef63df0d2013-01-16 19:29:14 -08006618 //This can fail only if the staId is not registered yet with TL
6619 //return -EINVAL in such case.
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006620 if (0 != status) {
6621 hddLog(VOS_TRACE_LEVEL_ERROR,
6622 "%s: WLANTL_ChangeSTAState failed, returned %d",
6623 __func__, status);
Hoonki Leef63df0d2013-01-16 19:29:14 -08006624 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006625 }
Hoonki Leef63df0d2013-01-16 19:29:14 -08006626
Chilam NG571c65a2013-01-19 12:27:36 +05306627 wlan_hdd_tdls_set_link_status(peer, eTDLS_LINK_CONNECTED);
6628
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006629 } else {
6630 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6631 }
6632 }
6633 break;
6634 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08006635 {
6636 if(-1 != wlan_hdd_findTdlsPeer(peer))
6637 {
6638 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6639 pAdapter->sessionId, peer );
6640 }
6641 else
6642 {
6643 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6644 "%s: TDLS Peer Station doesn't exist \n",__func__);
6645 }
6646 return 0;
6647 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006648 case NL80211_TDLS_TEARDOWN:
6649 case NL80211_TDLS_SETUP:
6650 case NL80211_TDLS_DISCOVERY_REQ:
6651 /* We don't support in-driver setup/teardown/discovery */
6652 return -ENOTSUPP;
6653 default:
6654 return -ENOTSUPP;
6655 }
6656 return 0;
6657}
Chilam NG571c65a2013-01-19 12:27:36 +05306658
6659int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
6660 struct net_device *dev, u8 *peer)
6661{
6662 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
6663 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6664
6665 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
6666 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
6667}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006668#endif
6669
Jeff Johnson295189b2012-06-20 16:38:30 -07006670/* cfg80211_ops */
6671static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6672{
6673 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6674 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6675 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6676 .change_station = wlan_hdd_change_station,
6677#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6678 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6679 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6680 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006681#else
6682 .start_ap = wlan_hdd_cfg80211_start_ap,
6683 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6684 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006685#endif
6686 .change_bss = wlan_hdd_cfg80211_change_bss,
6687 .add_key = wlan_hdd_cfg80211_add_key,
6688 .get_key = wlan_hdd_cfg80211_get_key,
6689 .del_key = wlan_hdd_cfg80211_del_key,
6690 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006691#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07006692 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006693#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006694 .scan = wlan_hdd_cfg80211_scan,
6695 .connect = wlan_hdd_cfg80211_connect,
6696 .disconnect = wlan_hdd_cfg80211_disconnect,
6697 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6698 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6699 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6700 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6701 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6702#ifdef WLAN_FEATURE_P2P
6703 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6704 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6705 .mgmt_tx = wlan_hdd_action,
6706#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6707 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6708 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6709 .set_txq_params = wlan_hdd_set_txq_params,
6710#endif
6711#endif
6712 .get_station = wlan_hdd_cfg80211_get_station,
6713 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6714 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006715 .add_station = wlan_hdd_cfg80211_add_station,
6716#ifdef FEATURE_WLAN_LFR
6717 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6718 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6719 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6720#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006721#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6722 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6723#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006724#ifdef FEATURE_WLAN_TDLS
6725 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6726 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6727#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006728};
6729
6730#endif // CONFIG_CFG80211