blob: 252a89b21f4112eba99d5f152d409faaab24493c [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
James Zmuda77fb5ae2013-01-29 08:00:17 -0800532#ifdef FEATURE_WLAN_LFR
533 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
534#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -0800535#ifdef FEATURE_WLAN_TDLS
536 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
537 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
538#endif
539
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700540 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
541 driver can still register regulatory callback and
542 it will get CRDA setting in wiphy->band[], but
543 driver need to determine what to do with both
544 regulatory settings */
545 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700546
Jeff Johnson295189b2012-06-20 16:38:30 -0700547 wiphy->max_scan_ssids = MAX_SCAN_SSID;
548
549 wiphy->max_scan_ie_len = 200 ; //TODO: define a macro
550
551 /* Supports STATION & AD-HOC modes right now */
552 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
553 | BIT(NL80211_IFTYPE_ADHOC)
554#ifdef WLAN_FEATURE_P2P
555 | BIT(NL80211_IFTYPE_P2P_CLIENT)
556 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800557#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 | BIT(NL80211_IFTYPE_AP);
559
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800560#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
561#ifdef WLAN_FEATURE_P2P
562 if( pCfg->enableMCC )
563 {
564 /* Currently, supports up to two channels */
565 wlan_hdd_iface_combination.num_different_channels = 2;
566
567 if( !pCfg->allowMCCGODiffBI )
568 wlan_hdd_iface_combination.beacon_int_infra_match = true;
569
570 }
571 wiphy->iface_combinations = &wlan_hdd_iface_combination;
572 wiphy->n_iface_combinations = 1;
573#endif
574#endif
575
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 /* Before registering we need to update the ht capabilitied based
577 * on ini values*/
578 if( !pCfg->ShortGI20MhzEnable )
579 {
580 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
581 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
582 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
583 }
584
585 if( !pCfg->ShortGI40MhzEnable )
586 {
587 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
588 }
589
590 if( !pCfg->nChannelBondingMode5GHz )
591 {
592 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
593 }
594
595 /*Initialize band capability*/
596 switch(pCfg->nBandCapability)
597 {
598 case eCSR_BAND_24:
599 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
600 break;
601 case eCSR_BAND_5G:
602#ifdef WLAN_FEATURE_P2P
603 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ;
604#endif
605 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
606 break;
607 case eCSR_BAND_ALL:
608 default:
609 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
610 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
611 }
612 /*Initialise the supported cipher suite details*/
613 wiphy->cipher_suites = hdd_cipher_suites;
614 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
615
616 /*signal strength in mBm (100*dBm) */
617 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
618
619#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
620#ifdef WLAN_FEATURE_P2P
621 wiphy->max_remain_on_channel_duration = 1000;
622#endif
623#endif
624
625 /* Register our wiphy dev with cfg80211 */
626 if (0 > wiphy_register(wiphy))
627 {
628 /* print eror */
629 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
630 return -EIO;
631 }
632
633 EXIT();
634 return 0;
635}
636
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700637/* In this function we will try to get default country code from crda.
638 If the gCrdaDefaultCountryCode is configured in ini file,
639 we will try to call user space crda to get the regulatory settings for
640 that country. We will timeout if we can't get it from crda.
641 It's called by hdd_wlan_startup() after wlan_hdd_cfg80211_register.
642*/
643int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg)
644{
645 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
646 if (memcmp(pCfg->crdaDefaultCountryCode,
647 CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0)
648 {
649 init_completion(&pHddCtx->driver_crda_req);
650 regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode);
651 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
652 CRDA_WAIT_TIME);
653 }
654 return 0;
655}
656
Jeff Johnson295189b2012-06-20 16:38:30 -0700657/* In this function we will do all post VOS start initialization.
658 In this function we will register for all frame in which supplicant
659 is interested.
660*/
661void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter)
662{
663#ifdef WLAN_FEATURE_P2P
664 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
665 /* Register for all P2P action, public action etc frames */
666 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
667
Jeff Johnsone7245742012-09-05 17:12:55 -0700668 ENTER();
669
Jeff Johnson295189b2012-06-20 16:38:30 -0700670 /* Right now we are registering these frame when driver is getting
671 initialized. Once we will move to 2.6.37 kernel, in which we have
672 frame register ops, we will move this code as a part of that */
673 /* GAS Initial Request */
674 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
675 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
676
677 /* GAS Initial Response */
678 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
679 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
680
681 /* GAS Comeback Request */
682 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
683 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
684
685 /* GAS Comeback Response */
686 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
687 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
688
689 /* P2P Public Action */
690 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
691 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
692 P2P_PUBLIC_ACTION_FRAME_SIZE );
693
694 /* P2P Action */
695 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
696 (v_U8_t*)P2P_ACTION_FRAME,
697 P2P_ACTION_FRAME_SIZE );
698#endif /* WLAN_FEATURE_P2P */
699}
700
701void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter)
702{
703#ifdef WLAN_FEATURE_P2P
704 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
705 /* Register for all P2P action, public action etc frames */
706 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
707
Jeff Johnsone7245742012-09-05 17:12:55 -0700708 ENTER();
709
Jeff Johnson295189b2012-06-20 16:38:30 -0700710 /* Right now we are registering these frame when driver is getting
711 initialized. Once we will move to 2.6.37 kernel, in which we have
712 frame register ops, we will move this code as a part of that */
713 /* GAS Initial Request */
714
715 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
716 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
717
718 /* GAS Initial Response */
719 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
720 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
721
722 /* GAS Comeback Request */
723 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
724 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
725
726 /* GAS Comeback Response */
727 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
728 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
729
730 /* P2P Public Action */
731 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
732 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
733 P2P_PUBLIC_ACTION_FRAME_SIZE );
734
735 /* P2P Action */
736 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
737 (v_U8_t*)P2P_ACTION_FRAME,
738 P2P_ACTION_FRAME_SIZE );
739#endif /* WLAN_FEATURE_P2P */
740}
741
742#ifdef FEATURE_WLAN_WAPI
743void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
744 const u8 *mac_addr, u8 *key , int key_Len)
745{
746 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
747 tCsrRoamSetKey setKey;
748 v_BOOL_t isConnected = TRUE;
749 int status = 0;
750 v_U32_t roamId= 0xFF;
751 tANI_U8 *pKeyPtr = NULL;
752 int n = 0;
753
754 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
755 __func__,pAdapter->device_mode);
756
757 setKey.keyId = key_index; // Store Key ID
758 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
759 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
760 setKey.paeRole = 0 ; // the PAE role
761 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
762 {
763 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
764 }
765 else
766 {
767 isConnected = hdd_connIsConnected(pHddStaCtx);
768 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
769 }
770 setKey.keyLength = key_Len;
771 pKeyPtr = setKey.Key;
772 memcpy( pKeyPtr, key, key_Len);
773
774 hddLog(VOS_TRACE_LEVEL_INFO,"\n%s: WAPI KEY LENGTH:0x%04x",
775 __func__, key_Len);
776 for (n = 0 ; n < key_Len; n++)
777 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
778 __func__,n,setKey.Key[n]);
779
780 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
781 if ( isConnected )
782 {
783 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
784 pAdapter->sessionId, &setKey, &roamId );
785 }
786 if ( status != 0 )
787 {
788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
789 "[%4d] sme_RoamSetKey returned ERROR status= %d",
790 __LINE__, status );
791 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
792 }
793}
794#endif /* FEATURE_WLAN_WAPI*/
795
796#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
797int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
798 beacon_data_t **ppBeacon,
799 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700800#else
801int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
802 beacon_data_t **ppBeacon,
803 struct cfg80211_beacon_data *params,
804 int dtim_period)
805#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700806{
807 int size;
808 beacon_data_t *beacon = NULL;
809 beacon_data_t *old = NULL;
810 int head_len,tail_len;
811
Jeff Johnsone7245742012-09-05 17:12:55 -0700812 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700813 if (params->head && !params->head_len)
814 return -EINVAL;
815
816 old = pAdapter->sessionCtx.ap.beacon;
817
818 if (!params->head && !old)
819 return -EINVAL;
820
821 if (params->tail && !params->tail_len)
822 return -EINVAL;
823
824#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
825 /* Kernel 3.0 is not updating dtim_period for set beacon */
826 if (!params->dtim_period)
827 return -EINVAL;
828#endif
829
830 if(params->head)
831 head_len = params->head_len;
832 else
833 head_len = old->head_len;
834
835 if(params->tail || !old)
836 tail_len = params->tail_len;
837 else
838 tail_len = old->tail_len;
839
840 size = sizeof(beacon_data_t) + head_len + tail_len;
841
842 beacon = kzalloc(size, GFP_KERNEL);
843
844 if( beacon == NULL )
845 return -ENOMEM;
846
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700847#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700848 if(params->dtim_period || !old )
849 beacon->dtim_period = params->dtim_period;
850 else
851 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700852#else
853 if(dtim_period || !old )
854 beacon->dtim_period = dtim_period;
855 else
856 beacon->dtim_period = old->dtim_period;
857#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700858
859 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
860 beacon->tail = beacon->head + head_len;
861 beacon->head_len = head_len;
862 beacon->tail_len = tail_len;
863
864 if(params->head) {
865 memcpy (beacon->head,params->head,beacon->head_len);
866 }
867 else {
868 if(old)
869 memcpy (beacon->head,old->head,beacon->head_len);
870 }
871
872 if(params->tail) {
873 memcpy (beacon->tail,params->tail,beacon->tail_len);
874 }
875 else {
876 if(old)
877 memcpy (beacon->tail,old->tail,beacon->tail_len);
878 }
879
880 *ppBeacon = beacon;
881
882 kfree(old);
883
884 return 0;
885
886}
Jeff Johnson295189b2012-06-20 16:38:30 -0700887
888v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
889{
890 int left = length;
891 v_U8_t *ptr = pIes;
892 v_U8_t elem_id,elem_len;
893
894 while(left >= 2)
895 {
896 elem_id = ptr[0];
897 elem_len = ptr[1];
898 left -= 2;
899 if(elem_len > left)
900 {
901 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700902 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 eid,elem_len,left);
904 return NULL;
905 }
906 if (elem_id == eid)
907 {
908 return ptr;
909 }
910
911 left -= elem_len;
912 ptr += (elem_len + 2);
913 }
914 return NULL;
915}
916
Jeff Johnson295189b2012-06-20 16:38:30 -0700917/* Check if rate is 11g rate or not */
918static int wlan_hdd_rate_is_11g(u8 rate)
919{
920 u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */
921 u8 i;
922 for (i = 0; i < 8; i++)
923 {
924 if(rate == gRateArray[i])
925 return TRUE;
926 }
927 return FALSE;
928}
929
930/* Check for 11g rate and set proper 11g only mode */
931static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
932 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
933{
934 u8 i, num_rates = pIe[0];
935
936 pIe += 1;
937 for ( i = 0; i < num_rates; i++)
938 {
939 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
940 {
941 /* If rate set have 11g rate than change the mode to 11G */
942 *pSapHw_mode = eSAP_DOT11_MODE_11g;
943 if (pIe[i] & BASIC_RATE_MASK)
944 {
945 /* If we have 11g rate as basic rate, it means mode
946 is 11g only mode.
947 */
948 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
949 *pCheckRatesfor11g = FALSE;
950 }
951 }
952 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
953 {
954 *require_ht = TRUE;
955 }
956 }
957 return;
958}
959
960static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
961{
962 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
963 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
964 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
965 u8 checkRatesfor11g = TRUE;
966 u8 require_ht = FALSE;
967 u8 *pIe=NULL;
968
969 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
970
971 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
972 pBeacon->head_len, WLAN_EID_SUPP_RATES);
973 if (pIe != NULL)
974 {
975 pIe += 1;
976 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
977 &pConfig->SapHw_mode);
978 }
979
980 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
981 WLAN_EID_EXT_SUPP_RATES);
982 if (pIe != NULL)
983 {
984
985 pIe += 1;
986 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
987 &pConfig->SapHw_mode);
988 }
989
990 if( pConfig->channel > 14 )
991 {
992 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
993 }
994
995 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
996 WLAN_EID_HT_CAPABILITY);
997
998 if(pIe)
999 {
1000 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
1001 if(require_ht)
1002 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
1003 }
1004}
1005
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001006#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001007static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1008 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001009#else
1010static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
1011 struct cfg80211_beacon_data *params)
1012#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001013{
1014 v_U8_t *genie;
1015 v_U8_t total_ielen = 0, ielen = 0;
1016 v_U8_t *pIe = NULL;
1017 v_U8_t addIE[1] = {0};
1018 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
Jeff Johnsone7245742012-09-05 17:12:55 -07001019 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001020
1021 genie = vos_mem_malloc(MAX_GENIE_LEN);
1022
1023 if(genie == NULL) {
1024
1025 return -ENOMEM;
1026 }
1027
1028 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1029
1030 if(pIe)
1031 {
1032 /*Copy the wps IE*/
1033 ielen = pIe[1] + 2;
1034 if( ielen <=MAX_GENIE_LEN)
1035 {
1036 vos_mem_copy(genie, pIe, ielen);
1037 }
1038 else
1039 {
1040 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001041 ret = -EINVAL;
1042 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001043 }
1044 total_ielen = ielen;
1045 }
1046
1047#ifdef WLAN_FEATURE_WFD
1048 pIe = wlan_hdd_get_wfd_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1049
1050 if(pIe)
1051 {
1052 ielen = pIe[1] + 2;
1053 if(total_ielen + ielen <= MAX_GENIE_LEN) {
1054 vos_mem_copy(&genie[total_ielen],pIe,(pIe[1] + 2));
1055 }
1056 else {
1057 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie + P2p Ie + Wfd Ie Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001058 ret = -EINVAL;
1059 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001060 }
1061 total_ielen += ielen;
1062 }
1063#endif
1064
1065#ifdef WLAN_FEATURE_P2P
1066 pIe = wlan_hdd_get_p2p_ie_ptr(pBeacon->tail,pBeacon->tail_len);
1067
1068 if(pIe)
1069 {
1070 ielen = pIe[1] + 2;
1071 if(total_ielen + ielen <= MAX_GENIE_LEN)
1072 {
1073 vos_mem_copy(&genie[total_ielen], pIe, (pIe[1] + 2));
1074 }
1075 else
1076 {
1077 hddLog( VOS_TRACE_LEVEL_ERROR,
1078 "**Wps Ie+ P2pIE Length is too big***\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001079 ret = -EINVAL;
1080 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001081 }
1082 total_ielen += ielen;
1083 }
1084#endif
1085
1086 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1087 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
1088 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
1089 {
1090 hddLog(LOGE,
1091 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001092 ret = -EINVAL;
1093 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001094 }
1095
1096 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1097 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
1098 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1099 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1100 ==eHAL_STATUS_FAILURE)
1101 {
1102 hddLog(LOGE,
1103 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001104 ret = -EINVAL;
1105 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 }
1107
1108 // Added for ProResp IE
1109 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
1110 {
1111 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
1112 u8 probe_rsp_ie_len[3] = {0};
1113 u8 counter = 0;
1114 /* Check Probe Resp Length if it is greater then 255 then Store
1115 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
1116 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
1117 Store More then 255 bytes into One Variable.
1118 */
1119 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
1120 {
1121 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
1122 {
1123 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
1124 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
1125 }
1126 else
1127 {
1128 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
1129 rem_probe_resp_ie_len = 0;
1130 }
1131 }
1132
1133 rem_probe_resp_ie_len = 0;
1134
1135 if (probe_rsp_ie_len[0] > 0)
1136 {
1137 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1138 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
1139 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1140 probe_rsp_ie_len[0], NULL,
1141 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1142 {
1143 hddLog(LOGE,
1144 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001145 ret = -EINVAL;
1146 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001147 }
1148 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
1149 }
1150
1151 if (probe_rsp_ie_len[1] > 0)
1152 {
1153 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1154 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
1155 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1156 probe_rsp_ie_len[1], NULL,
1157 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1158 {
1159 hddLog(LOGE,
1160 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001161 ret = -EINVAL;
1162 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 }
1164 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
1165 }
1166
1167 if (probe_rsp_ie_len[2] > 0)
1168 {
1169 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1170 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
1171 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
1172 probe_rsp_ie_len[2], NULL,
1173 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1174 {
1175 hddLog(LOGE,
1176 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001177 ret = -EINVAL;
1178 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 }
1180 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
1181 }
1182
1183 if (probe_rsp_ie_len[1] == 0 )
1184 {
1185 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1186 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1187 eANI_BOOLEAN_FALSE) )
1188 {
1189 hddLog(LOGE,
1190 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1191 }
1192 }
1193
1194 if (probe_rsp_ie_len[2] == 0 )
1195 {
1196 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1197 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1198 eANI_BOOLEAN_FALSE) )
1199 {
1200 hddLog(LOGE,
1201 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1202 }
1203 }
1204
1205 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1206 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
1207 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1208 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1209 == eHAL_STATUS_FAILURE)
1210 {
1211 hddLog(LOGE,
1212 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001213 ret = -EINVAL;
1214 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001215 }
1216 }
1217 else
1218 {
1219 // Reset WNI_CFG_PROBE_RSP Flags
1220 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
1221
1222 hddLog(VOS_TRACE_LEVEL_INFO,
1223 "%s: No Probe Response IE received in set beacon",
1224 __func__);
1225 }
1226
1227 // Added for AssocResp IE
1228 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
1229 {
1230 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1231 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
1232 params->assocresp_ies_len, NULL,
1233 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
1234 {
1235 hddLog(LOGE,
1236 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001237 ret = -EINVAL;
1238 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001239 }
1240
1241 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1242 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
1243 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
1244 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
1245 == eHAL_STATUS_FAILURE)
1246 {
1247 hddLog(LOGE,
1248 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07001249 ret = -EINVAL;
1250 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07001251 }
1252 }
1253 else
1254 {
1255 hddLog(VOS_TRACE_LEVEL_INFO,
1256 "%s: No Assoc Response IE received in set beacon",
1257 __func__);
1258
1259 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1260 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
1261 eANI_BOOLEAN_FALSE) )
1262 {
1263 hddLog(LOGE,
1264 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
1265 }
1266 }
1267
Jeff Johnsone7245742012-09-05 17:12:55 -07001268done:
Jeff Johnson295189b2012-06-20 16:38:30 -07001269 vos_mem_free(genie);
1270 return 0;
1271}
Jeff Johnson295189b2012-06-20 16:38:30 -07001272
1273/*
1274 * FUNCTION: wlan_hdd_validate_operation_channel
1275 * called by wlan_hdd_cfg80211_start_bss() and
1276 * wlan_hdd_cfg80211_set_channel()
1277 * This function validates whether given channel is part of valid
1278 * channel list.
1279 */
1280static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
1281{
1282
1283 v_U32_t num_ch = 0;
1284 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
1285 u32 indx = 0;
1286 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1287
1288 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
1289
1290 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
1291 valid_ch, &num_ch))
1292 {
1293 hddLog(VOS_TRACE_LEVEL_ERROR,
1294 "%s: failed to get valid channel list\n", __func__);
1295 return VOS_STATUS_E_FAILURE;
1296 }
1297
1298 for (indx = 0; indx < num_ch; indx++)
1299 {
1300 if (channel == valid_ch[indx])
1301 {
1302 break;
1303 }
1304 }
1305
1306 if (indx >= num_ch)
1307 {
1308 hddLog(VOS_TRACE_LEVEL_ERROR,
1309 "%s: Invalid Channel [%d] \n", __func__, channel);
1310 return VOS_STATUS_E_FAILURE;
1311 }
1312 return VOS_STATUS_SUCCESS;
1313
1314}
1315
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301316/*
1317 * FUNCTION: wlan_hdd_select_cbmode
1318 * called by wlan_hdd_cfg80211_start_bss() and
1319 * This function selects the cbmode based on primary channel
1320 */
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001321VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel)
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301322{
1323 tSmeConfigParams smeConfig;
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001324 hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter;
1325 hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini;
1326
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301327 if(
1328#ifdef WLAN_FEATURE_11AC
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001329 SapHw_mode != eSAP_DOT11_MODE_11ac &&
1330 SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY &&
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301331#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001332 SapHw_mode != eSAP_DOT11_MODE_11n &&
1333 SapHw_mode != eSAP_DOT11_MODE_11n_ONLY
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301334 )
1335 {
1336 return VOS_STATUS_SUCCESS;
1337 }
1338
1339 if (!pConfigIni->nChannelBondingMode5GHz) {
1340 return VOS_STATUS_SUCCESS;
1341 }
1342
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001343 //channel = pSapConfig->channel;
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301344 vos_mem_zero(&smeConfig, sizeof (tSmeConfigParams));
1345
1346 sme_GetConfigParam(pHddCtx->hHal, &smeConfig);
1347
1348#ifdef WLAN_FEATURE_11AC
1349
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001350 if ( SapHw_mode == eSAP_DOT11_MODE_11ac ||
1351 SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301352 {
1353 if ( channel== 36 || channel == 52 || channel == 100 ||
1354 channel == 116 || channel == 149 )
1355 {
1356 smeConfig.csrConfig.channelBondingMode5GHz =
1357 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
1358 }
1359 else if ( channel == 40 || channel == 56 || channel == 104 ||
1360 channel == 120 || channel == 153 )
1361 {
1362 smeConfig.csrConfig.channelBondingMode5GHz =
1363 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
1364 }
1365 else if ( channel == 44 || channel == 60 || channel == 108 ||
1366 channel == 124 || channel == 157 )
1367 {
1368 smeConfig.csrConfig.channelBondingMode5GHz =
1369 PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1;
1370 }
1371 else if ( channel == 48 || channel == 64 || channel == 112 ||
1372 channel == 128 || channel == 161 )
1373 {
1374 smeConfig.csrConfig.channelBondingMode5GHz =
1375 PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
1376 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301377 }
1378#endif
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001379 if ( SapHw_mode == eSAP_DOT11_MODE_11n ||
1380 SapHw_mode == eSAP_DOT11_MODE_11n_ONLY )
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301381 {
1382 if ( channel== 40 || channel == 48 || channel == 56 ||
1383 channel == 64 || channel == 104 || channel == 112 ||
1384 channel == 120 || channel == 128 || channel == 136 ||
1385 channel == 144 || channel == 153 || channel == 161 )
1386 {
1387 smeConfig.csrConfig.channelBondingMode5GHz = 1;
1388 }
1389 else if ( channel== 36 || channel == 44 || channel == 52 ||
1390 channel == 60 || channel == 100 || channel == 108 ||
1391 channel == 116 || channel == 124 || channel == 132 ||
1392 channel == 140 || channel == 149 || channel == 157 )
1393 {
1394 smeConfig.csrConfig.channelBondingMode5GHz = 2;
1395 }
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301396 }
1397 pr_info ("cbmode selected=%ld\n",smeConfig.csrConfig.channelBondingMode5GHz);
1398
1399 sme_UpdateConfig (pHddCtx->hHal,&smeConfig);
1400 return VOS_STATUS_SUCCESS;
1401}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001402
Jeff Johnson295189b2012-06-20 16:38:30 -07001403#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1404static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1405 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001406#else
1407static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
1408 struct cfg80211_beacon_data *params,
1409 const u8 *ssid, size_t ssid_len,
1410 enum nl80211_hidden_ssid hidden_ssid)
1411#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001412{
1413 tsap_Config_t *pConfig;
1414 beacon_data_t *pBeacon = NULL;
1415 struct ieee80211_mgmt *pMgmt_frame;
1416 v_U8_t *pIe=NULL;
1417 v_U16_t capab_info;
1418 eCsrAuthType RSNAuthType;
1419 eCsrEncryptionType RSNEncryptType;
1420 eCsrEncryptionType mcRSNEncryptType;
1421 int status = VOS_STATUS_SUCCESS;
1422 tpWLAN_SAPEventCB pSapEventCallback;
1423 hdd_hostapd_state_t *pHostapdState;
1424 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
1425 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
1426 struct qc_mac_acl_entry *acl_entry = NULL;
1427 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001428 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001429
1430 ENTER();
1431
1432 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
1433
1434 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
1435
1436 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
1437
1438 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
1439
1440 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
1441
1442 //channel is already set in the set_channel Call back
1443 //pConfig->channel = pCommitConfig->channel;
1444
1445 /*Protection parameter to enable or disable*/
1446 pConfig->protEnabled =
1447 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
1448
1449 pConfig->dtim_period = pBeacon->dtim_period;
1450
1451 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***\n",
1452 pConfig->dtim_period);
1453
1454
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08001455 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07001456 {
1457 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07001458 WLAN_EID_COUNTRY);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001459 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07001460 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001461 tANI_BOOLEAN restartNeeded;
1462 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
1463 pConfig->ieee80211d = 1;
1464 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
1465 sme_setRegInfo(hHal, pConfig->countryCode);
1466 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
1467 /*
1468 * If auto channel is configured i.e. channel is 0,
1469 * so skip channel validation.
1470 */
1471 if( AUTO_CHANNEL_SELECT != pConfig->channel )
Jeff Johnson295189b2012-06-20 16:38:30 -07001472 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07001473 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
1474 {
1475 hddLog(VOS_TRACE_LEVEL_ERROR,
1476 "%s: Invalid Channel [%d] \n", __func__, pConfig->channel);
1477 return -EINVAL;
1478 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001479 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001480 /*
1481 * Validate the given channel range for the given country code
1482 */
1483 else
1484 {
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001485 if(1 != pHddCtx->is_dynamic_channel_range_set)
Ng Chilamfc416462012-12-27 17:26:52 -08001486 {
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001487 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001488 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
Ng Chilamfc416462012-12-27 17:26:52 -08001489 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08001490 }
Gopichand Nakkalaf7e53c52013-01-07 14:52:52 -08001491
Ng Chilamfc416462012-12-27 17:26:52 -08001492 pHddCtx->is_dynamic_channel_range_set = 0;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001493 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001494 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001495 else
1496 {
1497 pConfig->ieee80211d = 0;
1498 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001499 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001500 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001501 {
1502 pConfig->ieee80211d = 0;
1503 }
1504 pConfig->authType = eSAP_AUTO_SWITCH;
1505
1506 capab_info = pMgmt_frame->u.beacon.capab_info;
1507
1508 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
1509 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
1510
1511 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
1512
1513 /*Set wps station to configured*/
1514 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
1515
1516 if(pIe)
1517 {
1518 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
1519 {
1520 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***\n");
1521 return -EINVAL;
1522 }
1523 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
1524 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001525 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07001526 /* Check 15 bit of WPS IE as it contain information for wps state
1527 * WPS state
1528 */
1529 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
1530 {
1531 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
1532 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
1533 {
1534 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
1535 }
1536 }
1537 }
1538 else
1539 {
1540 pConfig->wps_state = SAP_WPS_DISABLED;
1541 }
1542 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
1543
1544 pConfig->RSNWPAReqIELength = 0;
1545 pConfig->pRSNWPAReqIE = NULL;
1546 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
1547 WLAN_EID_RSN);
1548 if(pIe && pIe[1])
1549 {
1550 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1551 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1552 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1553 /* The actual processing may eventually be more extensive than
1554 * this. Right now, just consume any PMKIDs that are sent in
1555 * by the app.
1556 * */
1557 status = hdd_softap_unpackIE(
1558 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1559 &RSNEncryptType,
1560 &mcRSNEncryptType,
1561 &RSNAuthType,
1562 pConfig->pRSNWPAReqIE[1]+2,
1563 pConfig->pRSNWPAReqIE );
1564
1565 if( VOS_STATUS_SUCCESS == status )
1566 {
1567 /* Now copy over all the security attributes you have
1568 * parsed out
1569 * */
1570 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1571 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1572 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1573 = RSNEncryptType;
1574 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1575 "EncryptionType = %d mcEncryptionType = %d\n"),
1576 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1577 }
1578 }
1579
1580 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1581 pBeacon->tail, pBeacon->tail_len);
1582
1583 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
1584 {
1585 if (pConfig->pRSNWPAReqIE)
1586 {
1587 /*Mixed mode WPA/WPA2*/
1588 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
1589 pConfig->RSNWPAReqIELength += pIe[1] + 2;
1590 }
1591 else
1592 {
1593 pConfig->RSNWPAReqIELength = pIe[1] + 2;
1594 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
1595 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
1596 status = hdd_softap_unpackIE(
1597 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
1598 &RSNEncryptType,
1599 &mcRSNEncryptType,
1600 &RSNAuthType,
1601 pConfig->pRSNWPAReqIE[1]+2,
1602 pConfig->pRSNWPAReqIE );
1603
1604 if( VOS_STATUS_SUCCESS == status )
1605 {
1606 /* Now copy over all the security attributes you have
1607 * parsed out
1608 * */
1609 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
1610 pConfig->mcRSNEncryptType = mcRSNEncryptType;
1611 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
1612 = RSNEncryptType;
1613 hddLog( LOG1, FL("%s: CSR AuthType = %d, "
1614 "EncryptionType = %d mcEncryptionType = %d\n"),
1615 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
1616 }
1617 }
1618 }
1619
1620 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
1621
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001622#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001623 if (params->ssid != NULL)
1624 {
1625 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
1626 pConfig->SSIDinfo.ssid.length = params->ssid_len;
1627 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1628 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1629 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001630#else
1631 if (ssid != NULL)
1632 {
1633 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
1634 pConfig->SSIDinfo.ssid.length = ssid_len;
1635 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1636 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
1637 }
1638#endif
1639
Jeff Johnson295189b2012-06-20 16:38:30 -07001640 vos_mem_copy(pConfig->self_macaddr.bytes,
1641 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1642
1643 /* default value */
1644 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
1645 pConfig->num_accept_mac = 0;
1646 pConfig->num_deny_mac = 0;
1647
1648 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1649 pBeacon->tail, pBeacon->tail_len);
1650
1651 /* pIe for black list is following form:
1652 type : 1 byte
1653 length : 1 byte
1654 OUI : 4 bytes
1655 acl type : 1 byte
1656 no of mac addr in black list: 1 byte
1657 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1658 */
1659 if ((pIe != NULL) && (pIe[1] != 0))
1660 {
1661 pConfig->SapMacaddr_acl = pIe[6];
1662 pConfig->num_deny_mac = pIe[7];
1663 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n",
1664 pIe[6], pIe[7]);
1665 if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED)
1666 pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED;
1667 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1668 for (i = 0; i < pConfig->num_deny_mac; i++)
1669 {
1670 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1671 acl_entry++;
1672 }
1673 }
1674 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
1675 pBeacon->tail, pBeacon->tail_len);
1676
1677 /* pIe for white list is following form:
1678 type : 1 byte
1679 length : 1 byte
1680 OUI : 4 bytes
1681 acl type : 1 byte
1682 no of mac addr in white list: 1 byte
1683 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
1684 */
1685 if ((pIe != NULL) && (pIe[1] != 0))
1686 {
1687 pConfig->SapMacaddr_acl = pIe[6];
1688 pConfig->num_accept_mac = pIe[7];
1689 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n",
1690 pIe[6], pIe[7]);
1691 if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED)
1692 pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED;
1693 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
1694 for (i = 0; i < pConfig->num_accept_mac; i++)
1695 {
1696 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
1697 acl_entry++;
1698 }
1699 }
1700 wlan_hdd_set_sapHwmode(pHostapdAdapter);
1701
Jeff Johnsone7245742012-09-05 17:12:55 -07001702#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08001703 /* Overwrite the hostapd setting for HW mode only for 11ac.
1704 * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini .
1705 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */
1706 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
1707 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
1708 (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
1709 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) ||
1710 ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07001711 {
1712 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
1713 }
1714#endif
Madan Mohan Koyyalamudi59381622012-11-28 01:56:47 +05301715
Madan Mohan Koyyalamudi527935a2012-12-04 16:41:16 -08001716 if( AUTO_CHANNEL_SELECT != pConfig->channel)
1717 wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001718 // ht_capab is not what the name conveys,this is used for protection bitmap
1719 pConfig->ht_capab =
1720 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
1721
1722 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
1723 {
1724 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
1725 return -EINVAL;
1726 }
1727
1728 //Uapsd Enabled Bit
1729 pConfig->UapsdEnable =
1730 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
1731 //Enable OBSS protection
1732 pConfig->obssProtEnabled =
1733 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
1734
1735 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"),
1736 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
1737 hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId);
1738 hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int,
1739 (int)pConfig->channel);
1740 hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode);
1741 hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy,
1742 pConfig->authType);
1743 hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength);
1744 hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable);
1745 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"),
1746 pConfig->protEnabled, pConfig->obssProtEnabled);
1747
1748 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
1749 {
1750 //Bss already started. just return.
1751 //TODO Probably it should update some beacon params.
1752 hddLog( LOGE, "Bss Already started...Ignore the request");
1753 EXIT();
1754 return 0;
1755 }
1756
1757 pConfig->persona = pHostapdAdapter->device_mode;
1758
1759 pSapEventCallback = hdd_hostapd_SAPEventCB;
1760 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
1761 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
1762 {
1763 hddLog(LOGE,FL("SAP Start Bss fail\n"));
1764 return -EINVAL;
1765 }
1766
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001767 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07001768 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
1769
1770 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1771
1772 if (!VOS_IS_STATUS_SUCCESS(status))
1773 {
1774 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1775 ("ERROR: HDD vos wait for single_event failed!!\n"));
1776 VOS_ASSERT(0);
1777 }
1778
1779 //Succesfully started Bss update the state bit.
1780 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
1781
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001782#ifdef WLAN_FEATURE_P2P_DEBUG
1783 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
1784 {
1785 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
1786 {
1787 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1788 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001789 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001790 }
1791 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
1792 {
1793 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
1794 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001795 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001796 }
1797 }
1798#endif
1799
Jeff Johnson295189b2012-06-20 16:38:30 -07001800 pHostapdState->bCommit = TRUE;
1801 EXIT();
1802
1803 return 0;
1804}
1805
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001806#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001807static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
1808 struct net_device *dev,
1809 struct beacon_parameters *params)
1810{
1811 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1812 int status=VOS_STATUS_SUCCESS;
1813
1814 ENTER();
1815
1816 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode);
1817
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001818 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1819 {
1820 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1821 "%s:LOGP in Progress. Ignore!!!", __func__);
1822 return -EAGAIN;
1823 }
1824
Jeff Johnson295189b2012-06-20 16:38:30 -07001825 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
1826#ifdef WLAN_FEATURE_P2P
1827 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1828#endif
1829 )
1830 {
1831 beacon_data_t *old,*new;
1832
1833 old = pAdapter->sessionCtx.ap.beacon;
1834
1835 if (old)
1836 return -EALREADY;
1837
1838 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1839
1840 if(status != VOS_STATUS_SUCCESS)
1841 {
1842 hddLog(VOS_TRACE_LEVEL_FATAL,
1843 "%s:Error!!! Allocating the new beacon\n",__func__);
1844 return -EINVAL;
1845 }
1846
1847 pAdapter->sessionCtx.ap.beacon = new;
1848
1849 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1850 }
1851
1852 EXIT();
1853 return status;
1854}
1855
1856static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
1857 struct net_device *dev,
1858 struct beacon_parameters *params)
1859{
1860 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1861 int status=VOS_STATUS_SUCCESS;
1862
1863 ENTER();
1864
1865 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1866 __func__,pAdapter->device_mode);
1867
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001868 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
1869 {
1870 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1871 "%s:LOGP in Progress. Ignore!!!", __func__);
1872 return -EAGAIN;
1873 }
1874
Jeff Johnson295189b2012-06-20 16:38:30 -07001875 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1876#ifdef WLAN_FEATURE_P2P
1877 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1878#endif
1879 )
1880 {
1881 beacon_data_t *old,*new;
1882
1883 old = pAdapter->sessionCtx.ap.beacon;
1884
1885 if (!old)
1886 return -ENOENT;
1887
1888 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
1889
1890 if(status != VOS_STATUS_SUCCESS) {
1891 hddLog(VOS_TRACE_LEVEL_FATAL,
1892 "%s: Error!!! Allocating the new beacon\n",__func__);
1893 return -EINVAL;
1894 }
1895
1896 pAdapter->sessionCtx.ap.beacon = new;
1897
1898 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
1899 }
1900
1901 EXIT();
1902 return status;
1903}
1904
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001905#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
1906
1907#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001908static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
1909 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001910#else
1911static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
1912 struct net_device *dev)
1913#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001914{
1915 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07001916 hdd_context_t *pHddCtx = NULL;
1917 hdd_scaninfo_t *pScanInfo = NULL;
1918 hdd_adapter_t *staAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001919 VOS_STATUS status = 0;
1920
1921 ENTER();
1922
1923 if (NULL == pAdapter)
1924 {
1925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001926 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001927 return -ENODEV;
1928 }
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001929 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1930 {
1931 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1932 "%s:LOGP in Progress. Ignore!!!", __func__);
1933 return -EAGAIN;
1934 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001935
1936 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1937 if (NULL == pHddCtx)
1938 {
1939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001940 "%s: HDD context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001941 return -ENODEV;
1942 }
1943
1944 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
1945 if (NULL == staAdapter)
1946 {
1947 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
1948 if (NULL == staAdapter)
1949 {
1950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001951 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07001952 return -ENODEV;
1953 }
1954 }
1955
1956 pScanInfo = &pHddCtx->scan_info;
1957
Jeff Johnson295189b2012-06-20 16:38:30 -07001958 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1959 {
1960 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
1961 return -EAGAIN;
1962 }
1963
1964 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1965
1966 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
1967 __func__,pAdapter->device_mode);
1968
Jeff Johnsone7245742012-09-05 17:12:55 -07001969 if ((pScanInfo != NULL) && pScanInfo->mScanPending)
1970 {
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001971 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Jeff Johnsone7245742012-09-05 17:12:55 -07001972 hdd_abort_mac_scan(staAdapter->pHddCtx);
1973 status = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08001974 &pScanInfo->abortscan_event_var,
Jeff Johnsone7245742012-09-05 17:12:55 -07001975 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
1976 if (!status)
1977 {
1978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson902c9832012-12-10 14:28:09 -08001979 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001980 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001981 VOS_ASSERT(pScanInfo->mScanPending);
1982 return 0;
1983 }
1984 }
1985
Jeff Johnson295189b2012-06-20 16:38:30 -07001986 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
1987#ifdef WLAN_FEATURE_P2P
1988 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
1989#endif
1990 )
1991 {
1992 beacon_data_t *old;
1993
1994 old = pAdapter->sessionCtx.ap.beacon;
1995
1996 if (!old)
1997 return -ENOENT;
1998
1999#ifdef CONFIG_CFG80211
2000 hdd_cleanup_actionframe(pHddCtx, pAdapter);
2001#endif
2002
2003 mutex_lock(&pHddCtx->sap_lock);
2004 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2005 {
2006 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss((WLAN_HDD_GET_CTX(pAdapter))->pvosContext) ) )
2007 {
2008 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2009
2010 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2011
2012 if (!VOS_IS_STATUS_SUCCESS(status))
2013 {
2014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2015 ("ERROR: HDD vos wait for single_event failed!!\n"));
2016 VOS_ASSERT(0);
2017 }
2018 }
2019 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2020 }
2021 mutex_unlock(&pHddCtx->sap_lock);
2022
2023 if(status != VOS_STATUS_SUCCESS)
2024 {
2025 hddLog(VOS_TRACE_LEVEL_FATAL,
2026 "%s:Error!!! Stopping the BSS\n",__func__);
2027 return -EINVAL;
2028 }
2029
2030 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2031 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
2032 ==eHAL_STATUS_FAILURE)
2033 {
2034 hddLog(LOGE,
2035 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM\n");
2036 }
2037
2038 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2039 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2040 eANI_BOOLEAN_FALSE) )
2041 {
2042 hddLog(LOGE,
2043 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM\n");
2044 }
2045
2046 // Reset WNI_CFG_PROBE_RSP Flags
2047 wlan_hdd_reset_prob_rspies(pAdapter);
2048
2049 pAdapter->sessionCtx.ap.beacon = NULL;
2050 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002051#ifdef WLAN_FEATURE_P2P_DEBUG
2052 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
2053 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
2054 {
2055 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
2056 "GO got removed");
2057 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
2058 }
2059#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002060 }
2061 EXIT();
2062 return status;
2063}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002064
2065#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2066
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302067static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
2068 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002069 struct cfg80211_ap_settings *params)
2070{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302071 hdd_adapter_t *pAdapter;
2072 hdd_context_t *pHddCtx;
2073 int status = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002074
2075 ENTER();
2076
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302077 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002078 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2080 "%s: Device is Null", __func__);
2081 return -ENODEV;
2082 }
2083
2084 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2085 if (NULL == pAdapter)
2086 {
2087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2088 "%s: HDD adapter is Null", __func__);
2089 return -ENODEV;
2090 }
2091
2092 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2093 {
2094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2095 "%s: HDD adapter magic is invalid", __func__);
2096 return -ENODEV;
2097 }
2098
2099 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2100 if (NULL == pHddCtx)
2101 {
2102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2103 "%s: HDD context is Null", __func__);
2104 return -ENODEV;
2105 }
2106
2107 if (pHddCtx->isLogpInProgress)
2108 {
2109 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2110 "%s: LOGP in Progress. Ignore!!!", __func__);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002111 return -EAGAIN;
2112 }
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302113
2114 if (pHddCtx->isLoadUnloadInProgress)
2115 {
2116 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2117 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
2118 return -EAGAIN;
2119 }
2120
2121 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d",
2122 __func__, pAdapter->device_mode);
2123
2124 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002125#ifdef WLAN_FEATURE_P2P
2126 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2127#endif
2128 )
2129 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302130 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002131
2132 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302133
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002134 if (old)
2135 return -EALREADY;
2136
2137 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
2138
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302139 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002140 {
2141 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05302142 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002143 return -EINVAL;
2144 }
2145 pAdapter->sessionCtx.ap.beacon = new;
2146 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
2147 params->ssid_len, params->hidden_ssid);
2148 }
2149
2150 EXIT();
2151 return status;
2152}
2153
2154
2155static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
2156 struct net_device *dev,
2157 struct cfg80211_beacon_data *params)
2158{
2159 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2160 int status=VOS_STATUS_SUCCESS;
2161
2162 ENTER();
2163
2164 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2165 __func__, pAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07002166 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2167 {
2168 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2169 return -EAGAIN;
2170 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002171
2172 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2173#ifdef WLAN_FEATURE_P2P
2174 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2175#endif
2176 )
2177 {
2178 beacon_data_t *old,*new;
2179
2180 old = pAdapter->sessionCtx.ap.beacon;
2181
2182 if (!old)
2183 return -ENOENT;
2184
2185 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
2186
2187 if(status != VOS_STATUS_SUCCESS) {
2188 hddLog(VOS_TRACE_LEVEL_FATAL,
2189 "%s: Error!!! Allocating the new beacon\n",__func__);
2190 return -EINVAL;
2191 }
2192
2193 pAdapter->sessionCtx.ap.beacon = new;
2194
2195 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
2196 }
2197
2198 EXIT();
2199 return status;
2200}
2201
2202#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
2203
Jeff Johnson295189b2012-06-20 16:38:30 -07002204
2205static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
2206 struct net_device *dev,
2207 struct bss_parameters *params)
2208{
2209 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2210
2211 ENTER();
2212
2213 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2214 __func__,pAdapter->device_mode);
2215
2216 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2217#ifdef WLAN_FEATURE_P2P
2218 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2219#endif
2220 )
2221 {
2222 /* ap_isolate == -1 means that in change bss, upper layer doesn't
2223 * want to update this parameter */
2224 if (-1 != params->ap_isolate)
2225 {
2226 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
2227 }
2228 }
2229
2230 EXIT();
2231 return 0;
2232}
2233
2234/*
2235 * FUNCTION: wlan_hdd_cfg80211_change_iface
2236 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
2237 */
2238int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
2239 struct net_device *ndev,
2240 enum nl80211_iftype type,
2241 u32 *flags,
2242 struct vif_params *params
2243 )
2244{
2245 struct wireless_dev *wdev;
2246 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2247 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Mohit Khanna0f232092012-09-11 14:46:08 -07002248 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002249 tCsrRoamProfile *pRoamProfile = NULL;
2250 eCsrRoamBssType LastBSSType;
2251 hdd_config_t *pConfig = pHddCtx->cfg_ini;
2252 eMib_dot11DesiredBssType connectedBssType;
2253 VOS_STATUS status;
2254
2255 ENTER();
2256
2257 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
2258 {
2259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
2260 return -EAGAIN;
2261 }
2262
2263 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2264 __func__, pAdapter->device_mode);
2265
2266 wdev = ndev->ieee80211_ptr;
2267
2268#ifdef WLAN_BTAMP_FEATURE
2269 if((NL80211_IFTYPE_P2P_CLIENT == type)||
2270 (NL80211_IFTYPE_ADHOC == type)||
2271 (NL80211_IFTYPE_AP == type)||
2272 (NL80211_IFTYPE_P2P_GO == type))
2273 {
2274 pHddCtx->isAmpAllowed = VOS_FALSE;
2275 // stop AMP traffic
2276 status = WLANBAP_StopAmp();
2277 if(VOS_STATUS_SUCCESS != status )
2278 {
2279 pHddCtx->isAmpAllowed = VOS_TRUE;
2280 hddLog(VOS_TRACE_LEVEL_FATAL,
2281 "%s: Failed to stop AMP", __func__);
2282 return -EINVAL;
2283 }
2284 }
2285#endif //WLAN_BTAMP_FEATURE
2286 /* Reset the current device mode bit mask*/
2287 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2288
2289 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2290#ifdef WLAN_FEATURE_P2P
2291 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07002292 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07002293#endif
2294 )
2295 {
2296 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2297 pRoamProfile = &pWextState->roamProfile;
2298 LastBSSType = pRoamProfile->BSSType;
2299
2300 switch (type)
2301 {
2302 case NL80211_IFTYPE_STATION:
2303#ifdef WLAN_FEATURE_P2P
2304 case NL80211_IFTYPE_P2P_CLIENT:
2305#endif
2306 hddLog(VOS_TRACE_LEVEL_INFO,
2307 "%s: setting interface Type to INFRASTRUCTURE", __func__);
2308 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07002309#ifdef WLAN_FEATURE_11AC
2310 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
2311 {
2312 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
2313 }
2314#endif
2315 pRoamProfile->phyMode =
2316 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002317 wdev->iftype = type;
2318#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002319 //Check for sub-string p2p to confirm its a p2p interface
2320 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002321 {
2322 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2323 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2324 }
2325 else
2326 {
2327 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002328 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002329 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002330#endif
2331 break;
2332 case NL80211_IFTYPE_ADHOC:
2333 hddLog(VOS_TRACE_LEVEL_INFO,
2334 "%s: setting interface Type to ADHOC", __func__);
2335 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
2336 pRoamProfile->phyMode =
2337 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
2338 wdev->iftype = type;
2339 break;
2340
2341 case NL80211_IFTYPE_AP:
2342#ifdef WLAN_FEATURE_P2P
2343 case NL80211_IFTYPE_P2P_GO:
2344#endif
2345 {
2346 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
2347 "%s: setting interface Type to %s", __func__,
2348 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
2349
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002350 //Cancel any remain on channel for GO mode
2351 if (NL80211_IFTYPE_P2P_GO == type)
2352 {
2353 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
2354 }
Mohit Khanna0f232092012-09-11 14:46:08 -07002355 if (NL80211_IFTYPE_AP == type)
2356 {
2357 /* As Loading WLAN Driver one interface being created for p2p device
2358 * address. This will take one HW STA and the max number of clients
2359 * that can connect to softAP will be reduced by one. so while changing
2360 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
2361 * interface as it is not required in SoftAP mode.
2362 */
2363
2364 // Get P2P Adapter
2365 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
2366
2367 if (pP2pAdapter)
2368 {
2369 hdd_stop_adapter(pHddCtx, pP2pAdapter);
2370 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
2371 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
2372 }
2373 }
2374
Jeff Johnson295189b2012-06-20 16:38:30 -07002375 //De-init the adapter.
2376 hdd_stop_adapter( pHddCtx, pAdapter );
2377 hdd_deinit_adapter( pHddCtx, pAdapter );
2378 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2379#ifdef WLAN_SOFTAP_FEATURE
2380#ifdef WLAN_FEATURE_P2P
2381 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2382 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2383#else
2384 pAdapter->device_mode = WLAN_HDD_SOFTAP;
2385#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07002386
2387 //Disable BMPS and IMPS if enabled
2388 //before starting Go
2389 if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
2390 {
2391 if(VOS_STATUS_E_FAILURE ==
2392 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
2393 {
2394 //Fail to Exit BMPS
2395 VOS_ASSERT(0);
2396 }
2397 }
2398
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07002399 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
2400 (pConfig->apRandomBssidEnabled))
2401 {
2402 /* To meet Android requirements create a randomized
2403 MAC address of the form 02:1A:11:Fx:xx:xx */
2404 get_random_bytes(&ndev->dev_addr[3], 3);
2405 ndev->dev_addr[0] = 0x02;
2406 ndev->dev_addr[1] = 0x1A;
2407 ndev->dev_addr[2] = 0x11;
2408 ndev->dev_addr[3] |= 0xF0;
2409 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
2410 VOS_MAC_ADDR_SIZE);
2411 pr_info("wlan: Generated HotSpot BSSID "
2412 "%02x:%02x:%02x:%02x:%02x:%02x\n",
2413 ndev->dev_addr[0],
2414 ndev->dev_addr[1],
2415 ndev->dev_addr[2],
2416 ndev->dev_addr[3],
2417 ndev->dev_addr[4],
2418 ndev->dev_addr[5]);
2419 }
2420
Jeff Johnson295189b2012-06-20 16:38:30 -07002421 hdd_set_ap_ops( pAdapter->dev );
2422
2423 status = hdd_init_ap_mode(pAdapter);
2424 if(status != VOS_STATUS_SUCCESS)
2425 {
2426 hddLog(VOS_TRACE_LEVEL_FATAL,
2427 "%s: Error initializing the ap mode", __func__);
2428 return -EINVAL;
2429 }
2430 hdd_set_conparam(1);
2431
2432#endif
2433 /*interface type changed update in wiphy structure*/
2434 if(wdev)
2435 {
2436 wdev->iftype = type;
2437 pHddCtx->change_iface = type;
2438 }
2439 else
2440 {
2441 hddLog(VOS_TRACE_LEVEL_ERROR,
2442 "%s: ERROR !!!! Wireless dev is NULL", __func__);
2443 return -EINVAL;
2444 }
2445 goto done;
2446 }
2447
2448 default:
2449 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2450 __func__);
2451 return -EOPNOTSUPP;
2452 }
2453 }
2454 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
2455#ifdef WLAN_FEATURE_P2P
2456 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2457#endif
2458 )
2459 {
2460 switch(type)
2461 {
2462 case NL80211_IFTYPE_STATION:
2463#ifdef WLAN_FEATURE_P2P
2464 case NL80211_IFTYPE_P2P_CLIENT:
2465#endif
2466 case NL80211_IFTYPE_ADHOC:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002467 hdd_stop_adapter( pHddCtx, pAdapter );
2468 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07002469 wdev->iftype = type;
2470#ifdef WLAN_FEATURE_P2P
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08002471 //Check for sub-string p2p to confirm its a p2p interface
2472 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002473 {
2474 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
2475 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
2476 }
2477 else
2478 {
2479 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002480 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08002481 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002482#endif
2483 hdd_set_conparam(0);
2484 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
2486 hdd_set_station_ops( pAdapter->dev );
2487 status = hdd_init_station_mode( pAdapter );
2488 if( VOS_STATUS_SUCCESS != status )
2489 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07002490 /* In case of JB, for P2P-GO, only change interface will be called,
2491 * This is the right place to enable back bmps_imps()
2492 */
2493 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002494 goto done;
2495 case NL80211_IFTYPE_AP:
2496#ifdef WLAN_FEATURE_P2P
2497 case NL80211_IFTYPE_P2P_GO:
2498#endif
2499 wdev->iftype = type;
2500#ifdef WLAN_FEATURE_P2P
2501 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
2502 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
2503#endif
2504 goto done;
2505 default:
2506 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
2507 __func__);
2508 return -EOPNOTSUPP;
2509
2510 }
2511
2512 }
2513 else
2514 {
2515 return -EOPNOTSUPP;
2516 }
2517
2518
2519 if(pRoamProfile)
2520 {
2521 if ( LastBSSType != pRoamProfile->BSSType )
2522 {
2523 /*interface type changed update in wiphy structure*/
2524 wdev->iftype = type;
2525
2526 /*the BSS mode changed, We need to issue disconnect
2527 if connected or in IBSS disconnect state*/
2528 if ( hdd_connGetConnectedBssType(
2529 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
2530 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
2531 {
2532 /*need to issue a disconnect to CSR.*/
2533 INIT_COMPLETION(pAdapter->disconnect_comp_var);
2534 if( eHAL_STATUS_SUCCESS ==
2535 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
2536 pAdapter->sessionId,
2537 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
2538 {
2539 wait_for_completion_interruptible_timeout(
2540 &pAdapter->disconnect_comp_var,
2541 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2542 }
2543 }
2544 }
2545 }
2546
2547done:
2548 /*set bitmask based on updated value*/
2549 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
2550#ifdef WLAN_BTAMP_FEATURE
2551 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
2552 (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1))
2553 {
2554 //we are ok to do AMP
2555 pHddCtx->isAmpAllowed = VOS_TRUE;
2556 }
2557#endif //WLAN_BTAMP_FEATURE
2558 EXIT();
2559 return 0;
2560}
2561
2562static int wlan_hdd_change_station(struct wiphy *wiphy,
2563 struct net_device *dev,
2564 u8 *mac,
2565 struct station_parameters *params)
2566{
2567 VOS_STATUS status = VOS_STATUS_SUCCESS;
2568 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
2569 v_MACADDR_t STAMacAddress;
2570
Jeff Johnsone7245742012-09-05 17:12:55 -07002571 ENTER();
2572
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002573 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2574 {
2575 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2576 "%s:LOGP in Progress. Ignore!!!", __func__);
2577 return -EAGAIN;
2578 }
2579
Jeff Johnson295189b2012-06-20 16:38:30 -07002580 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
2581
2582 if ( ( pAdapter->device_mode == WLAN_HDD_SOFTAP )
2583#ifdef WLAN_FEATURE_P2P
2584 || ( pAdapter->device_mode == WLAN_HDD_P2P_GO )
2585#endif
2586 )
2587 {
2588 if(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
2589 {
2590 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
2591 WLANTL_STA_AUTHENTICATED);
2592
2593 VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002594 "%s: Station MAC address does not matching", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002595 return -EINVAL;
2596 }
2597 }
2598
Jeff Johnsone7245742012-09-05 17:12:55 -07002599 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07002600 return status;
2601}
2602
2603/*
2604 * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx
2605 * This function is used to get peer station index in IBSS mode
2606 */
2607static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter)
2608{
2609 u8 idx = 0;
2610 u8 temp[VOS_MAC_ADDR_SIZE] = {0};
2611 ENTER();
2612 memset(temp, 0, VOS_MAC_ADDR_SIZE);
2613 for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
2614 {
2615 if ( (0 !=
2616 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx])
2617 && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx],
2618 temp, VOS_MAC_ADDR_SIZE)
2619 )
2620 {
2621 return idx;
2622 }
2623 }
2624 return idx;
2625}
2626
2627
2628/*
2629 * FUNCTION: wlan_hdd_cfg80211_add_key
2630 * This function is used to initialize the key information
2631 */
2632#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2633static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2634 struct net_device *ndev,
2635 u8 key_index, bool pairwise,
2636 const u8 *mac_addr,
2637 struct key_params *params
2638 )
2639#else
2640static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
2641 struct net_device *ndev,
2642 u8 key_index, const u8 *mac_addr,
2643 struct key_params *params
2644 )
2645#endif
2646{
2647 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
2648 tCsrRoamSetKey setKey;
2649 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
2650 int status = 0;
2651 v_U32_t roamId= 0xFF;
2652 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
2653 hdd_hostapd_state_t *pHostapdState;
2654 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002655 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002656
2657 ENTER();
2658
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002659 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
2660 {
2661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2662 "%s:LOGP in Progress. Ignore!!!", __func__);
2663 return -EAGAIN;
2664 }
2665
Jeff Johnson295189b2012-06-20 16:38:30 -07002666 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
2667 __func__,pAdapter->device_mode);
2668
2669 if (CSR_MAX_NUM_KEY <= key_index)
2670 {
2671 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
2672 key_index);
2673
2674 return -EINVAL;
2675 }
2676
2677 hddLog(VOS_TRACE_LEVEL_INFO,
2678 "%s: called with key index = %d & key length %d",
2679 __func__, key_index, params->key_len);
2680
2681 /*extract key idx, key len and key*/
2682 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2683 setKey.keyId = key_index;
2684 setKey.keyLength = params->key_len;
2685 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
2686
2687 switch (params->cipher)
2688 {
2689 case WLAN_CIPHER_SUITE_WEP40:
2690 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
2691 break;
2692
2693 case WLAN_CIPHER_SUITE_WEP104:
2694 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
2695 break;
2696
2697 case WLAN_CIPHER_SUITE_TKIP:
2698 {
2699 u8 *pKey = &setKey.Key[0];
2700 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
2701
2702 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
2703
2704 /*Supplicant sends the 32bytes key in this order
2705
2706 |--------------|----------|----------|
2707 | Tk1 |TX-MIC | RX Mic |
2708 |--------------|----------|----------|
2709 <---16bytes---><--8bytes--><--8bytes-->
2710
2711 */
2712 /*Sme expects the 32 bytes key to be in the below order
2713
2714 |--------------|----------|----------|
2715 | Tk1 |RX-MIC | TX Mic |
2716 |--------------|----------|----------|
2717 <---16bytes---><--8bytes--><--8bytes-->
2718 */
2719 /* Copy the Temporal Key 1 (TK1) */
2720 vos_mem_copy(pKey, params->key,16);
2721
2722 /*Copy the rx mic first*/
2723 vos_mem_copy(&pKey[16],&params->key[24],8);
2724
2725 /*Copy the tx mic */
2726 vos_mem_copy(&pKey[24],&params->key[16],8);
2727
2728
2729 break;
2730 }
2731
2732 case WLAN_CIPHER_SUITE_CCMP:
2733 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
2734 break;
2735
2736#ifdef FEATURE_WLAN_WAPI
2737 case WLAN_CIPHER_SUITE_SMS4:
2738 {
2739 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
2740 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
2741 params->key, params->key_len);
2742 return 0;
2743 }
2744#endif
2745#ifdef FEATURE_WLAN_CCX
2746 case WLAN_CIPHER_SUITE_KRK:
2747 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
2748 break;
2749#endif
2750 default:
2751 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu",
2752 __func__, params->cipher);
2753 return -EOPNOTSUPP;
2754 }
2755
2756 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
2757 __func__, setKey.encType);
2758
2759
2760
2761 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
2762#ifdef WLAN_FEATURE_P2P
2763 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
2764#endif
2765 )
2766 {
2767
2768
2769 if (
2770#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2771 (!pairwise)
2772#else
2773 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2774#endif
2775 )
2776 {
2777 /* set group key*/
2778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson1250df42012-12-10 14:31:52 -08002779 "%s- %d: setting Broadcast key",
Jeff Johnson295189b2012-06-20 16:38:30 -07002780 __func__, __LINE__);
2781 setKey.keyDirection = eSIR_RX_ONLY;
2782 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2783 }
2784 else
2785 {
2786 /* set pairwise key*/
2787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2788 "%s- %d: setting pairwise key",
2789 __func__, __LINE__);
2790 setKey.keyDirection = eSIR_TX_RX;
2791 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2792 }
2793
2794 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2795 if( pHostapdState->bssState == BSS_START )
2796 {
2797 status = WLANSAP_SetKeySta( pVosContext, &setKey);
2798
2799 if ( status != eHAL_STATUS_SUCCESS )
2800 {
2801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2802 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
2803 __LINE__, status );
2804 }
2805 }
2806
2807 /* Saving WEP keys */
2808 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
2809 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
2810 {
2811 //Save the wep key in ap context. Issue setkey after the BSS is started.
2812 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2813 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
2814 }
2815 else
2816 {
2817 //Save the key in ap context. Issue setkey after the BSS is started.
2818 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2819 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
2820 }
2821 }
2822 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
2823#ifdef WLAN_FEATURE_P2P
2824 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
2825#endif
2826 )
2827 {
2828 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2829 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2830
2831 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
2832
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08002833 pWextState->roamProfile.Keys.defaultIndex = key_index;
2834
2835
Jeff Johnson295189b2012-06-20 16:38:30 -07002836 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
2837 params->key, params->key_len);
2838
2839 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
2840
2841 if (!( ( IW_AUTH_KEY_MGMT_802_1X
2842 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2843 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2844 )
2845 &&
2846 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
2847 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
2848 )
2849 )
2850 {
2851 /* in case of static WEP, macaddr/bssid is not coming from nl80211
2852 * interface, copy bssid for pairwise key and group macaddr for
2853 * group key initialization*/
2854
2855 tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile;
2856
2857 pWextState->roamProfile.negotiatedUCEncryptionType =
2858 pHddStaCtx->conn_info.ucEncryptionType =
2859 ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ?
2860 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY :
2861 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY);
2862
2863
2864 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2865 "%s: Negotiated encryption type %d", __func__,
2866 pWextState->roamProfile.negotiatedUCEncryptionType);
2867
2868 sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter),
2869 &pWextState->roamProfile, true);
2870 setKey.keyLength = 0;
2871 setKey.keyDirection = eSIR_TX_RX;
2872
2873#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2874 if (pairwise)
2875 {
2876#endif
2877 if (mac_addr)
2878 {
2879 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2880 }
2881 else
2882 {
2883 /* macaddr is NULL, set the peerMac to bssId in case of BSS,
2884 * and peerMacAddress in case of IBSS*/
2885 if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType)
2886 {
2887 u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter);
2888 if (HDD_MAX_NUM_IBSS_STA != staidx)
2889 {
2890 vos_mem_copy(setKey.peerMac,
2891 &pHddStaCtx->conn_info.peerMacAddress[staidx],
2892 WNI_CFG_BSSID_LEN);
2893
2894 }
2895 else
2896 {
2897 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found",
2898 __func__);
2899 return -EOPNOTSUPP;
2900 }
2901 }
2902 else
2903 {
2904 vos_mem_copy(setKey.peerMac,
2905 &pHddStaCtx->conn_info.bssId[0],
2906 WNI_CFG_BSSID_LEN);
2907 }
2908 }
2909#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2910 }
2911 else
2912 {
2913 /* set group key*/
2914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2915 "%s- %d: setting Group key",
2916 __func__, __LINE__);
2917 setKey.keyDirection = eSIR_RX_ONLY;
2918 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
2919 }
2920#endif
2921 }
2922 else if (
2923#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2924 (!pairwise)
2925#else
2926 (!mac_addr || is_broadcast_ether_addr(mac_addr))
2927#endif
2928 )
2929 {
2930 /* set group key*/
2931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2932 "%s- %d: setting Group key",
2933 __func__, __LINE__);
2934 setKey.keyDirection = eSIR_RX_ONLY;
2935 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
2936 }
2937 else
2938 {
2939 /* set pairwise key*/
2940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2941 "%s- %d: setting pairwise key",
2942 __func__, __LINE__);
2943 setKey.keyDirection = eSIR_TX_RX;
2944 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
2945 }
2946
2947 hddLog(VOS_TRACE_LEVEL_INFO_MED,
2948 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
2949 __func__, setKey.peerMac[0], setKey.peerMac[1],
2950 setKey.peerMac[2], setKey.peerMac[3],
2951 setKey.peerMac[4], setKey.peerMac[5],
2952 setKey.keyDirection);
2953
2954 vos_status = wlan_hdd_check_ula_done(pAdapter);
2955
2956 if ( vos_status != VOS_STATUS_SUCCESS )
2957 {
2958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2959 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
2960 __LINE__, vos_status );
2961
2962 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2963
2964 return -EINVAL;
2965
2966 }
2967
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07002968#ifdef WLAN_FEATURE_VOWIFI_11R
2969 /* The supplicant may attempt to set the PTK once pre-authentication is done.
2970 Save the key in the UMAC and include it in the ADD BSS request */
2971 /*TODO 11r - is this used?? */
2972 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
2973 if( halStatus == eHAL_STATUS_SUCCESS )
2974 {
2975 return halStatus;
2976 }
2977#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07002978
2979 /* issue set key request to SME*/
2980 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
2981 pAdapter->sessionId, &setKey, &roamId );
2982
2983 if ( 0 != status )
2984 {
2985 hddLog(VOS_TRACE_LEVEL_ERROR,
2986 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
2987 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
2988 return -EINVAL;
2989 }
2990
2991
2992 /* in case of IBSS as there was no information available about WEP keys during
2993 * IBSS join, group key intialized with NULL key, so re-initialize group key
2994 * with correct value*/
2995 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
2996 !( ( IW_AUTH_KEY_MGMT_802_1X
2997 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
2998 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
2999 )
3000 &&
3001 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
3002 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
3003 )
3004 )
3005 {
3006 setKey.keyDirection = eSIR_RX_ONLY;
3007 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
3008
3009 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3010 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
3011 __func__, setKey.peerMac[0], setKey.peerMac[1],
3012 setKey.peerMac[2], setKey.peerMac[3],
3013 setKey.peerMac[4], setKey.peerMac[5],
3014 setKey.keyDirection);
3015
3016 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3017 pAdapter->sessionId, &setKey, &roamId );
3018
3019 if ( 0 != status )
3020 {
3021 hddLog(VOS_TRACE_LEVEL_ERROR,
3022 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
3023 __func__, status);
3024 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3025 return -EINVAL;
3026 }
3027 }
3028 }
3029
3030 return 0;
3031}
3032
3033/*
3034 * FUNCTION: wlan_hdd_cfg80211_get_key
3035 * This function is used to get the key information
3036 */
3037#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3038static int wlan_hdd_cfg80211_get_key(
3039 struct wiphy *wiphy,
3040 struct net_device *ndev,
3041 u8 key_index, bool pairwise,
3042 const u8 *mac_addr, void *cookie,
3043 void (*callback)(void *cookie, struct key_params*)
3044 )
3045#else
3046static int wlan_hdd_cfg80211_get_key(
3047 struct wiphy *wiphy,
3048 struct net_device *ndev,
3049 u8 key_index, const u8 *mac_addr, void *cookie,
3050 void (*callback)(void *cookie, struct key_params*)
3051 )
3052#endif
3053{
3054 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3055 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3056 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
3057 struct key_params params;
3058
3059 ENTER();
3060
3061 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
3062 __func__,pAdapter->device_mode);
3063
3064 memset(&params, 0, sizeof(params));
3065
3066 if (CSR_MAX_NUM_KEY <= key_index)
3067 {
3068 return -EINVAL;
3069 }
3070
3071 switch(pRoamProfile->EncryptionType.encryptionType[0])
3072 {
3073 case eCSR_ENCRYPT_TYPE_NONE:
3074 params.cipher = IW_AUTH_CIPHER_NONE;
3075 break;
3076
3077 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
3078 case eCSR_ENCRYPT_TYPE_WEP40:
3079 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3080 break;
3081
3082 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
3083 case eCSR_ENCRYPT_TYPE_WEP104:
3084 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3085 break;
3086
3087 case eCSR_ENCRYPT_TYPE_TKIP:
3088 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3089 break;
3090
3091 case eCSR_ENCRYPT_TYPE_AES:
3092 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3093 break;
3094
3095 default:
3096 params.cipher = IW_AUTH_CIPHER_NONE;
3097 break;
3098 }
3099
3100 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
3101 params.seq_len = 0;
3102 params.seq = NULL;
3103 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
3104 callback(cookie, &params);
3105 return 0;
3106}
3107
3108/*
3109 * FUNCTION: wlan_hdd_cfg80211_del_key
3110 * This function is used to delete the key information
3111 */
3112#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3113static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3114 struct net_device *ndev,
3115 u8 key_index,
3116 bool pairwise,
3117 const u8 *mac_addr
3118 )
3119#else
3120static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
3121 struct net_device *ndev,
3122 u8 key_index,
3123 const u8 *mac_addr
3124 )
3125#endif
3126{
3127 int status = 0;
3128
3129 //This code needs to be revisited. There is sme_removeKey API, we should
3130 //plan to use that. After the change to use correct index in setkey,
3131 //it is observed that this is invalidating peer
3132 //key index whenever re-key is done. This is affecting data link.
3133 //It should be ok to ignore del_key.
3134#if 0
3135 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3136 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
3137 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
3138 tCsrRoamSetKey setKey;
3139 v_U32_t roamId= 0xFF;
3140
3141 ENTER();
3142
3143 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
3144 __func__,pAdapter->device_mode);
3145
3146 if (CSR_MAX_NUM_KEY <= key_index)
3147 {
3148 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3149 key_index);
3150
3151 return -EINVAL;
3152 }
3153
3154 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3155 setKey.keyId = key_index;
3156
3157 if (mac_addr)
3158 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
3159 else
3160 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
3161
3162 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
3163
3164 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3165#ifdef WLAN_FEATURE_P2P
3166 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3167#endif
3168 )
3169 {
3170
3171 hdd_hostapd_state_t *pHostapdState =
3172 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3173 if( pHostapdState->bssState == BSS_START)
3174 {
3175 status = WLANSAP_SetKeySta( pVosContext, &setKey);
3176
3177 if ( status != eHAL_STATUS_SUCCESS )
3178 {
3179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3180 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
3181 __LINE__, status );
3182 }
3183 }
3184 }
3185 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3186#ifdef WLAN_FEATURE_P2P
3187 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3188#endif
3189 )
3190 {
3191 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3192
3193 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
3194
3195 hddLog(VOS_TRACE_LEVEL_INFO_MED,
3196 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
3197 __func__, setKey.peerMac[0], setKey.peerMac[1],
3198 setKey.peerMac[2], setKey.peerMac[3],
3199 setKey.peerMac[4], setKey.peerMac[5]);
3200 if(pAdapter->sessionCtx.station.conn_info.connState ==
3201 eConnectionState_Associated)
3202 {
3203 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3204 pAdapter->sessionId, &setKey, &roamId );
3205
3206 if ( 0 != status )
3207 {
3208 hddLog(VOS_TRACE_LEVEL_ERROR,
3209 "%s: sme_RoamSetKey failure, returned %d",
3210 __func__, status);
3211 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
3212 return -EINVAL;
3213 }
3214 }
3215 }
3216#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003217 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07003218 return status;
3219}
3220
3221/*
3222 * FUNCTION: wlan_hdd_cfg80211_set_default_key
3223 * This function is used to set the default tx key index
3224 */
3225#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3226static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3227 struct net_device *ndev,
3228 u8 key_index,
3229 bool unicast, bool multicast)
3230#else
3231static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
3232 struct net_device *ndev,
3233 u8 key_index)
3234#endif
3235{
3236 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
3237 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3238 int status = 0;
3239 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3240
3241 ENTER();
3242
3243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n",
3244 __func__,pAdapter->device_mode, key_index);
3245
3246 if (CSR_MAX_NUM_KEY <= key_index)
3247 {
3248 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
3249 key_index);
3250
3251 return -EINVAL;
3252 }
3253
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003254 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
3255 {
3256 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3257 "%s:LOGP in Progress. Ignore!!!", __func__);
3258 return -EAGAIN;
3259 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003260
3261 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3262#ifdef WLAN_FEATURE_P2P
3263 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3264#endif
3265 )
3266 {
3267 if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) &&
3268 (eCSR_ENCRYPT_TYPE_TKIP !=
3269 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3270 (eCSR_ENCRYPT_TYPE_AES !=
3271 pWextState->roamProfile.EncryptionType.encryptionType[0])
3272 )
3273 {
3274 /* if default key index is not same as previous one,
3275 * then update the default key index */
3276
3277 tCsrRoamSetKey setKey;
3278 v_U32_t roamId= 0xFF;
3279 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
3280
3281 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
3282 __func__, key_index);
3283
3284 Keys->defaultIndex = (u8)key_index;
3285 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
3286 setKey.keyId = key_index;
3287 setKey.keyLength = Keys->KeyLength[key_index];
3288
3289 vos_mem_copy(&setKey.Key[0],
3290 &Keys->KeyMaterial[key_index][0],
3291 Keys->KeyLength[key_index]);
3292
3293 setKey.keyDirection = eSIR_TX_ONLY;
3294
3295 vos_mem_copy(setKey.peerMac,
3296 &pHddStaCtx->conn_info.bssId[0],
3297 WNI_CFG_BSSID_LEN);
3298
3299 setKey.encType =
3300 pWextState->roamProfile.EncryptionType.encryptionType[0];
3301
3302 /* issue set key request */
3303 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
3304 pAdapter->sessionId, &setKey, &roamId );
3305
3306 if ( 0 != status )
3307 {
3308 hddLog(VOS_TRACE_LEVEL_ERROR,
3309 "%s: sme_RoamSetKey failed, returned %d", __func__,
3310 status);
3311 return -EINVAL;
3312 }
3313 }
3314 }
3315
3316 /* In SoftAp mode setting key direction for default mode */
3317 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3318 {
3319 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
3320 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
3321 (eCSR_ENCRYPT_TYPE_AES !=
3322 pWextState->roamProfile.EncryptionType.encryptionType[0])
3323 )
3324 {
3325 /* Saving key direction for default key index to TX default */
3326 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3327 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
3328 }
3329 }
3330
3331 return status;
3332}
3333
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003334#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07003335/**
3336 * FUNCTION: wlan_hdd_cfg80211_set_channel
3337 * This function is used to set the channel number
3338 */
3339int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
3340 struct ieee80211_channel *chan,
3341 enum nl80211_channel_type channel_type
3342 )
3343{
3344 v_U32_t num_ch = 0;
3345 u32 channel = 0;
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003346 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 int freq = chan->center_freq; /* freq is in MHZ */
3348
3349 ENTER();
Madan Mohan Koyyalamudi73305412012-11-30 17:21:40 -08003350
3351 if( NULL == dev )
3352 {
3353 hddLog(VOS_TRACE_LEVEL_ERROR,
3354 "%s: Called with dev = NULL.\n", __func__);
3355 return -ENODEV;
3356 }
3357 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003358
3359 hddLog(VOS_TRACE_LEVEL_INFO,
3360 "%s: device_mode = %d freq = %d \n",__func__,
3361 pAdapter->device_mode, chan->center_freq);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07003362 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3363 {
3364 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3365 return -EAGAIN;
3366 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003367
3368 /*
3369 * Do freq to chan conversion
3370 * TODO: for 11a
3371 */
3372
3373 channel = ieee80211_frequency_to_channel(freq);
3374
3375 /* Check freq range */
3376 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
3377 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
3378 {
3379 hddLog(VOS_TRACE_LEVEL_ERROR,
3380 "%s: Channel [%d] is outside valid range from %d to %d\n",
3381 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
3382 WNI_CFG_CURRENT_CHANNEL_STAMAX);
3383 return -EINVAL;
3384 }
3385
3386 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3387
3388 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode)
3389#ifdef WLAN_FEATURE_P2P
3390 && (WLAN_HDD_P2P_GO != pAdapter->device_mode)
3391#endif
3392 )
3393 {
3394 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
3395 {
3396 hddLog(VOS_TRACE_LEVEL_ERROR,
3397 "%s: Invalid Channel [%d] \n", __func__, channel);
3398 return -EINVAL;
3399 }
3400 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3401 "%s: set channel to [%d] for device mode =%d",
3402 __func__, channel,pAdapter->device_mode);
3403 }
3404 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
3405#ifdef WLAN_FEATURE_P2P
3406 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
3407#endif
3408 )
3409 {
3410 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3411 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
3412 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3413
3414 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
3415 {
3416 /* Link is up then return cant set channel*/
3417 hddLog( VOS_TRACE_LEVEL_ERROR,
3418 "%s: IBSS Associated, can't set the channel\n", __func__);
3419 return -EINVAL;
3420 }
3421
3422 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
3423 pHddStaCtx->conn_info.operationChannel = channel;
3424 pRoamProfile->ChannelInfo.ChannelList =
3425 &pHddStaCtx->conn_info.operationChannel;
3426 }
3427 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
3428#ifdef WLAN_FEATURE_P2P
3429 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
3430#endif
3431 )
3432 {
3433 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
3434
3435 if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
3436 {
3437 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3438
3439 /* If auto channel selection is configured as enable/ 1 then ignore
3440 channel set by supplicant
3441 */
3442 if ( cfg_param->apAutoChannelSelection )
3443 {
3444 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = AUTO_CHANNEL_SELECT;
3445
3446 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3447 "%s: set channel to auto channel (0) for device mode =%d",
3448 __func__, pAdapter->device_mode);
3449 }
3450 }
3451 }
3452 else
3453 {
3454 hddLog(VOS_TRACE_LEVEL_FATAL,
3455 "%s: Invalid device mode failed to set valid channel", __func__);
3456 return -EINVAL;
3457 }
3458 EXIT();
3459 return 0;
3460}
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003461#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003462
3463
3464
3465/*
3466 * FUNCTION: wlan_hdd_cfg80211_inform_bss
3467 * This function is used to inform the BSS details to nl80211 interface.
3468 */
3469static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
3470 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
3471{
3472 struct net_device *dev = pAdapter->dev;
3473 struct wireless_dev *wdev = dev->ieee80211_ptr;
3474 struct wiphy *wiphy = wdev->wiphy;
3475 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
3476 int chan_no;
3477 int ie_length;
3478 const char *ie;
3479 unsigned int freq;
3480 struct ieee80211_channel *chan;
3481 int rssi = 0;
3482 struct cfg80211_bss *bss = NULL;
3483
3484 ENTER();
3485
3486 if( NULL == pBssDesc )
3487 {
3488 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL\n", __func__);
3489 return bss;
3490 }
3491
3492 chan_no = pBssDesc->channelId;
3493 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
3494 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
3495
3496 if( NULL == ie )
3497 {
3498 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL\n", __func__);
3499 return bss;
3500 }
3501
3502#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3503 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
3504 {
3505 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3506 }
3507 else
3508 {
3509 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3510 }
3511#else
3512 freq = ieee80211_channel_to_frequency(chan_no);
3513#endif
3514
3515 chan = __ieee80211_get_channel(wiphy, freq);
3516
3517 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
3518 &roamProfile->SSID.ssId[0], roamProfile->SSID.length,
3519 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
3520 if (bss == NULL)
3521 {
3522 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
3523
3524 return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
3525 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
3526 pBssDesc->capabilityInfo,
3527 pBssDesc->beaconInterval, ie, ie_length,
3528 rssi, GFP_KERNEL ));
3529}
3530 else
3531 {
3532 return bss;
3533 }
3534}
3535
3536
3537
3538/*
3539 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
3540 * This function is used to inform the BSS details to nl80211 interface.
3541 */
3542struct cfg80211_bss*
3543wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
3544 tSirBssDescription *bss_desc
3545 )
3546{
3547 /*
3548 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
3549 already exists in bss data base of cfg80211 for that particular BSS ID.
3550 Using cfg80211_inform_bss_frame to update the bss entry instead of
3551 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
3552 now there is no possibility to get the mgmt(probe response) frame from PE,
3553 converting bss_desc to ieee80211_mgmt(probe response) and passing to
3554 cfg80211_inform_bss_frame.
3555 */
3556 struct net_device *dev = pAdapter->dev;
3557 struct wireless_dev *wdev = dev->ieee80211_ptr;
3558 struct wiphy *wiphy = wdev->wiphy;
3559 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003560#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3561 qcom_ie_age *qie_age = NULL;
3562 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
3563#else
Jeff Johnson295189b2012-06-20 16:38:30 -07003564 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003565#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003566 const char *ie =
3567 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
3568 unsigned int freq;
3569 struct ieee80211_channel *chan;
3570 struct ieee80211_mgmt *mgmt =
3571 kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
3572 struct cfg80211_bss *bss_status = NULL;
3573 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
3574 int rssi = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07003575#ifdef WLAN_OPEN_SOURCE
3576 struct timespec ts;
3577#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003578
3579 ENTER();
3580
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07003581 if (!mgmt)
3582 return NULL;
3583
Jeff Johnson295189b2012-06-20 16:38:30 -07003584 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07003585
3586#ifdef WLAN_OPEN_SOURCE
3587 /* Android does not want the timestamp from the frame.
3588 Instead it wants a monotonic increasing value */
3589 get_monotonic_boottime(&ts);
3590 mgmt->u.probe_resp.timestamp =
3591 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
3592#else
3593 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07003594 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
3595 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07003596
3597#endif
3598
Jeff Johnson295189b2012-06-20 16:38:30 -07003599 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
3600 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08003601
3602#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
3603 /* GPS Requirement: need age ie per entry. Using vendor specific. */
3604 /* Assuming this is the last IE, copy at the end */
3605 ie_length -=sizeof(qcom_ie_age);
3606 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
3607 qie_age->element_id = QCOM_VENDOR_IE_ID;
3608 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
3609 qie_age->oui_1 = QCOM_OUI1;
3610 qie_age->oui_2 = QCOM_OUI2;
3611 qie_age->oui_3 = QCOM_OUI3;
3612 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
3613 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
3614#endif
3615
Jeff Johnson295189b2012-06-20 16:38:30 -07003616 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
3617
3618 mgmt->frame_control |=
3619 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
3620
3621#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
3622 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
3623 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
3624 {
3625 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
3626 }
3627 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
3628 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
3629
3630 {
3631 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
3632 }
3633 else
3634 {
3635 kfree(mgmt);
3636 return NULL;
3637 }
3638#else
3639 freq = ieee80211_channel_to_frequency(chan_no);
3640#endif
3641 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08003642 /*when the band is changed on the fly using the GUI, three things are done
3643 * 1. scan abort 2.flush scan results from cache 3.update the band with the new band user specified(refer to the hdd_setBand_helper function)
3644 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
3645 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
3646 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
3647 * and discards the channels correponding to previous band and calls back with zero bss results.
3648 * but if the time between band update and scan done callback is very small then band change will not reflect in SME and SME reports to HDD
3649 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
3650 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
3651 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
3652 * So drop the bss and continue to next bss.
3653 */
3654 if(chan == NULL)
3655 {
3656 hddLog(VOS_TRACE_LEVEL_INFO, "%s chan pointer is NULL", __func__);
3657 return NULL;
3658 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003659 /*To keep the rssi icon of the connected AP in the scan window
3660 *and the rssi icon of the wireless networks in sync
3661 * */
3662 if (( eConnectionState_Associated ==
3663 pAdapter->sessionCtx.station.conn_info.connState ) &&
3664 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
3665 pAdapter->sessionCtx.station.conn_info.bssId,
3666 WNI_CFG_BSSID_LEN)))
3667 {
3668 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
3669 rssi = (pAdapter->rssi * 100);
3670 }
3671 else
3672 {
3673 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
3674 }
3675
3676 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
3677 frame_len, rssi, GFP_KERNEL);
3678 kfree(mgmt);
3679 return bss_status;
3680}
3681
3682/*
3683 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
3684 * This function is used to update the BSS data base of CFG8011
3685 */
3686struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
3687 tCsrRoamInfo *pRoamInfo
3688 )
3689{
3690 tCsrRoamConnectedProfile roamProfile;
3691 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3692 struct cfg80211_bss *bss = NULL;
3693
3694 ENTER();
3695
3696 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
3697 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
3698
3699 if (NULL != roamProfile.pBssDesc)
3700 {
3701 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
3702 &roamProfile);
3703
3704 if (NULL == bss)
3705 {
3706 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
3707 __func__);
3708 }
3709
3710 sme_RoamFreeConnectProfile(hHal, &roamProfile);
3711 }
3712 else
3713 {
3714 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
3715 __func__);
3716 }
3717 return bss;
3718}
3719
3720/*
3721 * FUNCTION: wlan_hdd_cfg80211_update_bss
3722 */
3723static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
3724 hdd_adapter_t *pAdapter
3725 )
3726{
3727 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
3728 tCsrScanResultInfo *pScanResult;
3729 eHalStatus status = 0;
3730 tScanResultHandle pResult;
3731 struct cfg80211_bss *bss_status = NULL;
3732
3733 ENTER();
3734
3735 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
3736 {
3737 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
3738 return -EAGAIN;
3739 }
3740
3741 /*
3742 * start getting scan results and populate cgf80211 BSS database
3743 */
3744 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
3745
3746 /* no scan results */
3747 if (NULL == pResult)
3748 {
3749 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result\n", __func__);
3750 return status;
3751 }
3752
3753 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
3754
3755 while (pScanResult)
3756 {
3757 /*
3758 * cfg80211_inform_bss() is not updating ie field of bss entry, if
3759 * entry already exists in bss data base of cfg80211 for that
3760 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
3761 * bss entry instead of cfg80211_inform_bss, But this call expects
3762 * mgmt packet as input. As of now there is no possibility to get
3763 * the mgmt(probe response) frame from PE, converting bss_desc to
3764 * ieee80211_mgmt(probe response) and passing to c
3765 * fg80211_inform_bss_frame.
3766 * */
3767
3768 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
3769 &pScanResult->BssDescriptor);
3770
3771
3772 if (NULL == bss_status)
3773 {
3774 hddLog(VOS_TRACE_LEVEL_INFO,
3775 "%s: NULL returned by cfg80211_inform_bss\n", __func__);
3776 }
3777 else
3778 {
3779 cfg80211_put_bss(bss_status);
3780 }
3781
3782 pScanResult = sme_ScanResultGetNext(hHal, pResult);
3783 }
3784
3785 sme_ScanResultPurge(hHal, pResult);
3786
3787 return 0;
3788}
3789
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003790void
3791hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
3792{
3793 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003794 "%02X:%02X:%02X:%02X:%02X:%02X\n",
3795 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4],
3796 macAddr[5]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003797} /****** end hddPrintMacAddr() ******/
3798
3799void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003800hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003801{
3802 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003803 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
3804 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
3805 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
3806 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003807} /****** end hddPrintPmkId() ******/
3808
3809//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
3810//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
3811
3812//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
3813//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
3814
3815#define dump_bssid(bssid) \
3816 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003817 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
3818 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
3819 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003820 }
3821
3822#define dump_pmkid(pMac, pmkid) \
3823 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07003824 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
3825 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
3826 hddLog(VOS_TRACE_LEVEL_INFO, "\n"); \
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003827 }
3828
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07003829#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003830/*
3831 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
3832 * This function is used to notify the supplicant of a new PMKSA candidate.
3833 */
3834int wlan_hdd_cfg80211_pmksa_candidate_notify(
3835 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
3836 int index, bool preauth )
3837{
Jeff Johnsone7245742012-09-05 17:12:55 -07003838#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003839 struct net_device *dev = pAdapter->dev;
3840
3841 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07003842 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003843
3844 if( NULL == pRoamInfo )
3845 {
3846 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL\n", __func__);
3847 return -EINVAL;
3848 }
3849
3850 dump_bssid(pRoamInfo->bssid);
3851 cfg80211_pmksa_candidate_notify(dev, index,
3852 pRoamInfo->bssid, preauth, GFP_KERNEL);
Jeff Johnsone7245742012-09-05 17:12:55 -07003853#endif /* FEATURE_WLAN_OKC */
Jeff Johnson04dd8a82012-06-29 20:41:40 -07003854 return 0;
3855}
3856#endif //FEATURE_WLAN_LFR
3857
Jeff Johnson295189b2012-06-20 16:38:30 -07003858/*
3859 * FUNCTION: hdd_cfg80211_scan_done_callback
3860 * scanning callback function, called after finishing scan
3861 *
3862 */
3863static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
3864 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
3865{
3866 struct net_device *dev = (struct net_device *) pContext;
3867 //struct wireless_dev *wdev = dev->ieee80211_ptr;
3868 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003869 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3870 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07003871 struct cfg80211_scan_request *req = NULL;
3872 int ret = 0;
3873
3874 ENTER();
3875
3876 hddLog(VOS_TRACE_LEVEL_INFO,
3877 "%s called with halHandle = %p, pContext = %p,"
3878 "scanID = %d, returned status = %d\n",
3879 __func__, halHandle, pContext, (int) scanId, (int) status);
3880
3881 //Block on scan req completion variable. Can't wait forever though.
3882 ret = wait_for_completion_interruptible_timeout(
3883 &pScanInfo->scan_req_completion_event,
3884 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
3885 if (!ret)
3886 {
3887 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003888 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003889 }
3890
3891 if(pScanInfo->mScanPending != VOS_TRUE)
3892 {
3893 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07003894 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 }
3896
3897 /* Check the scanId */
3898 if (pScanInfo->scanId != scanId)
3899 {
3900 hddLog(VOS_TRACE_LEVEL_INFO,
3901 "%s called with mismatched scanId pScanInfo->scanId = %d "
3902 "scanId = %d \n", __func__, (int) pScanInfo->scanId,
3903 (int) scanId);
3904 }
3905
Jeff Johnson295189b2012-06-20 16:38:30 -07003906 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
3907 pAdapter);
3908
3909 if (0 > ret)
3910 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
3911
3912
3913 /* If any client wait scan result through WEXT
3914 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003915 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07003916 {
3917 /* The other scan request waiting for current scan finish
3918 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003919 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003920 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003921 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 }
3923 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003924 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07003925 {
3926 struct net_device *dev = pAdapter->dev;
3927 union iwreq_data wrqu;
3928 int we_event;
3929 char *msg;
3930
3931 memset(&wrqu, '\0', sizeof(wrqu));
3932 we_event = SIOCGIWSCAN;
3933 msg = NULL;
3934 wireless_send_event(dev, we_event, &wrqu, msg);
3935 }
3936 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003937 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003938
3939 /* Get the Scan Req */
3940 req = pAdapter->request;
3941
3942 if (!req)
3943 {
3944 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL\n");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003945 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07003946 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07003947 }
3948
3949 /*
3950 * setting up 0, just in case.
3951 */
3952 req->n_ssids = 0;
3953 req->n_channels = 0;
3954 req->ie = 0;
3955
Jeff Johnson295189b2012-06-20 16:38:30 -07003956 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003957 /* Scan is no longer pending */
3958 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003959
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07003960 /*
3961 * cfg80211_scan_done informing NL80211 about completion
3962 * of scanning
3963 */
3964 cfg80211_scan_done(req, false);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003965 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003966
Jeff Johnsone7245742012-09-05 17:12:55 -07003967allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07003968 /* release the wake lock at the end of the scan*/
3969 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003970
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003971 /* Acquire wakelock to handle the case where APP's tries to suspend
3972 * immediatly after the driver gets connect request(i.e after scan)
3973 * from supplicant, this result in app's is suspending and not able
3974 * to process the connect request to AP */
3975 hdd_allow_suspend_timeout(100);
3976
Jeff Johnson295189b2012-06-20 16:38:30 -07003977 EXIT();
3978 return 0;
3979}
3980
3981/*
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08003982 * FUNCTION: hdd_isScanAllowed
3983 * Go through each adapter and check if scan allowed
3984 *
3985 */
3986v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx )
3987{
3988 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3989 hdd_station_ctx_t *pHddStaCtx = NULL;
3990 hdd_adapter_t *pAdapter = NULL;
3991 VOS_STATUS status = 0;
3992 v_U8_t staId = 0;
3993 v_U8_t *staMac = NULL;
3994
3995 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3996
3997 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3998 {
3999 pAdapter = pAdapterNode->pAdapter;
4000
4001 if( pAdapter )
4002 {
4003 hddLog(VOS_TRACE_LEVEL_INFO,
4004 "%s: Adapter with device mode %d exists",
4005 __func__, pAdapter->device_mode);
4006 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4007 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4008 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
4009 {
4010 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4011 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
4012 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
4013 {
4014 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
4015 hddLog(VOS_TRACE_LEVEL_ERROR,
4016 "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the "
4017 "middle of WPS/EAPOL exchange.", __func__,
4018 staMac[0], staMac[1], staMac[2],
4019 staMac[3], staMac[4], staMac[5]);
4020 return VOS_FALSE;
4021 }
4022 }
4023 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
4024 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
4025 {
4026 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
4027 {
4028 if ((pAdapter->aStaInfo[staId].isUsed) &&
4029 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
4030 {
4031 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
4032
4033 hddLog(VOS_TRACE_LEVEL_ERROR,
4034 "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the "
4035 "middle of WPS/EAPOL exchange.", __func__,
4036 staMac[0], staMac[1], staMac[2],
4037 staMac[3], staMac[4], staMac[5]);
4038 return VOS_FALSE;
4039 }
4040 }
4041 }
4042 }
4043 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4044 pAdapterNode = pNext;
4045 }
4046 hddLog(VOS_TRACE_LEVEL_INFO,
4047 "%s: Scan allowed", __func__);
4048 return VOS_TRUE;
4049}
4050
4051/*
Jeff Johnson295189b2012-06-20 16:38:30 -07004052 * FUNCTION: wlan_hdd_cfg80211_scan
4053 * this scan respond to scan trigger and update cfg80211 scan database
4054 * later, scan dump command can be used to recieve scan results
4055 */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08004056int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
4057#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
4058 struct net_device *dev,
4059#endif
4060 struct cfg80211_scan_request *request)
4061{
4062#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4063 struct net_device *dev = request->wdev->netdev;
4064#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004065 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
4066 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4067 hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4068 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4069 tCsrScanRequest scanRequest;
4070 tANI_U8 *channelList = NULL, i;
4071 v_U32_t scanId = 0;
4072 int status = 0;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004073 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07004074#ifdef WLAN_FEATURE_P2P
4075 v_U8_t* pP2pIe = NULL;
4076#endif
4077
4078 ENTER();
4079
4080 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
4081 __func__,pAdapter->device_mode);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004082
4083 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
4084 (eConnectionState_Connecting ==
4085 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) )
4086 {
4087 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004088 "%s: %p(%d) Connection in progress: Scan request denied (EBUSY)", __func__, \
4089 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004090 return -EBUSY;
4091 }
4092
Jeff Johnson295189b2012-06-20 16:38:30 -07004093#ifdef WLAN_BTAMP_FEATURE
4094 //Scan not supported when AMP traffic is on.
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004095 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -07004096 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004097 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004098 "%s: No scanning when AMP is on", __func__);
4099 return -EOPNOTSUPP;
4100 }
4101#endif
4102 //Scan on any other interface is not supported.
4103 if( pAdapter->device_mode == WLAN_HDD_SOFTAP )
4104 {
4105 hddLog(VOS_TRACE_LEVEL_ERROR,
4106 "%s: Not scanning on device_mode = %d",
4107 __func__, pAdapter->device_mode);
4108 return -EOPNOTSUPP;
4109 }
4110
4111 if (TRUE == pScanInfo->mScanPending)
4112 {
4113 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mScanPending is TRUE", __func__);
4114 return -EBUSY;
4115 }
4116
4117 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
4118 {
4119 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4120 "%s:LOGP in Progress. Ignore!!!", __func__);
4121 return -EAGAIN;
4122 }
4123
Mohit Khanna6c52bbf2012-09-11 15:10:12 -07004124 if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress)
4125 {
4126 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4127 "%s:Unloading/Loading in Progress. Ignore!!!", __func__);
4128 return -EAGAIN;
4129 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07004130 //Don't Allow Scan and return busy if Remain On
4131 //Channel and action frame is pending
4132 //Otherwise Cancel Remain On Channel and allow Scan
4133 //If no action frame pending
4134 if(0 != wlan_hdd_check_remain_on_channel(pAdapter))
4135 {
4136 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Remain On Channel Pending", __func__);
4137 return -EBUSY;
4138 }
4139
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
4141 {
4142 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08004143 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004144 return -EAGAIN;
4145 }
4146 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
4147 {
4148 hddLog(VOS_TRACE_LEVEL_WARN,
4149 "%s: MAX TM Level Scan not allowed", __func__);
4150 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4151 return -EBUSY;
4152 }
4153 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
4154
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08004155 /* Check if scan is allowed at this point of time.
4156 */
4157 if (!hdd_isScanAllowed(pHddCtx))
4158 {
4159 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
4160 return -EBUSY;
4161 }
4162
Jeff Johnson295189b2012-06-20 16:38:30 -07004163 vos_mem_zero( &scanRequest, sizeof(scanRequest));
4164
4165 if (NULL != request)
4166 {
4167 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
4168 (int)request->n_ssids);
4169
4170 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
4171 * Becasue of this, driver is assuming that this is not wildcard scan and so
4172 * is not aging out the scan results.
4173 */
Jeff Johnson32d95a32012-09-10 13:15:23 -07004174 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07004175 {
4176 request->n_ssids = 0;
4177 }
4178
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07004179 if ((request->ssids) && (0 < request->n_ssids))
Jeff Johnson295189b2012-06-20 16:38:30 -07004180 {
4181 tCsrSSIDInfo *SsidInfo;
4182 int j;
4183 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
4184 /* Allocate num_ssid tCsrSSIDInfo structure */
4185 SsidInfo = scanRequest.SSIDs.SSIDList =
4186 ( tCsrSSIDInfo *)vos_mem_malloc(
4187 request->n_ssids*sizeof(tCsrSSIDInfo));
4188
4189 if(NULL == scanRequest.SSIDs.SSIDList)
4190 {
4191 hddLog(VOS_TRACE_LEVEL_ERROR,
4192 "memory alloc failed SSIDInfo buffer");
4193 return -ENOMEM;
4194 }
4195
4196 /* copy all the ssid's and their length */
4197 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
4198 {
4199 /* get the ssid length */
4200 SsidInfo->SSID.length = request->ssids[j].ssid_len;
4201 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
4202 SsidInfo->SSID.length);
4203 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
4204 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d: %s",
4205 j, SsidInfo->SSID.ssId);
4206 }
4207 /* set the scan type to active */
4208 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4209 }
4210 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
4211 {
4212 /* set the scan type to active */
4213 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4214 }
4215 else
4216 {
4217 /*Set the scan type to default type, in this case it is ACTIVE*/
4218 scanRequest.scanType = pScanInfo->scan_mode;
4219 }
4220 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
4221 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
4222 }
4223 else
4224 {
4225 /* set the scan type to active */
4226 scanRequest.scanType = eSIR_ACTIVE_SCAN;
4227 vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );
4228
4229 /* set min and max channel time to zero */
4230 scanRequest.minChnTime = 0;
4231 scanRequest.maxChnTime = 0;
4232 }
4233
4234 /* set BSSType to default type */
4235 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
4236
4237 /*TODO: scan the requested channels only*/
4238
4239 /*Right now scanning all the channels */
4240 if( request )
4241 {
4242 if( request->n_channels )
4243 {
4244 channelList = vos_mem_malloc( request->n_channels );
4245 if( NULL == channelList )
4246 {
4247 status = -ENOMEM;
4248 goto free_mem;
4249 }
4250
4251 for( i = 0 ; i < request->n_channels ; i++ )
4252 channelList[i] = request->channels[i]->hw_value;
4253 }
4254
4255 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
4256 scanRequest.ChannelInfo.ChannelList = channelList;
4257
4258 /* set requestType to full scan */
4259 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
Madan Mohan Koyyalamudi8d50f312012-11-27 15:48:57 -08004260
4261 /* Flush the scan results(only p2p beacons) for STA scan and P2P
4262 * search (Flush on both full scan and social scan but not on single
4263 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
4264 */
4265
4266 /* Supplicant does single channel scan after 8-way handshake
4267 * and in that case driver shoudnt flush scan results. If
4268 * driver flushes the scan results here and unfortunately if
4269 * the AP doesnt respond to our probe req then association
4270 * fails which is not desired
4271 */
4272
4273 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
4274 {
4275 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
4276 pAdapter->sessionId );
4277 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004278
4279 if( request->ie_len )
4280 {
4281 /* save this for future association (join requires this) */
4282 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
4283 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
4284 pScanInfo->scanAddIE.length = request->ie_len;
4285
4286 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07004287 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
4288 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07004289 )
4290 {
4291 pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata;
4292 pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length;
4293 }
4294
4295 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
4296 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
4297
4298#ifdef WLAN_FEATURE_P2P
4299 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
4300 request->ie_len);
4301 if (pP2pIe != NULL)
4302 {
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07004303#ifdef WLAN_FEATURE_P2P_DEBUG
4304 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
4305 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
4306 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4307 {
4308 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
4309 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4310 "Go nego completed to Connection is started");
4311 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4312 "for 8way Handshake");
4313 }
4314 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
4315 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
4316 {
4317 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
4318 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
4319 "Disconnected state to Connection is started");
4320 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
4321 "for 4way Handshake");
4322 }
4323#endif
4324
Jeff Johnsone7245742012-09-05 17:12:55 -07004325 /* no_cck will be set during p2p find to disable 11b rates */
4326 if(TRUE == request->no_cck)
Jeff Johnson295189b2012-06-20 16:38:30 -07004327 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004328 hddLog(VOS_TRACE_LEVEL_INFO,
4329 "%s: This is a P2P Search", __func__);
4330 scanRequest.p2pSearch = 1;
Jeff Johnsone7245742012-09-05 17:12:55 -07004331
Jeff Johnsone7245742012-09-05 17:12:55 -07004332 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
4333 {
Madan Mohan Koyyalamudi1b1d9e82012-10-21 11:38:33 -07004334 /* set requestType to P2P Discovery */
4335 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
Jeff Johnsone7245742012-09-05 17:12:55 -07004336 }
4337
4338 /*
4339 Skip Dfs Channel in case of P2P Search
4340 if it is set in ini file
4341 */
4342 if(cfg_param->skipDfsChnlInP2pSearch)
4343 {
4344 scanRequest.skipDfsChnlInP2pSearch = 1;
4345 }
4346 else
4347 {
4348 scanRequest.skipDfsChnlInP2pSearch = 0;
4349 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004350
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 }
4352 }
4353#endif
4354 }
4355 }
4356
4357 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
4358
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004359 /* acquire the wakelock to avoid the apps suspend during the scan. To
4360 * address the following issues.
4361 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
4362 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
4363 * for long time, this result in apps running at full power for long time.
4364 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
4365 * be stuck in full power because of resume BMPS
4366 */
4367 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004368
4369 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 pAdapter->sessionId, &scanRequest, &scanId,
4371 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07004372
Jeff Johnson295189b2012-06-20 16:38:30 -07004373 if (eHAL_STATUS_SUCCESS != status)
4374 {
4375 hddLog(VOS_TRACE_LEVEL_ERROR,
4376 "%s: sme_ScanRequest returned error %d", __func__, status);
4377 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07004378 if(eHAL_STATUS_RESOURCES == status)
4379 {
Madan Mohan Koyyalamudia3fcf142012-10-18 15:01:20 -07004380 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 -07004381 status = -EBUSY;
4382 } else {
4383 status = -EIO;
4384 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07004385 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004386 goto free_mem;
4387 }
4388
4389 pScanInfo->mScanPending = TRUE;
4390 pAdapter->request = request;
4391 pScanInfo->scanId = scanId;
4392
4393 complete(&pScanInfo->scan_req_completion_event);
4394
4395free_mem:
4396 if( scanRequest.SSIDs.SSIDList )
4397 {
4398 vos_mem_free(scanRequest.SSIDs.SSIDList);
4399 }
4400
4401 if( channelList )
4402 vos_mem_free( channelList );
4403
4404 EXIT();
4405
4406 return status;
4407}
4408
4409/*
4410 * FUNCTION: wlan_hdd_cfg80211_connect_start
4411 * This function is used to start the association process
4412 */
4413int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07004414 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07004415{
4416 int status = 0;
4417 hdd_wext_state_t *pWextState;
4418 v_U32_t roamId;
4419 tCsrRoamProfile *pRoamProfile;
4420 eMib_dot11DesiredBssType connectedBssType;
4421 eCsrAuthType RSNAuthType;
4422
4423 ENTER();
4424
4425 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4426
4427 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
4428 {
4429 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
4430 return -EINVAL;
4431 }
4432
4433 pRoamProfile = &pWextState->roamProfile;
4434
4435 if (pRoamProfile)
4436 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004437 int ret = 0;
4438 hdd_station_ctx_t *pHddStaCtx;
4439 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4440 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
4441
4442 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
4443 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
4444 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -07004445 {
4446 /* Issue disconnect to CSR */
4447 INIT_COMPLETION(pAdapter->disconnect_comp_var);
4448 if( eHAL_STATUS_SUCCESS ==
4449 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4450 pAdapter->sessionId,
4451 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
4452 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004453 ret = wait_for_completion_interruptible_timeout(
4454 &pAdapter->disconnect_comp_var,
4455 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4456 if (0 == ret)
4457 {
4458 VOS_ASSERT(0);
4459 }
4460 }
4461 }
4462 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
4463 {
4464 ret = wait_for_completion_interruptible_timeout(
4465 &pAdapter->disconnect_comp_var,
4466 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4467 if (0 == ret)
4468 {
4469 VOS_ASSERT(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07004470 }
4471 }
4472
4473 if (HDD_WMM_USER_MODE_NO_QOS ==
4474 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
4475 {
4476 /*QoS not enabled in cfg file*/
4477 pRoamProfile->uapsd_mask = 0;
4478 }
4479 else
4480 {
4481 /*QoS enabled, update uapsd mask from cfg file*/
4482 pRoamProfile->uapsd_mask =
4483 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
4484 }
4485
4486 pRoamProfile->SSIDs.numOfSSIDs = 1;
4487 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
4488 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
4489 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
4490 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
4491 ssid, ssid_len);
4492
4493 if (bssid)
4494 {
4495 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
4496 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
4497 WNI_CFG_BSSID_LEN);
4498 /* Save BSSID in seperate variable as well, as RoamProfile
4499 BSSID is getting zeroed out in the association process. And in
4500 case of join failure we should send valid BSSID to supplicant
4501 */
4502 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
4503 WNI_CFG_BSSID_LEN);
4504 }
4505
4506 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
4507 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
4508 {
4509 /*set gen ie*/
4510 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
4511 /*set auth*/
4512 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
4513 }
4514 else if ( (pWextState->roamProfile.AuthType.authType[0] ==
4515 eCSR_AUTH_TYPE_OPEN_SYSTEM)
4516 && ((pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4517 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY)
4518 || (pWextState->roamProfile.EncryptionType.encryptionType[0] ==
4519 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
4520 )
4521 {
4522 /*Android UI not having any option to configure the Authentication type to OPEN/SHARED;
4523 * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used
4524 * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/
4525 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType =
4526 eCSR_AUTH_TYPE_AUTOSWITCH;
4527 pWextState->roamProfile.AuthType.authType[0] =
4528 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType;
4529 }
4530#ifdef FEATURE_WLAN_WAPI
4531 if (pAdapter->wapi_info.nWapiMode)
4532 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004533 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004534 switch (pAdapter->wapi_info.wapiAuthMode)
4535 {
4536 case WAPI_AUTH_MODE_PSK:
4537 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004538 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004539 pAdapter->wapi_info.wapiAuthMode);
4540 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
4541 break;
4542 }
4543 case WAPI_AUTH_MODE_CERT:
4544 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004545 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07004546 pAdapter->wapi_info.wapiAuthMode);
4547 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
4548 break;
4549 }
4550 } // End of switch
4551 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
4552 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
4553 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004554 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004555 pRoamProfile->AuthType.numEntries = 1;
4556 pRoamProfile->EncryptionType.numEntries = 1;
4557 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4558 pRoamProfile->mcEncryptionType.numEntries = 1;
4559 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
4560 }
4561 }
4562#endif /* FEATURE_WLAN_WAPI */
4563 pRoamProfile->csrPersona = pAdapter->device_mode;
4564
Jeff Johnson32d95a32012-09-10 13:15:23 -07004565 if( operatingChannel )
4566 {
4567 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
4568 pRoamProfile->ChannelInfo.numOfChannels = 1;
4569 }
4570
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004571 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
4572 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
4573 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
4574 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004575 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
4576 */
4577 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4578 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
4579 eConnectionState_Connecting);
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004580
Jeff Johnson295189b2012-06-20 16:38:30 -07004581 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
4582 pAdapter->sessionId, pRoamProfile, &roamId);
4583
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004584 if( (eHAL_STATUS_SUCCESS != status) &&
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304585 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
4586
4587 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004588 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
4589 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
4590 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304591 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08004592 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05304593 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08004594
4595 pRoamProfile->ChannelInfo.ChannelList = NULL;
4596 pRoamProfile->ChannelInfo.numOfChannels = 0;
4597
Jeff Johnson295189b2012-06-20 16:38:30 -07004598 }
4599 else
4600 {
4601 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
4602 return -EINVAL;
4603 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08004604 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07004605 return status;
4606}
4607
4608/*
4609 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
4610 * This function is used to set the authentication type (OPEN/SHARED).
4611 *
4612 */
4613static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
4614 enum nl80211_auth_type auth_type)
4615{
4616 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4617 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4618
4619 ENTER();
4620
4621 /*set authentication type*/
4622 switch (auth_type)
4623 {
4624 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4625 case NL80211_AUTHTYPE_AUTOMATIC:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07004626#ifdef WLAN_FEATURE_VOWIFI_11R
4627 case NL80211_AUTHTYPE_FT:
4628#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07004629 hddLog(VOS_TRACE_LEVEL_INFO,
4630 "%s: set authentication type to OPEN", __func__);
4631 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4632 break;
4633
4634 case NL80211_AUTHTYPE_SHARED_KEY:
4635 hddLog(VOS_TRACE_LEVEL_INFO,
4636 "%s: set authentication type to SHARED", __func__);
4637 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
4638 break;
4639#ifdef FEATURE_WLAN_CCX
4640 case NL80211_AUTHTYPE_NETWORK_EAP:
4641 hddLog(VOS_TRACE_LEVEL_INFO,
4642 "%s: set authentication type to CCKM WPA", __func__);
4643 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
4644 break;
4645#endif
4646
4647
4648 default:
4649 hddLog(VOS_TRACE_LEVEL_ERROR,
4650 "%s: Unsupported authentication type %d", __func__,
4651 auth_type);
4652 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
4653 return -EINVAL;
4654 }
4655
4656 pWextState->roamProfile.AuthType.authType[0] =
4657 pHddStaCtx->conn_info.authType;
4658 return 0;
4659}
4660
4661/*
4662 * FUNCTION: wlan_hdd_set_akm_suite
4663 * This function is used to set the key mgmt type(PSK/8021x).
4664 *
4665 */
4666static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
4667 u32 key_mgmt
4668 )
4669{
4670 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4671 ENTER();
4672
4673 /*set key mgmt type*/
4674 switch(key_mgmt)
4675 {
4676 case WLAN_AKM_SUITE_PSK:
4677 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
4678 __func__);
4679 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
4680 break;
4681
4682 case WLAN_AKM_SUITE_8021X:
4683 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
4684 __func__);
4685 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
4686 break;
4687#ifdef FEATURE_WLAN_CCX
4688#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
4689#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
4690 case WLAN_AKM_SUITE_CCKM:
4691 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
4692 __func__);
4693 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
4694 break;
4695#endif
4696
4697 default:
4698 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
4699 __func__, key_mgmt);
4700 return -EINVAL;
4701
4702 }
4703 return 0;
4704}
4705
4706/*
4707 * FUNCTION: wlan_hdd_cfg80211_set_cipher
4708 * This function is used to set the encryption type
4709 * (NONE/WEP40/WEP104/TKIP/CCMP).
4710 */
4711static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
4712 u32 cipher,
4713 bool ucast
4714 )
4715{
4716 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4717 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4718 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4719
4720 ENTER();
4721
4722 if (!cipher)
4723 {
4724 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
4725 __func__, cipher);
4726 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4727 }
4728 else
4729 {
4730
4731 /*set encryption method*/
4732 switch (cipher)
4733 {
4734 case IW_AUTH_CIPHER_NONE:
4735 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
4736 break;
4737
4738 case WLAN_CIPHER_SUITE_WEP40:
4739 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4740 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4741 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
4742 else
4743 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
4744 break;
4745
4746 case WLAN_CIPHER_SUITE_WEP104:
4747 if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) &&
4748 (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType))
4749 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
4750 else
4751 encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
4752 break;
4753
4754 case WLAN_CIPHER_SUITE_TKIP:
4755 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
4756 break;
4757
4758 case WLAN_CIPHER_SUITE_CCMP:
4759 encryptionType = eCSR_ENCRYPT_TYPE_AES;
4760 break;
4761#ifdef FEATURE_WLAN_WAPI
4762 case WLAN_CIPHER_SUITE_SMS4:
4763 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
4764 break;
4765#endif
4766
4767#ifdef FEATURE_WLAN_CCX
4768 case WLAN_CIPHER_SUITE_KRK:
4769 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
4770 break;
4771#endif
4772 default:
4773 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
4774 __func__, cipher);
4775 return -EOPNOTSUPP;
4776 }
4777 }
4778
4779 if (ucast)
4780 {
4781 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
4782 __func__, encryptionType);
4783 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
4784 pWextState->roamProfile.EncryptionType.numEntries = 1;
4785 pWextState->roamProfile.EncryptionType.encryptionType[0] =
4786 encryptionType;
4787 }
4788 else
4789 {
4790 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
4791 __func__, encryptionType);
4792 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
4793 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
4794 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
4795 }
4796
4797 return 0;
4798}
4799
4800
4801/*
4802 * FUNCTION: wlan_hdd_cfg80211_set_ie
4803 * This function is used to parse WPA/RSN IE's.
4804 */
4805int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
4806 u8 *ie,
4807 size_t ie_len
4808 )
4809{
4810 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4811 u8 *genie = ie;
4812 v_U16_t remLen = ie_len;
4813#ifdef FEATURE_WLAN_WAPI
4814 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
4815 u16 *tmp;
4816 v_U16_t akmsuiteCount;
4817 int *akmlist;
4818#endif
4819 ENTER();
4820
4821 /* clear previous assocAddIE */
4822 pWextState->assocAddIE.length = 0;
4823 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
4824
4825 while (remLen >= 2)
4826 {
4827 v_U16_t eLen = 0;
4828 v_U8_t elementId;
4829 elementId = *genie++;
4830 eLen = *genie++;
4831 remLen -= 2;
4832
4833 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n",
4834 __func__, elementId, eLen);
4835
4836 switch ( elementId )
4837 {
4838 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004839 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 -07004840 {
4841 hddLog(VOS_TRACE_LEVEL_ERROR,
4842 "%s: Invalid WPA IE", __func__);
4843 return -EINVAL;
4844 }
4845 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
4846 {
4847 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4848 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
4849 __func__, eLen + 2);
4850
4851 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4852 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004853 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
4854 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004855 VOS_ASSERT(0);
4856 return -ENOMEM;
4857 }
4858 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4859 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4860 pWextState->assocAddIE.length += eLen + 2;
4861
4862 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
4863 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4864 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4865 }
4866 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
4867 {
4868 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
4869 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4870 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
4871 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
4872 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
4873 }
4874#ifdef WLAN_FEATURE_P2P
4875 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
4876 P2P_OUI_TYPE_SIZE))
4877 /*Consider P2P IE, only for P2P Client */
4878 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4879 {
4880 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4881 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
4882 __func__, eLen + 2);
4883
4884 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4885 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004886 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4887 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004888 VOS_ASSERT(0);
4889 return -ENOMEM;
4890 }
4891 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
4892 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4893 pWextState->assocAddIE.length += eLen + 2;
4894
4895 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4896 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4897 }
4898#endif
4899#ifdef WLAN_FEATURE_WFD
4900 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
4901 WFD_OUI_TYPE_SIZE))
4902 /*Consider WFD IE, only for P2P Client */
4903 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4904 {
4905 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4906 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
4907 __func__, eLen + 2);
4908
4909 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4910 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004911 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4912 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07004913 VOS_ASSERT(0);
4914 return -ENOMEM;
4915 }
4916 // WFD IE is saved to Additional IE ; it should be accumulated to handle
4917 // WPS IE + P2P IE + WFD IE
4918 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4919 pWextState->assocAddIE.length += eLen + 2;
4920
4921 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4922 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4923 }
4924#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004925 /* Appending HS 2.0 Indication Element in Assiciation Request */
4926 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004927 HS20_OUI_TYPE_SIZE)) )
4928 {
4929 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4930 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
4931 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004932
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004933 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4934 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004935 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4936 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004937 VOS_ASSERT(0);
4938 return -ENOMEM;
4939 }
4940 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4941 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004942
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07004943 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4944 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4945 }
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004946
Jeff Johnson295189b2012-06-20 16:38:30 -07004947 break;
4948 case DOT11F_EID_RSN:
4949 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
4950 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
4951 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
4952 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
4953 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
4954 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004955 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
4956 case DOT11F_EID_EXTCAP:
4957 {
4958 v_U16_t curAddIELen = pWextState->assocAddIE.length;
4959 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
4960 __func__, eLen + 2);
4961
4962 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
4963 {
Jeff Johnson902c9832012-12-10 14:28:09 -08004964 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
4965 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07004966 VOS_ASSERT(0);
4967 return -ENOMEM;
4968 }
4969 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
4970 pWextState->assocAddIE.length += eLen + 2;
4971
4972 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
4973 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
4974 break;
4975 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004976#ifdef FEATURE_WLAN_WAPI
4977 case WLAN_EID_WAPI:
4978 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
4979 hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n",
4980 pAdapter->wapi_info.nWapiMode);
4981 tmp = (u16 *)ie;
4982 tmp = tmp + 2; // Skip element Id and Len, Version
4983 akmsuiteCount = WPA_GET_LE16(tmp);
4984 tmp = tmp + 1;
4985 akmlist = (int *)(tmp);
4986 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
4987 {
4988 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
4989 }
4990 else
4991 {
4992 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count\n");
4993 VOS_ASSERT(0);
4994 return -EINVAL;
4995 }
4996
4997 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
4998 {
4999 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005000 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005001 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
5002 }
5003 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
5004 {
5005 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005006 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005007 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
5008 }
5009 break;
5010#endif
5011 default:
5012 hddLog (VOS_TRACE_LEVEL_ERROR,
5013 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07005014 /* when Unknown IE is received we should break and continue
5015 * to the next IE in the buffer instead we were returning
5016 * so changing this to break */
5017 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005018 }
5019 genie += eLen;
5020 remLen -= eLen;
5021 }
5022 EXIT();
5023 return 0;
5024}
5025
5026/*
5027 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5028 * This function is used to initialize the security
5029 * parameters during connect operation.
5030 */
5031int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
5032 struct cfg80211_connect_params *req
5033 )
5034{
5035 int status = 0;
5036 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5037 ENTER();
5038
5039 /*set wpa version*/
5040 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5041
5042 if (req->crypto.wpa_versions)
5043 {
5044 if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
5045 && ( (req->ie_len)
5046 && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) )
5047 // Make sure that it is including a WPA IE.
5048 /* Currently NL is putting WPA version 1 even for open,
5049 * since p2p ie is also put in same buffer.
5050 * */
5051 {
5052 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5053 }
5054 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
5055 {
5056 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5057 }
5058 }
5059
5060 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
5061 pWextState->wpaVersion);
5062
5063 /*set authentication type*/
5064 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
5065
5066 if (0 > status)
5067 {
5068 hddLog(VOS_TRACE_LEVEL_ERROR,
5069 "%s: failed to set authentication type ", __func__);
5070 return status;
5071 }
5072
5073 /*set key mgmt type*/
5074 if (req->crypto.n_akm_suites)
5075 {
5076 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
5077 if (0 > status)
5078 {
5079 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
5080 __func__);
5081 return status;
5082 }
5083 }
5084
5085 /*set pairwise cipher type*/
5086 if (req->crypto.n_ciphers_pairwise)
5087 {
5088 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
5089 req->crypto.ciphers_pairwise[0], true);
5090 if (0 > status)
5091 {
5092 hddLog(VOS_TRACE_LEVEL_ERROR,
5093 "%s: failed to set unicast cipher type", __func__);
5094 return status;
5095 }
5096 }
5097 else
5098 {
5099 /*Reset previous cipher suite to none*/
5100 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
5101 if (0 > status)
5102 {
5103 hddLog(VOS_TRACE_LEVEL_ERROR,
5104 "%s: failed to set unicast cipher type", __func__);
5105 return status;
5106 }
5107 }
5108
5109 /*set group cipher type*/
5110 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
5111 false);
5112
5113 if (0 > status)
5114 {
5115 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
5116 __func__);
5117 return status;
5118 }
5119
5120 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
5121 if (req->ie_len)
5122 {
5123 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
5124 if ( 0 > status)
5125 {
5126 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
5127 __func__);
5128 return status;
5129 }
5130 }
5131
5132 /*incase of WEP set default key information*/
5133 if (req->key && req->key_len)
5134 {
5135 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
5136 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
5137 )
5138 {
5139 if ( IW_AUTH_KEY_MGMT_802_1X
5140 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
5141 {
5142 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
5143 __func__);
5144 return -EOPNOTSUPP;
5145 }
5146 else
5147 {
5148 u8 key_len = req->key_len;
5149 u8 key_idx = req->key_idx;
5150
5151 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
5152 && (CSR_MAX_NUM_KEY > key_idx)
5153 )
5154 {
5155 hddLog(VOS_TRACE_LEVEL_INFO,
5156 "%s: setting default wep key, key_idx = %hu key_len %hu",
5157 __func__, key_idx, key_len);
5158 vos_mem_copy(
5159 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
5160 req->key, key_len);
5161 pWextState->roamProfile.Keys.KeyLength[key_idx] =
5162 (u8)key_len;
5163 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
5164 }
5165 }
5166 }
5167 }
5168
5169 return status;
5170}
5171
5172/*
5173 * FUNCTION: wlan_hdd_cfg80211_set_privacy
5174 * This function is used to initialize the security
5175 * parameters during connect operation.
5176 */
5177static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
5178 struct net_device *ndev,
5179 struct cfg80211_connect_params *req
5180 )
5181{
5182 int status = 0;
5183 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
5184 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
5185 hdd_context_t *pHddCtx = NULL;
5186
5187 ENTER();
5188
5189 hddLog(VOS_TRACE_LEVEL_INFO,
5190 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5191
5192 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5193 {
5194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5195 "%s:LOGP in Progress. Ignore!!!", __func__);
5196 return -EAGAIN;
5197 }
5198
5199#ifdef WLAN_BTAMP_FEATURE
5200 //Infra connect not supported when AMP traffic is on.
5201 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
5202 {
5203 hddLog(VOS_TRACE_LEVEL_ERROR,
5204 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005205 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -07005206 }
5207#endif
5208 /*initialise security parameters*/
5209 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
5210
5211 if ( 0 > status)
5212 {
5213 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
5214 __func__);
5215 return status;
5216 }
5217
5218 //If Device Mode is Station Concurrent Sessions Exit BMps
Jeff Johnsona8a1a482012-12-12 16:49:33 -08005219 //P2P Mode will be taken care in Open/close adapter
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
5221 (vos_concurrent_sessions_running()))
5222 {
5223 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5224
5225 if (NULL != pVosContext)
5226 {
5227 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5228 if(NULL != pHddCtx)
5229 {
5230 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
5231 }
5232 }
5233 }
5234
Mohit Khanna765234a2012-09-11 15:08:35 -07005235 if ( req->channel )
5236 {
5237 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5238 req->ssid_len, req->bssid,
5239 req->channel->hw_value);
5240 }
5241 else
5242 {
5243 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
5244 req->ssid_len, req->bssid,
5245 0);
5246 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005247
5248 if (0 > status)
5249 {
5250 //ReEnable BMPS if disabled
5251 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
5252 (NULL != pHddCtx))
5253 {
5254 //ReEnable Bmps and Imps back
5255 hdd_enable_bmps_imps(pHddCtx);
5256 }
5257
5258 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5259 return status;
5260 }
5261 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE;
5262 EXIT();
5263 return status;
5264}
5265
5266
5267/*
5268 * FUNCTION: wlan_hdd_cfg80211_disconnect
5269 * This function is used to issue a disconnect request to SME
5270 */
5271static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
5272 struct net_device *dev,
5273 u16 reason
5274 )
5275{
5276 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5277 tCsrRoamProfile *pRoamProfile =
5278 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
5279 int status = 0;
5280 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5281
5282 ENTER();
5283
5284 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",
5285 __func__,pAdapter->device_mode);
5286
5287 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
5288 __func__, reason);
5289
5290 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
5291 {
5292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5293 "%s:LOGP in Progress. Ignore!!!",__func__);
5294 return -EAGAIN;
5295 }
5296 if (NULL != pRoamProfile)
5297 {
5298 /*issue disconnect request to SME, if station is in connected state*/
5299 if (pHddStaCtx->conn_info.connState == eConnectionState_Associated)
5300 {
5301 eCsrRoamDisconnectReason reasonCode =
5302 eCSR_DISCONNECT_REASON_UNSPECIFIED;
5303 switch(reason)
5304 {
5305 case WLAN_REASON_MIC_FAILURE:
5306 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
5307 break;
5308
5309 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
5310 case WLAN_REASON_DISASSOC_AP_BUSY:
5311 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
5312 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
5313 break;
5314
5315 case WLAN_REASON_PREV_AUTH_NOT_VALID:
5316 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
5317 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
5318 break;
5319
5320 case WLAN_REASON_DEAUTH_LEAVING:
5321 default:
5322 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
5323 break;
5324 }
5325 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5326 (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE;
5327 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5328
5329 /*issue disconnect*/
5330 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
5331 pAdapter->sessionId, reasonCode);
5332
5333 if ( 0 != status)
5334 {
5335 hddLog(VOS_TRACE_LEVEL_ERROR,
5336 "%s csrRoamDisconnect failure, returned %d \n",
5337 __func__, (int)status );
5338 return -EINVAL;
5339 }
5340
5341 wait_for_completion_interruptible_timeout(
5342 &pAdapter->disconnect_comp_var,
5343 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5344
5345
5346 /*stop tx queues*/
5347 netif_tx_disable(dev);
5348 netif_carrier_off(dev);
5349 }
5350 }
5351 else
5352 {
5353 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
5354 }
5355
5356 return status;
5357}
5358
5359/*
5360 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
5361 * This function is used to initialize the security
5362 * settings in IBSS mode.
5363 */
5364static int wlan_hdd_cfg80211_set_privacy_ibss(
5365 hdd_adapter_t *pAdapter,
5366 struct cfg80211_ibss_params *params
5367 )
5368{
5369 int status = 0;
5370 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5371 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
5372 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5373
5374 ENTER();
5375
5376 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
5377
5378 if (params->ie_len && ( NULL != params->ie) )
5379 {
5380 if (WLAN_EID_RSN == params->ie[0])
5381 {
5382 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
5383 encryptionType = eCSR_ENCRYPT_TYPE_AES;
5384 }
5385 else
5386 {
5387 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
5388 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
5389 }
5390 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
5391
5392 if (0 > status)
5393 {
5394 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
5395 __func__);
5396 return status;
5397 }
5398 }
5399
5400 pWextState->roamProfile.AuthType.authType[0] =
5401 pHddStaCtx->conn_info.authType =
5402 eCSR_AUTH_TYPE_OPEN_SYSTEM;
5403
5404 if (params->privacy)
5405 {
5406 /* Security enabled IBSS, At this time there is no information available
5407 * about the security paramters, so initialise the encryption type to
5408 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
5409 * The correct security parameters will be updated later in
5410 * wlan_hdd_cfg80211_add_key */
5411 /* Hal expects encryption type to be set inorder
5412 *enable privacy bit in beacons */
5413
5414 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
5415 }
5416
5417 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
5418 pWextState->roamProfile.EncryptionType.numEntries = 1;
5419 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
5420
5421 return status;
5422}
5423
5424/*
5425 * FUNCTION: wlan_hdd_cfg80211_join_ibss
5426 * This function is used to create/join an IBSS
5427 */
5428static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
5429 struct net_device *dev,
5430 struct cfg80211_ibss_params *params
5431 )
5432{
5433 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5434 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5435 tCsrRoamProfile *pRoamProfile;
5436 int status;
5437 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5438
5439 ENTER();
5440
5441 hddLog(VOS_TRACE_LEVEL_INFO,
5442 "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5443
5444 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5445 {
5446 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5447 "%s:LOGP in Progress. Ignore!!!", __func__);
5448 return -EAGAIN;
5449 }
5450
5451 if (NULL == pWextState)
5452 {
5453 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5454 __func__);
5455 return -EIO;
5456 }
5457
5458 pRoamProfile = &pWextState->roamProfile;
5459
5460 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
5461 {
5462 hddLog (VOS_TRACE_LEVEL_ERROR,
5463 "%s Interface type is not set to IBSS \n", __func__);
5464 return -EINVAL;
5465 }
5466
5467 /* Set Channel */
5468 if (NULL != params->channel)
5469 {
5470 u8 channelNum;
5471 if (IEEE80211_BAND_5GHZ == params->channel->band)
5472 {
5473 hddLog(VOS_TRACE_LEVEL_ERROR,
5474 "%s: IBSS join is called with unsupported band %d",
5475 __func__, params->channel->band);
5476 return -EOPNOTSUPP;
5477 }
5478
5479 /* Get channel number */
5480 channelNum =
5481 ieee80211_frequency_to_channel(params->channel->center_freq);
5482
5483 /*TODO: use macro*/
5484 if (14 >= channelNum)
5485 {
5486 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5487 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5488 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5489 int indx;
5490
5491 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5492 validChan, &numChans))
5493 {
5494 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
5495 __func__);
5496 return -EOPNOTSUPP;
5497 }
5498
5499 for (indx = 0; indx < numChans; indx++)
5500 {
5501 if (channelNum == validChan[indx])
5502 {
5503 break;
5504 }
5505 }
5506 if (indx >= numChans)
5507 {
5508 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
5509 __func__, channelNum);
5510 return -EINVAL;
5511 }
5512 /* Set the Operational Channel */
5513 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
5514 channelNum);
5515 pRoamProfile->ChannelInfo.numOfChannels = 1;
5516 pHddStaCtx->conn_info.operationChannel = channelNum;
5517 pRoamProfile->ChannelInfo.ChannelList =
5518 &pHddStaCtx->conn_info.operationChannel;
5519 }
5520 else
5521 {
5522 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu",
5523 __func__, channelNum);
5524 return -EINVAL;
5525 }
5526 }
5527
5528 /* Initialize security parameters */
5529 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
5530 if (status < 0)
5531 {
5532 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
5533 __func__);
5534 return status;
5535 }
5536
5537 /* Issue connect start */
5538 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Jeff Johnson32d95a32012-09-10 13:15:23 -07005539 params->ssid_len, params->bssid, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -07005540
5541 if (0 > status)
5542 {
5543 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
5544 return status;
5545 }
5546
5547 return 0;
5548}
5549
5550/*
5551 * FUNCTION: wlan_hdd_cfg80211_leave_ibss
5552 * This function is used to leave an IBSS
5553 */
5554static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
5555 struct net_device *dev
5556 )
5557{
5558 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5559 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5560 tCsrRoamProfile *pRoamProfile;
5561
5562 ENTER();
5563
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005564 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5565 {
5566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5567 "%s:LOGP in Progress. Ignore!!!", __func__);
5568 return -EAGAIN;
5569 }
5570
Jeff Johnson295189b2012-06-20 16:38:30 -07005571 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode);
5572 if (NULL == pWextState)
5573 {
5574 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n",
5575 __func__);
5576 return -EIO;
5577 }
5578
5579 pRoamProfile = &pWextState->roamProfile;
5580
5581 /* Issue disconnect only if interface type is set to IBSS */
5582 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
5583 {
5584 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
5585 __func__);
5586 return -EINVAL;
5587 }
5588
5589 /* Issue Disconnect request */
5590 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5591 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
5592 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5593
5594 return 0;
5595}
5596
5597/*
5598 * FUNCTION: wlan_hdd_cfg80211_set_wiphy_params
5599 * This function is used to set the phy parameters
5600 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
5601 */
5602static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
5603 u32 changed)
5604{
5605 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5606 tHalHandle hHal = pHddCtx->hHal;
5607
5608 ENTER();
5609
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005610 if ( pHddCtx->isLogpInProgress )
5611 {
5612 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5613 "%s:LOGP in Progress. Ignore!!!", __func__);
5614 return -EAGAIN;
5615 }
5616
Jeff Johnson295189b2012-06-20 16:38:30 -07005617 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
5618 {
5619 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
5620 WNI_CFG_RTS_THRESHOLD_STAMAX :
5621 wiphy->rts_threshold;
5622
5623 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
5624 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
5625 {
5626 hddLog(VOS_TRACE_LEVEL_ERROR,
5627 "%s: Invalid RTS Threshold value %hu",
5628 __func__, rts_threshold);
5629 return -EINVAL;
5630 }
5631
5632 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
5633 rts_threshold, ccmCfgSetCallback,
5634 eANI_BOOLEAN_TRUE))
5635 {
5636 hddLog(VOS_TRACE_LEVEL_ERROR,
5637 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
5638 __func__, rts_threshold);
5639 return -EIO;
5640 }
5641
5642 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
5643 rts_threshold);
5644 }
5645
5646 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
5647 {
5648 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
5649 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
5650 wiphy->frag_threshold;
5651
5652 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
5653 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
5654 {
5655 hddLog(VOS_TRACE_LEVEL_ERROR,
5656 "%s: Invalid frag_threshold value %hu", __func__,
5657 frag_threshold);
5658 return -EINVAL;
5659 }
5660
5661 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
5662 frag_threshold, ccmCfgSetCallback,
5663 eANI_BOOLEAN_TRUE))
5664 {
5665 hddLog(VOS_TRACE_LEVEL_ERROR,
5666 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
5667 __func__, frag_threshold);
5668 return -EIO;
5669 }
5670
5671 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
5672 frag_threshold);
5673 }
5674
5675 if ((changed & WIPHY_PARAM_RETRY_SHORT)
5676 || (changed & WIPHY_PARAM_RETRY_LONG))
5677 {
5678 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
5679 wiphy->retry_short :
5680 wiphy->retry_long;
5681
5682 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
5683 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
5684 {
5685 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
5686 __func__, retry_value);
5687 return -EINVAL;
5688 }
5689
5690 if (changed & WIPHY_PARAM_RETRY_SHORT)
5691 {
5692 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
5693 retry_value, ccmCfgSetCallback,
5694 eANI_BOOLEAN_TRUE))
5695 {
5696 hddLog(VOS_TRACE_LEVEL_ERROR,
5697 "%s: ccmCfgSetInt failed for long retry count %hu",
5698 __func__, retry_value);
5699 return -EIO;
5700 }
5701 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
5702 __func__, retry_value);
5703 }
5704 else if (changed & WIPHY_PARAM_RETRY_SHORT)
5705 {
5706 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
5707 retry_value, ccmCfgSetCallback,
5708 eANI_BOOLEAN_TRUE))
5709 {
5710 hddLog(VOS_TRACE_LEVEL_ERROR,
5711 "%s: ccmCfgSetInt failed for short retry count %hu",
5712 __func__, retry_value);
5713 return -EIO;
5714 }
5715 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
5716 __func__, retry_value);
5717 }
5718 }
5719
5720 return 0;
5721}
5722
5723/*
5724 * FUNCTION: wlan_hdd_cfg80211_set_txpower
5725 * This function is used to set the txpower
5726 */
5727static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
5728#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
5729 enum tx_power_setting type,
5730#else
5731 enum nl80211_tx_power_setting type,
5732#endif
5733 int dbm)
5734{
5735 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5736 tHalHandle hHal = pHddCtx->hHal;
5737 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5738 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5739
5740 ENTER();
5741
5742 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
5743 dbm, ccmCfgSetCallback,
5744 eANI_BOOLEAN_TRUE))
5745 {
5746 hddLog(VOS_TRACE_LEVEL_ERROR,
5747 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
5748 return -EIO;
5749 }
5750
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005751 if ( pHddCtx->isLogpInProgress )
5752 {
5753 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5754 "%s:LOGP in Progress. Ignore!!!", __func__);
5755 return -EAGAIN;
5756 }
5757
Jeff Johnson295189b2012-06-20 16:38:30 -07005758 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
5759 dbm);
5760
5761 switch(type)
5762 {
5763 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
5764 /* Fall through */
5765 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
5766 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
5767 {
5768 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
5769 __func__);
5770 return -EIO;
5771 }
5772 break;
5773 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
5774 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
5775 __func__);
5776 return -EOPNOTSUPP;
5777 break;
5778 default:
5779 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
5780 __func__, type);
5781 return -EIO;
5782 }
5783
5784 return 0;
5785}
5786
5787/*
5788 * FUNCTION: wlan_hdd_cfg80211_get_txpower
5789 * This function is used to read the txpower
5790 */
5791static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
5792{
5793
5794 hdd_adapter_t *pAdapter;
5795 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5796
Jeff Johnsone7245742012-09-05 17:12:55 -07005797 ENTER();
5798
Jeff Johnson295189b2012-06-20 16:38:30 -07005799 if (NULL == pHddCtx)
5800 {
5801 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
5802 *dbm = 0;
5803 return -ENOENT;
5804 }
5805
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005806 if ( pHddCtx->isLogpInProgress )
5807 {
5808 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5809 "%s:LOGP in Progress. Ignore!!!", __func__);
5810 return -EAGAIN;
5811 }
5812
Jeff Johnson295189b2012-06-20 16:38:30 -07005813 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5814 if (NULL == pAdapter)
5815 {
5816 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
5817 return -ENOENT;
5818 }
5819
5820 wlan_hdd_get_classAstats(pAdapter);
5821 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
5822
Jeff Johnsone7245742012-09-05 17:12:55 -07005823 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 return 0;
5825}
5826
5827static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5828 u8* mac, struct station_info *sinfo)
5829{
5830 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
5831 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5832 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
5833 tANI_U8 rate_flags;
5834
5835 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
5836 hdd_config_t *pCfg = pHddCtx->cfg_ini;
5837 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5838
5839 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
5840 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
5841 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
5842 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
5843 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
5844 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
5845 tANI_U16 maxRate = 0;
5846 tANI_U16 myRate;
5847 tANI_U16 currentRate = 0;
5848 tANI_U8 maxSpeedMCS = 0;
5849 tANI_U8 maxMCSIdx = 0;
5850 tANI_U8 rateFlag = 1;
5851 tANI_U8 i, j, rssidx;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005852 tANI_U16 temp;
Jeff Johnson295189b2012-06-20 16:38:30 -07005853
Jeff Johnsone7245742012-09-05 17:12:55 -07005854 ENTER();
5855
Jeff Johnson295189b2012-06-20 16:38:30 -07005856 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
5857 (0 == ssidlen))
5858 {
5859 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
5860 " Invalid ssidlen, %d", __func__, ssidlen);
5861 /*To keep GUI happy*/
5862 return 0;
5863 }
5864
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005865 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
5866 {
5867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5868 "%s:LOGP in Progress. Ignore!!!", __func__);
5869 return -EAGAIN;
5870 }
5871
Jeff Johnson295189b2012-06-20 16:38:30 -07005872 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
5873 sinfo->filled |= STATION_INFO_SIGNAL;
5874
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07005875 wlan_hdd_get_station_stats(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
5877
5878 //convert to the UI units of 100kbps
5879 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
5880
5881#ifdef LINKSPEED_DEBUG_ENABLED
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005882 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 -07005883 sinfo->signal,
5884 pCfg->reportMaxLinkSpeed,
5885 myRate,
5886 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005887 (int) pCfg->linkSpeedRssiMid,
5888 (int) pCfg->linkSpeedRssiLow,
5889 (int) rate_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005890#endif //LINKSPEED_DEBUG_ENABLED
5891
5892 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
5893 {
5894 // we do not want to necessarily report the current speed
5895 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
5896 {
5897 // report the max possible speed
5898 rssidx = 0;
5899 }
5900 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
5901 {
5902 // report the max possible speed with RSSI scaling
5903 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
5904 {
5905 // report the max possible speed
5906 rssidx = 0;
5907 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005908 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -07005909 {
5910 // report middle speed
5911 rssidx = 1;
5912 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005913 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
5914 {
5915 // report middle speed
5916 rssidx = 2;
5917 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005918 else
5919 {
5920 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005921 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -07005922 }
5923 }
5924 else
5925 {
5926 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
5927 hddLog(VOS_TRACE_LEVEL_ERROR,
5928 "%s: Invalid value for reportMaxLinkSpeed: %u",
5929 __func__, pCfg->reportMaxLinkSpeed);
5930 rssidx = 0;
5931 }
5932
5933 maxRate = 0;
5934
5935 /* Get Basic Rate Set */
5936 ccmCfgGetStr(hHal, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates, &ORLeng);
5937 for (i = 0; i < ORLeng; i++)
5938 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005939 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005940 {
5941 /* Validate Rate Set */
5942 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
5943 {
5944 currentRate = supported_data_rate[j].supported_rate[rssidx];
5945 break;
5946 }
5947 }
5948 /* Update MAX rate */
5949 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5950 }
5951
5952 /* Get Extended Rate Set */
5953 ccmCfgGetStr(hHal, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedRates, &ERLeng);
5954 for (i = 0; i < ERLeng; i++)
5955 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005956 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005957 {
5958 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
5959 {
5960 currentRate = supported_data_rate[j].supported_rate[rssidx];
5961 break;
5962 }
5963 }
5964 /* Update MAX rate */
5965 maxRate = (currentRate > maxRate)?currentRate:maxRate;
5966 }
5967
5968 /* Get MCS Rate Set -- but only if we are connected at MCS
5969 rates or if we are always reporting max speed or if we have
5970 good rssi */
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07005971 if ((0 == rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -07005972 {
5973 ccmCfgGetStr(hHal, WNI_CFG_CURRENT_MCS_SET, MCSRates, &MCSLeng);
5974 rateFlag = 0;
5975 if (rate_flags & eHAL_TX_RATE_HT40)
5976 {
5977 rateFlag |= 1;
5978 }
5979 if (rate_flags & eHAL_TX_RATE_SGI)
5980 {
5981 rateFlag |= 2;
5982 }
5983
5984 for (i = 0; i < MCSLeng; i++)
5985 {
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005986 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
5987 for (j = 0; j < temp; j++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005988 {
5989 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
5990 {
5991 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
5992 break;
5993 }
5994 }
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005995 if ((j < temp) && (currentRate > maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07005996 {
5997 maxRate = currentRate;
5998 maxSpeedMCS = 1;
5999 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
6000 }
6001 }
6002 }
6003
6004 // make sure we report a value at least as big as our current rate
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006005 if (((maxRate < myRate) && (0 == rssidx)) ||
6006 (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -07006007 {
6008 maxRate = myRate;
6009 if (rate_flags & eHAL_TX_RATE_LEGACY)
6010 {
6011 maxSpeedMCS = 0;
6012 }
6013 else
6014 {
6015 maxSpeedMCS = 1;
6016 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6017 }
6018 }
6019
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -07006020 if ((!maxSpeedMCS) || (0 != rssidx))
Jeff Johnson295189b2012-06-20 16:38:30 -07006021 {
6022 sinfo->txrate.legacy = maxRate;
6023#ifdef LINKSPEED_DEBUG_ENABLED
6024 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
6025#endif //LINKSPEED_DEBUG_ENABLED
6026 }
6027 else
6028 {
6029 sinfo->txrate.mcs = maxMCSIdx;
6030 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6031 if (rate_flags & eHAL_TX_RATE_SGI)
6032 {
6033 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6034 }
6035 if (rate_flags & eHAL_TX_RATE_HT40)
6036 {
6037 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6038 }
6039#ifdef LINKSPEED_DEBUG_ENABLED
6040 pr_info("Reporting MCS rate %d flags %x\n",
6041 sinfo->txrate.mcs,
6042 sinfo->txrate.flags );
6043#endif //LINKSPEED_DEBUG_ENABLED
6044 }
6045 }
6046 else
6047 {
6048 // report current rate instead of max rate
6049
6050 if (rate_flags & eHAL_TX_RATE_LEGACY)
6051 {
6052 //provide to the UI in units of 100kbps
6053 sinfo->txrate.legacy = myRate;
6054#ifdef LINKSPEED_DEBUG_ENABLED
6055 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
6056#endif //LINKSPEED_DEBUG_ENABLED
6057 }
6058 else
6059 {
6060 //must be MCS
6061 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
6062 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
6063 if (rate_flags & eHAL_TX_RATE_SGI)
6064 {
6065 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
6066 }
6067 if (rate_flags & eHAL_TX_RATE_HT40)
6068 {
6069 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
6070 }
6071#ifdef LINKSPEED_DEBUG_ENABLED
6072 pr_info("Reporting actual MCS rate %d flags %x\n",
6073 sinfo->txrate.mcs,
6074 sinfo->txrate.flags );
6075#endif //LINKSPEED_DEBUG_ENABLED
6076 }
6077 }
6078 sinfo->filled |= STATION_INFO_TX_BITRATE;
6079
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -07006080 sinfo->tx_packets =
6081 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
6082 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
6083 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
6084 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
6085
6086 sinfo->tx_retries =
6087 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
6088 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
6089 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
6090 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
6091
6092 sinfo->tx_failed =
6093 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
6094 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
6095 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
6096 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
6097
6098 sinfo->filled |=
6099 STATION_INFO_TX_PACKETS |
6100 STATION_INFO_TX_RETRIES |
6101 STATION_INFO_TX_FAILED;
6102
6103 EXIT();
6104 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006105}
6106
6107static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
6108 struct net_device *dev, bool mode, v_SINT_t timeout)
6109{
6110 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6111 VOS_STATUS vos_status;
6112
Jeff Johnsone7245742012-09-05 17:12:55 -07006113 ENTER();
6114
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 if (NULL == pAdapter)
6116 {
6117 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6118 return -ENODEV;
6119 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006120 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6121 {
6122 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6123 "%s:LOGP in Progress. Ignore!!!", __func__);
6124 return -EAGAIN;
6125 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006126
6127 /**The get power cmd from the supplicant gets updated by the nl only
6128 *on successful execution of the function call
6129 *we are oppositely mapped w.r.t mode in the driver
6130 **/
6131 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
6132
Jeff Johnsone7245742012-09-05 17:12:55 -07006133 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006134 if (VOS_STATUS_E_FAILURE == vos_status)
6135 {
6136 return -EINVAL;
6137 }
6138 return 0;
6139}
6140
6141
6142#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6143static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
6144 struct net_device *netdev,
6145 u8 key_index)
6146{
Jeff Johnsone7245742012-09-05 17:12:55 -07006147 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 return 0;
6149}
6150#endif //LINUX_VERSION_CODE
6151
6152#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
6153static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6154 struct net_device *dev,
6155 struct ieee80211_txq_params *params)
6156{
Jeff Johnsone7245742012-09-05 17:12:55 -07006157 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006158 return 0;
6159}
6160#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6161static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
6162 struct ieee80211_txq_params *params)
6163{
Jeff Johnsone7245742012-09-05 17:12:55 -07006164 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006165 return 0;
6166}
6167#endif //LINUX_VERSION_CODE
6168
6169static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
6170 struct net_device *dev, u8 *mac)
6171{
6172 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006173 VOS_STATUS vos_status;
6174 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006175
Jeff Johnsone7245742012-09-05 17:12:55 -07006176 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006177 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6178 {
6179 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6180 return -EINVAL;
6181 }
6182
6183 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6184 {
6185 hddLog( LOGE,
6186 "%s: Wlan Load/Unload is in progress", __func__);
6187 return -EBUSY;
6188 }
6189
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006190 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6191 {
6192 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6193 "%s:LOGP in Progress. Ignore!!!", __func__);
6194 return -EAGAIN;
6195 }
6196
Jeff Johnson295189b2012-06-20 16:38:30 -07006197 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
6198#ifdef WLAN_FEATURE_P2P
6199 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6200#endif
6201 )
6202 {
6203 if( NULL == mac )
6204 {
6205 v_U16_t i;
6206 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
6207 {
6208 if(pAdapter->aStaInfo[i].isUsed)
6209 {
6210 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
6211 hddLog(VOS_TRACE_LEVEL_INFO,
6212 "%s: Delete STA with MAC::"
6213 "%02x:%02x:%02x:%02x:%02x:%02x",
6214 __func__,
6215 macAddr[0], macAddr[1], macAddr[2],
6216 macAddr[3], macAddr[4], macAddr[5]);
6217 hdd_softap_sta_deauth(pAdapter, macAddr);
6218 }
6219 }
6220 }
6221 else
6222 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006223
6224 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
6225 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6226 {
6227 hddLog(VOS_TRACE_LEVEL_INFO,
6228 "%s: Skip this DEL STA as this is not used::"
6229 "%02x:%02x:%02x:%02x:%02x:%02x",
6230 __func__,
6231 mac[0], mac[1], mac[2],
6232 mac[3], mac[4], mac[5]);
6233 return -ENOENT;
6234 }
6235
6236 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
6237 {
6238 hddLog(VOS_TRACE_LEVEL_INFO,
6239 "%s: Skip this DEL STA as deauth is in progress::"
6240 "%02x:%02x:%02x:%02x:%02x:%02x",
6241 __func__,
6242 mac[0], mac[1], mac[2],
6243 mac[3], mac[4], mac[5]);
6244 return -ENOENT;
6245 }
6246
6247 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
6248
Jeff Johnson295189b2012-06-20 16:38:30 -07006249 hddLog(VOS_TRACE_LEVEL_INFO,
6250 "%s: Delete STA with MAC::"
6251 "%02x:%02x:%02x:%02x:%02x:%02x",
6252 __func__,
6253 mac[0], mac[1], mac[2],
6254 mac[3], mac[4], mac[5]);
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006255
6256 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
6257 if (!VOS_IS_STATUS_SUCCESS(vos_status))
6258 {
6259 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
6260 hddLog(VOS_TRACE_LEVEL_INFO,
6261 "%s: STA removal failed for ::"
6262 "%02x:%02x:%02x:%02x:%02x:%02x",
6263 __func__,
6264 mac[0], mac[1], mac[2],
6265 mac[3], mac[4], mac[5]);
6266 return -ENOENT;
6267 }
6268
Jeff Johnson295189b2012-06-20 16:38:30 -07006269 }
6270 }
6271
6272 EXIT();
6273
6274 return 0;
6275}
6276
6277static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
6278 struct net_device *dev, u8 *mac, struct station_parameters *params)
6279{
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006280#ifdef FEATURE_WLAN_TDLS
6281 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6282 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6283 u32 mask, set;
6284 VOS_STATUS status;
Jeff Johnsone7245742012-09-05 17:12:55 -07006285 ENTER();
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006286
6287 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6288 {
6289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6290 "Invalid arguments");
6291 return -EINVAL;
6292 }
6293
6294 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6295 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6296 {
6297 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6298 "TDLS Disabled in INI OR not enabled in FW.\
6299 Cannot process TDLS commands \n");
6300 return -ENOTSUPP;
6301 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006302 /* first to check if we reached to maximum supported TDLS peer.
6303 TODO: for now, return -EPERM looks working fine,
6304 but need to check if any other errno fit into this category.*/
6305 if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
6306 {
6307 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6308 "%s: TDLS Max peer already connected. Request declined. \n",
6309 __func__);
6310 return -EPERM;
6311 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006312
6313 mask = params->sta_flags_mask;
6314
6315 set = params->sta_flags_set;
6316
6317
Lee Hoonkic1262f22013-01-24 21:59:00 -08006318 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6319 "%s: mask 0x%x set 0x%x\n",__func__, mask, set);
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006320
6321 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6322 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6324 "Add TDLS peer");
6325
6326
6327 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6328 pAdapter->sessionId, mac);
6329
6330 if (VOS_STATUS_SUCCESS != status) {
6331 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6332 "%s: sme_AddTdlsPeerSta failed!", __func__);
6333 }
6334 }
6335 }
6336#endif
6337
Jeff Johnson295189b2012-06-20 16:38:30 -07006338 return 0;
6339}
6340
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006341
6342#ifdef FEATURE_WLAN_LFR
6343static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006344 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006345{
6346#define MAX_PMKSAIDS_IN_CACHE 8
6347 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -07006348 static tANI_U32 i; // HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006349 tANI_U32 j=0;
6350 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6351 tHalHandle halHandle;
6352 eHalStatus result;
6353 tANI_U8 BSSIDMatched = 0;
6354
Jeff Johnsone7245742012-09-05 17:12:55 -07006355 ENTER();
6356
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006357 // Validate pAdapter
6358 if ( NULL == pAdapter || NULL == pAdapter->pHddCtx)
6359 {
6360 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__);
6361 return -EINVAL;
6362 }
6363
6364 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
6365 {
6366 hddLog( LOGE,
6367 "%s: Wlan Load/Unload is in progress", __func__);
6368 return -EBUSY;
6369 }
6370
6371 if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress )
6372 {
6373 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6374 "%s:LOGP in Progress. Ignore!!!", __func__);
6375 return -EAGAIN;
6376 }
6377
6378 // Retrieve halHandle
6379 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
6380
6381 for (j = 0; j < i; j++)
6382 {
6383 if(vos_mem_compare(PMKIDCache[j].BSSID,
6384 pmksa->bssid, WNI_CFG_BSSID_LEN))
6385 {
6386 /* BSSID matched previous entry. Overwrite it. */
6387 BSSIDMatched = 1;
6388 vos_mem_copy(PMKIDCache[j].BSSID,
6389 pmksa->bssid, WNI_CFG_BSSID_LEN);
6390 vos_mem_copy(PMKIDCache[j].PMKID,
6391 pmksa->pmkid,
6392 CSR_RSN_PMKID_SIZE);
6393 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006394 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006395 dump_bssid(pmksa->bssid);
6396 dump_pmkid(halHandle, pmksa->pmkid);
6397 break;
6398 }
6399 }
6400
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -07006401 /* Check we compared all entries,if then take the first slot now */
6402 if(j == MAX_PMKSAIDS_IN_CACHE) i=0;
6403
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006404 if (!BSSIDMatched)
6405 {
6406 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
6407 vos_mem_copy(PMKIDCache[i].BSSID,
6408 pmksa->bssid, ETHER_ADDR_LEN);
6409 vos_mem_copy(PMKIDCache[i].PMKID,
6410 pmksa->pmkid,
6411 CSR_RSN_PMKID_SIZE);
6412 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006413 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006414 dump_bssid(pmksa->bssid);
6415 dump_pmkid(halHandle, pmksa->pmkid);
6416 // Increment the HDD Local Cache index
6417 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
6418 if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0;
6419 }
6420
6421
6422 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
6423 //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."),
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006424 // __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006425 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006426 __func__, i );
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006427 // Finally set the PMKSA ID Cache in CSR
6428 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
6429 PMKIDCache,
6430 i );
6431 return 0;
6432}
6433
6434
6435static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -07006436 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006437{
Jeff Johnsone7245742012-09-05 17:12:55 -07006438 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006439 // TODO: Implement this later.
6440 return 0;
6441}
6442
6443static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6444{
Jeff Johnsone7245742012-09-05 17:12:55 -07006445 ENTER();
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006446 // TODO: Implement this later.
6447 return 0;
6448}
6449#endif
6450
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006451#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6452static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
6453 struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie)
6454{
6455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6456 hdd_station_ctx_t *pHddStaCtx;
6457
6458 if (NULL == pAdapter)
6459 {
6460 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__);
6461 return -ENODEV;
6462 }
6463
6464 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6465
6466 // Added for debug on reception of Re-assoc Req.
6467 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6468 {
6469 hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"),
6470 ftie->ie_len);
6471 hddLog(LOGE, FL("Should be Re-assoc Req IEs\n"));
6472 }
6473
6474#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
6475 hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__,
6476 ftie->ie_len);
6477#endif
6478
6479 // Pass the received FT IEs to SME
6480 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, ftie->ie,
6481 ftie->ie_len);
6482 return 0;
6483}
6484#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006485
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006486#ifdef FEATURE_WLAN_TDLS
6487static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
6488 u8 *peer, u8 action_code, u8 dialog_token,
6489 u16 status_code, const u8 *buf, size_t len)
6490{
6491
6492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6493 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6494 u8 *buf_1;
6495 size_t len_1 = len;
6496 u8 peerMac[6];
6497 VOS_STATUS status;
6498
6499 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6500 {
6501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6502 "Invalid arguments");
6503 return -EINVAL;
6504 }
6505
6506 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
6507 FALSE == sme_IsFeatureSupportedByFW(TDLS))
6508 {
6509 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6510 "TDLS Disabled in INI OR not enabled in FW.\
6511 Cannot process TDLS commands \n");
6512 return -ENOTSUPP;
6513 }
Lee Hoonkic1262f22013-01-24 21:59:00 -08006514
6515 if(SIR_MAC_TDLS_SETUP_REQ == action_code ||
6516 SIR_MAC_TDLS_SETUP_RSP == action_code )
6517 {
6518 if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
6519 {
6520 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
6521 we return error code at 'add_station()'. Hence we have this
6522 check again in addtion to add_station().
6523 Anyway, there is no hard to double-check. */
6524 if(SIR_MAC_TDLS_SETUP_REQ == action_code)
6525 {
6526 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6527 "%s: TDLS Max peer already connected. Request declined. \n",
6528 __func__);
6529 return -EPERM;
6530 }
6531 else
6532 {
6533 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
6534 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6535 "%s: TDLS Max peer already connected send response status %d \n",
6536 __func__,status_code);
6537 }
6538 }
6539 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006540 vos_mem_copy( peerMac, peer, 6);
6541
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006542#ifdef WLAN_FEATURE_TDLS_DEBUG
6543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6544 "%s: %02x:%02x:%02x:%02x:%02x:%02x) action %d, dialog_token %d status %d, len = %d",
6545 "tdls_mgmt", peer[0], peer[1], peer[2], peer[3], peer[4], peer[5],
6546 action_code, dialog_token, status_code, len);
6547#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006548
6549 buf_1 = vos_mem_malloc(len);
6550 if(buf_1 == NULL) {
6551 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6552 "%s: malloc failed!", __func__);
6553 return -ENOMEM;
6554 }
6555 vos_mem_copy(buf_1, buf, len);
6556
6557 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
6558 peerMac, action_code, dialog_token, status_code, buf_1, len_1);
6559
6560 if (VOS_STATUS_SUCCESS != status) {
6561 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6562 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
6563 }
6564
6565 vos_mem_free(buf_1);
6566
6567 return 0;
6568}
6569
6570static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
6571 u8 *peer, enum nl80211_tdls_operation oper)
6572{
6573 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6574 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006575#ifdef WLAN_FEATURE_TDLS_DEBUG
6576 const char *tdls_oper_str[]= {
6577 "NL80211_TDLS_DISCOVERY_REQ",
6578 "NL80211_TDLS_SETUP",
6579 "NL80211_TDLS_TEARDOWN",
6580 "NL80211_TDLS_ENABLE_LINK",
6581 "NL80211_TDLS_DISABLE_LINK",
6582 "NL80211_TDLS_UNKONW_OPER"};
6583#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006584
6585 if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
6586 {
6587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6588 "Invalid arguments");
6589 return -EINVAL;
6590 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006591
6592#ifdef WLAN_FEATURE_TDLS_DEBUG
6593 if((int)oper > 4)
6594 oper = 5;
6595
6596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6597 "%s: %02x:%02x:%02x:%02x:%02x:%02x: %d (%s) ", "tdls_oper",
6598 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5], (int)oper,
6599 tdls_oper_str[(int)oper]);
6600#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006601
6602 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006603 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006604 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006606 "TDLS Disabled in INI OR not enabled in FW.\
6607 Cannot process TDLS commands \n");
6608 return -ENOTSUPP;
6609 }
6610
6611 switch (oper) {
6612 case NL80211_TDLS_ENABLE_LINK:
6613 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08006614 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006615 v_U8_t my_peer[6];
6616 v_U8_t ucSTAId;
6617 VOS_STATUS status;
6618
6619 if (peer) {
6620 vos_mem_copy(my_peer, peer, 6);
6621 ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
6622
6623 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6624 "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
6625 __func__, peer[0], peer[1],
6626 peer[2], peer[3],
6627 peer[4], peer[5] );
6628
6629 if (-1 == ucSTAId ) {
6630 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
Hoonki Leef63df0d2013-01-16 19:29:14 -08006631 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006632 }
6633
6634 status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
6635 WLANTL_STA_AUTHENTICATED );
6636
Hoonki Leef63df0d2013-01-16 19:29:14 -08006637 //This can fail only if the staId is not registered yet with TL
6638 //return -EINVAL in such case.
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006639 if (0 != status) {
6640 hddLog(VOS_TRACE_LEVEL_ERROR,
6641 "%s: WLANTL_ChangeSTAState failed, returned %d",
6642 __func__, status);
Hoonki Leef63df0d2013-01-16 19:29:14 -08006643 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006644 }
Hoonki Leef63df0d2013-01-16 19:29:14 -08006645
Chilam NG571c65a2013-01-19 12:27:36 +05306646 wlan_hdd_tdls_set_link_status(peer, eTDLS_LINK_CONNECTED);
6647
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006648 } else {
6649 hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
6650 }
6651 }
6652 break;
6653 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -08006654 {
6655 if(-1 != wlan_hdd_findTdlsPeer(peer))
6656 {
6657 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
6658 pAdapter->sessionId, peer );
6659 }
6660 else
6661 {
6662 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6663 "%s: TDLS Peer Station doesn't exist \n",__func__);
6664 }
6665 return 0;
6666 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006667 case NL80211_TDLS_TEARDOWN:
6668 case NL80211_TDLS_SETUP:
6669 case NL80211_TDLS_DISCOVERY_REQ:
6670 /* We don't support in-driver setup/teardown/discovery */
6671 return -ENOTSUPP;
6672 default:
6673 return -ENOTSUPP;
6674 }
6675 return 0;
6676}
Chilam NG571c65a2013-01-19 12:27:36 +05306677
6678int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
6679 struct net_device *dev, u8 *peer)
6680{
6681 hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
6682 peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
6683
6684 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
6685 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
6686}
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006687#endif
6688
Jeff Johnson295189b2012-06-20 16:38:30 -07006689/* cfg80211_ops */
6690static struct cfg80211_ops wlan_hdd_cfg80211_ops =
6691{
6692 .add_virtual_intf = wlan_hdd_add_virtual_intf,
6693 .del_virtual_intf = wlan_hdd_del_virtual_intf,
6694 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
6695 .change_station = wlan_hdd_change_station,
6696#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6697 .add_beacon = wlan_hdd_cfg80211_add_beacon,
6698 .del_beacon = wlan_hdd_cfg80211_del_beacon,
6699 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006700#else
6701 .start_ap = wlan_hdd_cfg80211_start_ap,
6702 .change_beacon = wlan_hdd_cfg80211_change_beacon,
6703 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -07006704#endif
6705 .change_bss = wlan_hdd_cfg80211_change_bss,
6706 .add_key = wlan_hdd_cfg80211_add_key,
6707 .get_key = wlan_hdd_cfg80211_get_key,
6708 .del_key = wlan_hdd_cfg80211_del_key,
6709 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006710#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07006711 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08006712#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006713 .scan = wlan_hdd_cfg80211_scan,
6714 .connect = wlan_hdd_cfg80211_connect,
6715 .disconnect = wlan_hdd_cfg80211_disconnect,
6716 .join_ibss = wlan_hdd_cfg80211_join_ibss,
6717 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
6718 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
6719 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
6720 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
6721#ifdef WLAN_FEATURE_P2P
6722 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
6723 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
6724 .mgmt_tx = wlan_hdd_action,
6725#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6726 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
6727 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
6728 .set_txq_params = wlan_hdd_set_txq_params,
6729#endif
6730#endif
6731 .get_station = wlan_hdd_cfg80211_get_station,
6732 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
6733 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006734 .add_station = wlan_hdd_cfg80211_add_station,
6735#ifdef FEATURE_WLAN_LFR
6736 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
6737 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
6738 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
6739#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07006740#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
6741 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
6742#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08006743#ifdef FEATURE_WLAN_TDLS
6744 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
6745 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
6746#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006747};
6748
6749#endif // CONFIG_CFG80211